//----------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- package chalice; import java.io.BufferedReader import java.io.InputStreamReader import java.io.File import java.io.FileWriter import scala.util.parsing.input.Position import scala.util.parsing.input.NoPosition import collection.mutable.ListBuffer object Chalice { /** * Reporting options */ private[chalice] var vsMode = false; private[chalice] var rise4funMode = false; private[chalice] var InputFilename = ""; // the name of the last input file mentioned on the command line, or "" if none /** * Translation options */ // level 0 or below: no defaults // level 1: unfold predicates with receiver this in pre and postconditions // level 2: unfold predicates and functions with receiver this in pre and postconditions // level 3 or above: level 2 + autoMagic\ private[chalice] var defaults = 0: Int; private[chalice] var autoFold = false: Boolean; private[chalice] var checkLeaks = false: Boolean; private[chalice] var autoMagic = false: Boolean; private[chalice] var skipDeadlockChecks = false: Boolean; private[chalice] var skipTermination = false: Boolean; private[chalice] var noFreeAssume = false: Boolean; private[chalice] var percentageSupport = 0; private[chalice] var smoke = false; private[chalice] var smokeAll = false; private[chalice] var timingVerbosity = 1; /** * Holds all command line arguments not stored in fields of Chalice. * Can only be created parseCommandLine. */ sealed abstract class CommandLineParameters { val boogiePath: String val files: List[File] val printProgram: Boolean val doTypecheck: Boolean val doTranslate: Boolean val boogieArgs: String val gen: Boolean val showFullStackTrace: Boolean val noBplFile: Boolean val bplFile: String def getHelp(): String } def parseCommandLine(args: Array[String]): Option[CommandLineParameters] = { // help texts and closures for boolean command line options // closures should be idempotent import scala.collection.immutable.ListMap var aBoogiePath = "C:\\boogie\\Binaries\\Boogie.exe" val inputs = new ListBuffer[String]() var aPrintProgram = false var aDoTypecheck = true var aDoTranslate = true var aNoBplFile = true var aBplFile = "out.bpl" var aBoogieArgs = " " var aGen = false; var aShowFullStackTrace = false val options = ListMap[String,(() => Unit, String)]( "help" -> ( {() => }, "print this message"), "print" -> ({() => aNoBplFile = false},"output the Boogie program used for verification to 'out.bpl'"), "printIntermediate" -> ({() => aPrintProgram = true},"print intermediate versions of the Chalice program"), "noTranslate" -> ( {() => aDoTranslate = false}, "do not translate the program to Boogie (only parse and typecheck)"), "noTypecheck"-> ( {() => aDoTypecheck = false}, "do not typecheck the program (only parse). Implies /noTranslate."), "vs" -> ( {() => vsMode = true}, "Microsoft Visual Studio mode (special error reporting for Visual Studio; requires an existing, writable directory at C:\\tmp)"), "rise4fun" -> ( {() => rise4funMode = true}, "rise4fun mode (generates error messages in a format expected by the rise4fun harness"), "checkLeaks" -> ( {() => checkLeaks = true}, "(no description available)"), "noDeadlockChecks" -> ( {() => skipDeadlockChecks = true}, "skip all lock ordering checks"), "noTermination" -> ( {() => skipTermination = true}, "skip the termination checks for functions"), "defaults" -> ( {() => defaults = 3}, null), "gen" -> ( {() => aGen = true}, "generate C# code from the Chalice program"), "autoFold" -> ( {() => autoFold = true}, "automatically fold predicates whenever necessary"), "autoMagic" -> ( {() => autoMagic = true}, "automatically try to infer accessibility predicates and non-nullness checks in specifications"), "noFreeAssume" -> ( {() => noFreeAssume = true}, "(no description available)"), "showFullStackTrace" -> ( {() => aShowFullStackTrace = true}, "show the full stack trace if an exception is encountered"), "smoke" -> ( {() => smoke = true}, "smoke testing; try to find unreachable code, preconditions/invariants/predicates that are equivalent to false and assumptions that introduce contradictions, by trying to prove 'false' at various positions."), "smokeAll" -> ( {() => smokeAll = true; smoke = true}, "aggressive smoke testing; try to prove false after every statement."), "time" -> ( {() => timingVerbosity = 2}, "sets /time:2") ) // help text for options with arguments val nonBooleanOptions = ListMap( "boogie:" -> "use the executable of Boogie at ", "print:" -> "print the Boogie program used for verification into file ", "time:" -> ("output timing information\n"+ "0: no information is included\n"+ "1: the overall verification time is output (default)\n"+ "2: detailed timings for each phase of the verification are output\n"+ "3: (used for testing only) output the overall verification time on stderr"), "defaults:" -> ("defaults to reduce specification overhead\n"+ "level 0 or below: no defaults\n"+ "level 1: unfold predicates with receiver this in pre and postconditions\n"+ "level 2: unfold predicates and functions with receiver this in pre and postconditions\n"+ "level 3 or above: level 2 + autoMagic"), "percentageSupport:" -> ("determin how percentage permissions are translated to Boogie\n"+ "0: use multiplication directly (default)\n"+ "1: use a function and provide some (redundant) axioms")+ "boogieOpt:, /bo:" -> "specify additional Boogie options" ) lazy val help = { val maxLength = math.min((nonBooleanOptions.keys++options.keys).map(s => s.length+1).max,14) val printOptionHelp = (param: String, help: String) => "\n /" + param + (" "*(maxLength-param.length-1)) + ": " + help.split("\n").map(h => " "*(maxLength+2+2)+wordWrap(h, 80-2-2-math.max(maxLength,param.length+1)," "*(maxLength+2+2))).mkString("\n").substring(maxLength+2+2) "Chalice concurrent program verifier.\nUsage: chalice [option] +\n"+ " where