diff --git a/src/main/scala/gvc/Config.scala b/src/main/scala/gvc/Config.scala index 54ad4f4..21fced1 100644 --- a/src/main/scala/gvc/Config.scala +++ b/src/main/scala/gvc/Config.scala @@ -28,7 +28,7 @@ case class Config( onlyCompile: Boolean = false, onlyBenchmark: Boolean = false, onlyErrors: Boolean = false, - sourceFile: Option[String] = None, + sourceFiles: List[String] = List.empty, linkedLibraries: List[String] = List.empty, includeDirectories: List[String] = List.empty, versionString: Option[String] = None, @@ -52,15 +52,25 @@ case class Config( Some("Cannot combine --output and --only-verify") else if (exec && onlyVerify) Some("Cannot combine --exec and --only-verify") - else if (sourceFile.isEmpty && (mode == DefaultMode || mode == Describe || mode == CaseStudyMode)) + else if (sourceFiles.isEmpty && (mode == DefaultMode || mode == Describe || mode == CaseStudyMode)) Some("No source file specified") - else if (sourceFile.nonEmpty && !Files.exists(Paths.get(sourceFile.get))) - Some(s"Source file '${sourceFile.get}' does not exist") + else if (sourceFiles.nonEmpty) + sourceFiles.collectFirst { + case sourceFile if !Files.exists(Paths.get(sourceFile)) => + s"Source file '${sourceFile}' does not exist" + } else if (versionString.nonEmpty && versionString.get.trim.isEmpty) { Some(s"Invalid version string.") } else None ).foreach(Config.error) } + + def getSingleSourceFile(): String = { + if (sourceFiles.size > 1) { + Config.error("Cannot specify multiple input files") + } + sourceFiles.head + } } object Config { @@ -359,14 +369,10 @@ object Config { case other :: _ if other.startsWith("-") => error(s"Unrecognized command line argument: $other") case sourceFile :: tail => - current.sourceFile match { - case Some(_) => error("Cannot specify multiple input files") - case None => - fromCommandLineArgs( - tail, - current.copy(sourceFile = Some(sourceFile)) - ) - } + fromCommandLineArgs( + tail, + current.copy(sourceFiles = sourceFile :: current.sourceFiles) + ) case Nil => current } diff --git a/src/main/scala/gvc/benchmarking/BenchmarkExternalConfig.scala b/src/main/scala/gvc/benchmarking/BenchmarkExternalConfig.scala index 2191c23..9c292d6 100644 --- a/src/main/scala/gvc/benchmarking/BenchmarkExternalConfig.scala +++ b/src/main/scala/gvc/benchmarking/BenchmarkExternalConfig.scala @@ -253,9 +253,10 @@ object BenchmarkExternalConfig { p.getName.endsWith(".c0") }) .map(_.toPath) - val fileCollection = rootConfig.sourceFile match { - case Some(value) => c0SourceFiles ++ List(Paths.get(value)) - case None => c0SourceFiles + val fileCollection = rootConfig.sourceFiles match { + case List(value) => c0SourceFiles ++ List(Paths.get(value)) + case List() => c0SourceFiles + case _ => Config.error("Cannot specify multiple input files") } val outputDir = benchmarkRoot \ "output-dir" diff --git a/src/main/scala/gvc/main.scala b/src/main/scala/gvc/main.scala index 7e9248d..6b1f599 100644 --- a/src/main/scala/gvc/main.scala +++ b/src/main/scala/gvc/main.scala @@ -87,8 +87,8 @@ object Main extends App { BenchmarkMonitor.monitor(benchConfig) case Config.DynamicVerification | Config.FramingVerification => Output.printTiming(() => { - val fileNames = getOutputCollection(config.sourceFile.get) - val inputSource = readFile(config.sourceFile.get) + val fileNames = getOutputCollection(config.getSingleSourceFile()) + val inputSource = readFile(config.getSingleSourceFile()) val onlyFraming = config.mode == Config.FramingVerification val ir = generateIR(inputSource, linkedLibraries) BaselineChecker.check(ir, onlyFraming) @@ -159,38 +159,40 @@ object Main extends App { BenchmarkExternalConfig.parsePopulator(config) BenchmarkPopulator.populate(benchConfig, linkedLibraries) case Config.Describe => - val inputSource = readFile(config.sourceFile.get) + val inputSource = readFile(config.getSingleSourceFile()) val sourceIR = Main.generateIR(inputSource, linkedLibraries) val visitor = new LabelVisitor() val labelOutput = visitor.visit(sourceIR) visitor.printCounts(labelOutput.labels) case Config.DefaultMode => - val fileNames = getOutputCollection(config.sourceFile.get) - val inputSource = readFile(config.sourceFile.get) - Output.printTiming(() => { - val verifiedOutput = verify(inputSource, fileNames, cmdConfig) - execute(verifiedOutput.c0Source, fileNames) - }) + for (sourceFile <- config.sourceFiles.reverse) { + val fileNames = getOutputCollection(sourceFile) + val inputSource = readFile(sourceFile) + Output.printTiming(() => { + val verifiedOutput = verify(inputSource, fileNames, cmdConfig) + execute(verifiedOutput.c0Source, fileNames) + }) + } case Config.CaseStudyMode => { - val fileNames = getOutputCollection(config.sourceFile.get) - val inputSource = readFile(config.sourceFile.get) + val fileNames = getOutputCollection(config.getSingleSourceFile()) + val inputSource = readFile(config.getSingleSourceFile()) val caseName = fileNames.baseName.split("/").last // create new dir for collected data and files val localTime = java.time.LocalDateTime.now() val outputDir = Paths.get("").toAbsolutePath.toString + "/" + caseName + "-" + localTime + "/" - val newSourceFile = outputDir + config.sourceFile.get.split("/").last + val newSourceFile = outputDir + config.getSingleSourceFile().split("/").last val fileNames2 = getOutputCollection(newSourceFile) val caseConfig = new Config( mode = Config.CaseStudyMode, saveFiles = true, exec = true, - sourceFile = config.sourceFile, + sourceFiles = config.sourceFiles, linkedLibraries = config.linkedLibraries, includeDirectories = config.includeDirectories, ) - println(Output.purple("Verifying '" + config.sourceFile.get + "' and gathering data.")) + println(Output.purple("Verifying '" + config.getSingleSourceFile() + "' and gathering data.")) println(Output.purple("Outputting collected data to " + outputDir)) writeDir(outputDir) writeFile(newSourceFile, inputSource) @@ -464,8 +466,6 @@ object Main extends App { if (cmdConfig.exec) { val outputCommand = Paths.get(outputExe).toAbsolutePath.toString sys.exit(Seq(outputCommand) !) - } else { - sys.exit(0) } } }