# # # The Nim Compiler # (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # # This module handles the parsing of command line arguments. # We do this here before the 'import' statement so 'defined' does not get # confused with 'TGCMode.gcGenerational' etc. template bootSwitch(name, expr, userString) = # Helper to build boot constants, for debugging you can 'echo' the else part. const name = if expr: " " & userString else: "" bootSwitch(usedRelease, defined(release), "-d:release") bootSwitch(usedGnuReadline, defined(useLinenoise), "-d:useLinenoise") bootSwitch(usedNoCaas, defined(noCaas), "-d:noCaas") bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm") bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep") bootSwitch(usedGenerational, defined(gcgenerational), "--gc:generational") bootSwitch(usedGoGC, defined(gogc), "--gc:go") bootSwitch(usedNoGC, defined(nogc), "--gc:none") import os, msgs, options, nversion, condsyms, strutils, extccomp, platform, wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils # but some have deps to imported modules. Yay. bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc") bootSwitch(usedAvoidTimeMachine, noTimeMachine, "-d:avoidTimeMachine") bootSwitch(usedNativeStacktrace, defined(nativeStackTrace) and nativeStackTraceSupported, "-d:nativeStackTrace") bootSwitch(usedFFI, hasFFI, "-d:useFFI") proc writeCommandLineUsage*() type TCmdLinePass* = enum passCmd1, # first pass over the command line passCmd2, # second pass over the command line passPP # preprocessor called processCommand() proc processCommand*(switch: string, pass: TCmdLinePass) proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; config: ConfigRef = nil) # implementation const HelpMessage = "Nim Compiler Version $1 [$2: $3]\n" & "Copyright (c) 2006-" & copyrightYear & " by Andreas Rumpf\n" const Usage = slurp"../doc/basicopt.txt".replace("//", "") AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") proc getCommandLineDesc(): string = result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name, CPU[platform.hostCPU].name]) & Usage proc helpOnError(pass: TCmdLinePass) = if pass == passCmd1: msgWriteln(getCommandLineDesc(), {msgStdout}) msgQuit(0) proc writeAdvancedUsage(pass: TCmdLinePass) = if pass == passCmd1: msgWriteln(`%`(HelpMessage, [VersionAsString, platform.OS[platform.hostOS].name, CPU[platform.hostCPU].name]) & AdvancedUsage, {msgStdout}) msgQuit(0) proc writeVersionInfo(pass: TCmdLinePass) = if pass == passCmd1: msgWriteln(`%`(HelpMessage, [VersionAsString, platform.OS[platform.hostOS].name, CPU[platform.hostCPU].name]), {msgStdout}) const gitHash = gorge("git log -n 1 --format=%H").strip when gitHash.len == 40: msgWriteln("git hash: " & gitHash, {msgStdout}) msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine & usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas & usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC, {msgStdout}) msgQuit(0) var helpWritten: bool proc writeCommandLineUsage() = if not helpWritten: msgWriteln(getCommandLineDesc(), {msgStdout}) helpWritten = true proc addPrefix(switch: string): string = if len(switch) == 1: result = "-" & switch else: result = "--" & switch proc invalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) = if switch == " ": localError(info, errInvalidCmdLineOption, "-") else: localError(info, errInvalidCmdLineOption, addPrefix(switch)) proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass, info: TLineInfo) = cmd = "" var i = 0 if i < len(switch) and switch[i] == '-': inc(i) if i < len(switch) and switch[i] == '-': inc(i) while i < len(switch): case switch[i] of 'a'..'z', 'A'..'Z', '0'..'9', '_', '.': add(cmd, switch[i]) else: break inc(i) if i >= len(switch): arg = "" elif switch[i] in {':', '=', '['}: arg = substr(switch, i + 1) else: invalidCmdLineOption(pass, switch, info) proc processOnOffSwitch(op: TOptions, arg: string, pass: TCmdLinePass, info: TLineInfo) = case arg.normalize of "on": gOptions = gOptions + op of "off": gOptions = gOptions - op else: localError(info, errOnOrOffExpectedButXFound, arg) proc processOnOffSwitchOrList(op: TOptions, arg: string, pass: TCmdLinePass, info: TLineInfo): bool = result = false case arg.normalize of "on": gOptions = gOptions + op of "off": gOptions = gOptions - op else: if arg == "list": result = true else: localError(info, errOnOffOrListExpectedButXFound, arg) proc processOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdLinePass, info: TLineInfo) = case arg.normalize of "on": gGlobalOptions = gGlobalOptions + op of "off": gGlobalOptions = gGlobalOptions - op else: localError(info, errOnOrOffExpectedButXFound, arg) proc expectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = if arg == "": localError(info, errCmdLineArgExpected, addPrefix(switch)) proc expectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = if arg != "": localError(info, errCmdLineNoArgExpected, addPrefix(switch)) var enableNotes: TNoteKinds disableNotes: TNoteKinds proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass, info: TLineInfo; orig: string) = var id = "" # arg = "X]:on|off" var i = 0 var n = hintMin while i < len(arg) and (arg[i] != ']'): add(id, arg[i]) inc(i) if i < len(arg) and (arg[i] == ']'): inc(i) else: invalidCmdLineOption(pass, orig, info) if i < len(arg) and (arg[i] in {':', '='}): inc(i) else: invalidCmdLineOption(pass, orig, info) if state == wHint: var x = findStr(msgs.HintsToStr, id) if x >= 0: n = TNoteKind(x + ord(hintMin)) else: localError(info, "unknown hint: " & id) else: var x = findStr(msgs.WarningsToStr, id) if x >= 0: n = TNoteKind(x + ord(warnMin)) else: localError(info, "unknown warning: " & id) case substr(arg, i).normalize of "on": incl(gNotes, n) incl(gMainPackageNotes, n) incl(enableNotes, n) of "off": excl(gNotes, n) excl(gMainPackageNotes, n) incl(disableNotes, n) excl(ForeignPackageNotes, n) else: localError(info, errOnOrOffExpectedButXFound, arg) proc processCompile(filename: string) = var found = findFile(filename) if found == "": found = filename extccomp.addExternalFileToCompile(found) proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool = case switch.normalize of "gc": case arg.normalize of "boehm": result = gSelectedGC == gcBoehm of "refc": result = gSelectedGC == gcRefc of "v2": result = gSelectedGC == gcV2 of "markandsweep": result = gSelectedGC == gcMarkAndSweep of "generational": result = gSelectedGC == gcGenerational of "go": result = gSelectedGC == gcGo of "none": result = gSelectedGC == gcNone of "stack", "regions": result = gSelectedGC == gcRegions else: localError(info, errNoneBoehmRefcExpectedButXFound, arg) of "opt": case arg.normalize of "speed": result = contains(gOptions, optOptimizeSpeed) of "size": result = contains(gOptions, optOptimizeSize) of "none": result = gOptions * {optOptimizeSpeed, optOptimizeSize} == {} else: localError(info, errNoneSpeedOrSizeExpectedButXFound, arg) of "verbosity": result = $gVerbosity == arg of "app": case arg.normalize of "gui": result = contains(gGlobalOptions, optGenGuiApp) of "console": result = not contains(gGlobalOptions, optGenGuiApp) of "lib": result = contains(gGlobalOptions, optGenDynLib) and not contains(gGlobalOptions, optGenGuiApp) of "staticlib": result = contains(gGlobalOptions, optGenStaticLib) and not contains(gGlobalOptions, optGenGuiApp) else: localError(info, errGuiConsoleOrLibExpectedButXFound, arg) of "dynliboverride": result = isDynlibOverride(arg) else: invalidCmdLineOption(passCmd1, switch, info) proc testCompileOption*(switch: string, info: TLineInfo): bool = case switch.normalize of "debuginfo": result = contains(gGlobalOptions, optCDebug) of "compileonly", "c": result = contains(gGlobalOptions, optCompileOnly) of "nolinking": result = contains(gGlobalOptions, optNoLinking) of "nomain": result = contains(gGlobalOptions, optNoMain) of "forcebuild", "f": result = contains(gGlobalOptions, optForceFullMake) of "warnings", "w": result = contains(gOptions, optWarns) of "hints": result = contains(gOptions, optHints) of "threadanalysis": result = contains(gGlobalOptions, optThreadAnalysis) of "stacktrace": result = contains(gOptions, optStackTrace) of "linetrace": result = contains(gOptions, optLineTrace) of "debugger": result = contains(gOptions, optEndb) of "profiler": result = contains(gOptions, optProfiler) of "memtracker": result = contains(gOptions, optMemTracker) of "checks", "x": result = gOptions * ChecksOptions == ChecksOptions of "floatchecks": result = gOptions * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck} of "infchecks": result = contains(gOptions, optInfCheck) of "nanchecks": result = contains(gOptions, optNaNCheck) of "nilchecks": result = contains(gOptions, optNilCheck) of "objchecks": result = contains(gOptions, optObjCheck) of "fieldchecks": result = contains(gOptions, optFieldCheck) of "rangechecks": result = contains(gOptions, optRangeCheck) of "boundchecks": result = contains(gOptions, optBoundsCheck) of "overflowchecks": result = contains(gOptions, optOverflowCheck) of "linedir": result = contains(gOptions, optLineDir) of "assertions", "a": result = contains(gOptions, optAssert) of "deadcodeelim": result = contains(gGlobalOptions, optDeadCodeElim) of "run", "r": result = contains(gGlobalOptions, optRun) of "symbolfiles": result = gSymbolFiles != disabledSf of "genscript": result = contains(gGlobalOptions, optGenScript) of "threads": result = contains(gGlobalOptions, optThreads) of "taintmode": result = contains(gGlobalOptions, optTaintMode) of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation) of "implicitstatic": result = contains(gOptions, optImplicitStatic) of "patterns": result = contains(gOptions, optPatterns) of "experimental": result = gExperimentalMode of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace) else: invalidCmdLineOption(passCmd1, switch, info) proc processPath(path: string, info: TLineInfo, notRelativeToProj = false): string = let p = if notRelativeToProj or os.isAbsolute(path) or '$' in path: path else: options.gProjectPath / path try: result = pathSubs(p, info.toFullPath().splitFile().dir) except ValueError: localError(info, "invalid path: " & p) result = p proc processCfgPath(path: string, info: TLineInfo): string = let path = if path[0] == '"': strutils.unescape(path) else: path let basedir = info.toFullPath().splitFile().dir let p = if os.isAbsolute(path) or '$' in path: path else: basedir / path try: result = pathSubs(p, basedir) except ValueError: localError(info, "invalid path: " & p) result = p proc trackDirty(arg: string, info: TLineInfo) = var a = arg.split(',') if a.len != 4: localError(info, errTokenExpected, "DIRTY_BUFFER,ORIGINAL_FILE,LINE,COLUMN") var line, column: int if parseUtils.parseInt(a[2], line) <= 0: localError(info, errInvalidNumber, a[1]) if parseUtils.parseInt(a[3], column) <= 0: localError(info, errInvalidNumber, a[2]) let dirtyOriginalIdx = a[1].fileInfoIdx if dirtyOriginalIdx >= 0: msgs.setDirtyFile(dirtyOriginalIdx, a[0]) gTrackPos = newLineInfo(dirtyOriginalIdx, line, column) proc track(arg: string, info: TLineInfo) = var a = arg.split(',') if a.len != 3: localError(info, errTokenExpected, "FILE,LINE,COLUMN") var line, column: int if parseUtils.parseInt(a[1], line) <= 0: localError(info, errInvalidNumber, a[1]) if parseUtils.parseInt(a[2], column) <= 0: localError(info, errInvalidNumber, a[2]) gTrackPos = newLineInfo(a[0], line, column) proc dynlibOverride(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = if pass in {passCmd2, passPP}: expectArg(switch, arg, pass, info) options.inclDynlibOverride(arg) proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; config: ConfigRef = nil) = var theOS: TSystemOS cpu: TSystemCPU key, val: string case switch.normalize of "path", "p": expectArg(switch, arg, pass, info) addPath(if pass == passPP: processCfgPath(arg, info) else: processPath(arg, info), info) of "nimblepath", "babelpath": # keep the old name for compat if pass in {passCmd2, passPP} and not options.gNoNimblePath: expectArg(switch, arg, pass, info) var path = processPath(arg, info, notRelativeToProj=true) let nimbleDir = getEnv("NIMBLE_DIR") if nimbleDir.len > 0 and pass == passPP: path = nimbleDir / "pkgs" nimblePath(path, info) of "nonimblepath", "nobabelpath": expectNoArg(switch, arg, pass, info) disableNimblePath() of "excludepath": expectArg(switch, arg, pass, info) let path = processPath(arg, info) options.searchPaths.keepItIf( cmpPaths(it, path) != 0 ) options.lazyPaths.keepItIf( cmpPaths(it, path) != 0 ) if (len(path) > 0) and (path[len(path) - 1] == DirSep): let strippedPath = path[0 .. (len(path) - 2)] options.searchPaths.keepItIf( cmpPaths(it, strippedPath) != 0 ) options.lazyPaths.keepItIf( cmpPaths(it, strippedPath) != 0 ) of "nimcache": expectArg(switch, arg, pass, info) options.nimcacheDir = processPath(arg, info, true) of "out", "o": expectArg(switch, arg, pass, info) options.outFile = arg of "docseesrcurl": expectArg(switch, arg, pass, info) options.docSeeSrcUrl = arg of "mainmodule", "m": discard "allow for backwards compatibility, but don't do anything" of "define", "d": expectArg(switch, arg, pass, info) if {':', '='} in arg: splitSwitch(arg, key, val, pass, info) defineSymbol(key, val) else: defineSymbol(arg) of "undef", "u": expectArg(switch, arg, pass, info) undefSymbol(arg) of "symbol": expectArg(switch, arg, pass, info) # deprecated, do nothing of "compile": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: processCompile(arg) of "link": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: addExternalFileToLink(arg) of "debuginfo": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optCDebug) of "embedsrc": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optEmbedOrigSrc) of "compileonly", "c": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optCompileOnly) of "nolinking": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optNoLinking) of "nomain": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optNoMain) of "forcebuild", "f": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optForceFullMake) of "project": expectNoArg(switch, arg, pass, info) gWholeProject = true of "gc": expectArg(switch, arg, pass, info) case arg.normalize of "boehm": gSelectedGC = gcBoehm defineSymbol("boehmgc") of "refc": gSelectedGC = gcRefc of "v2": gSelectedGC = gcV2 of "markandsweep": gSelectedGC = gcMarkAndSweep defineSymbol("gcmarkandsweep") of "generational": gSelectedGC = gcGenerational defineSymbol("gcgenerational") of "go": gSelectedGC = gcGo defineSymbol("gogc") of "none": gSelectedGC = gcNone defineSymbol("nogc") of "stack", "regions": gSelectedGC= gcRegions defineSymbol("gcregions") else: localError(info, errNoneBoehmRefcExpectedButXFound, arg) of "warnings", "w": if processOnOffSwitchOrList({optWarns}, arg, pass, info): listWarnings() of "warning": processSpecificNote(arg, wWarning, pass, info, switch) of "hint": processSpecificNote(arg, wHint, pass, info, switch) of "hints": if processOnOffSwitchOrList({optHints}, arg, pass, info): listHints() of "threadanalysis": processOnOffSwitchG({optThreadAnalysis}, arg, pass, info) of "stacktrace": processOnOffSwitch({optStackTrace}, arg, pass, info) of "excessivestacktrace": processOnOffSwitchG({optExcessiveStackTrace}, arg, pass, info) of "linetrace": processOnOffSwitch({optLineTrace}, arg, pass, info) of "debugger": case arg.normalize of "on", "endb": gOptions.incl optEndb defineSymbol("endb") of "off": gOptions.excl optEndb undefSymbol("endb") of "native", "gdb": incl(gGlobalOptions, optCDebug) gOptions = gOptions + {optLineDir} - {optEndb} defineSymbol("nimTypeNames", nil) # type names are used in gdb pretty printing undefSymbol("endb") else: localError(info, "expected endb|gdb but found " & arg) of "profiler": processOnOffSwitch({optProfiler}, arg, pass, info) if optProfiler in gOptions: defineSymbol("profiler") else: undefSymbol("profiler") of "memtracker": processOnOffSwitch({optMemTracker}, arg, pass, info) if optMemTracker in gOptions: defineSymbol("memtracker") else: undefSymbol("memtracker") of "oldnewlines": case arg.normalize of "on": options.gOldNewlines = true defineSymbol("nimOldNewlines") of "off": options.gOldNewlines = false undefSymbol("nimOldNewlines") else: localError(info, errOnOrOffExpectedButXFound, arg) of "checks", "x": processOnOffSwitch(ChecksOptions, arg, pass, info) of "floatchecks": processOnOffSwitch({optNaNCheck, optInfCheck}, arg, pass, info) of "infchecks": processOnOffSwitch({optInfCheck}, arg, pass, info) of "nanchecks": processOnOffSwitch({optNaNCheck}, arg, pass, info) of "nilchecks": processOnOffSwitch({optNilCheck}, arg, pass, info) of "objchecks": processOnOffSwitch({optObjCheck}, arg, pass, info) of "fieldchecks": processOnOffSwitch({optFieldCheck}, arg, pass, info) of "rangechecks": processOnOffSwitch({optRangeCheck}, arg, pass, info) of "boundchecks": processOnOffSwitch({optBoundsCheck}, arg, pass, info) of "overflowchecks": processOnOffSwitch({optOverflowCheck}, arg, pass, info) of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info) of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info) of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info) of "threads": processOnOffSwitchG({optThreads}, arg, pass, info) #if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe) of "tlsemulation": processOnOffSwitchG({optTlsEmulation}, arg, pass, info) of "taintmode": processOnOffSwitchG({optTaintMode}, arg, pass, info) of "implicitstatic": processOnOffSwitch({optImplicitStatic}, arg, pass, info) of "patterns": processOnOffSwitch({optPatterns}, arg, pass, info) of "opt": expectArg(switch, arg, pass, info) case arg.normalize of "speed": incl(gOptions, optOptimizeSpeed) excl(gOptions, optOptimizeSize) of "size": excl(gOptions, optOptimizeSpeed) incl(gOptions, optOptimizeSize) of "none": excl(gOptions, optOptimizeSpeed) excl(gOptions, optOptimizeSize) else: localError(info, errNoneSpeedOrSizeExpectedButXFound, arg) of "app": expectArg(switch, arg, pass, info) case arg.normalize of "gui": incl(gGlobalOptions, optGenGuiApp) defineSymbol("executable") defineSymbol("guiapp") of "console": excl(gGlobalOptions, optGenGuiApp) defineSymbol("executable") defineSymbol("consoleapp") of "lib": incl(gGlobalOptions, optGenDynLib) excl(gGlobalOptions, optGenGuiApp) defineSymbol("library") defineSymbol("dll") of "staticlib": incl(gGlobalOptions, optGenStaticLib) excl(gGlobalOptions, optGenGuiApp) defineSymbol("library") defineSymbol("staticlib") else: localError(info, errGuiConsoleOrLibExpectedButXFound, arg) of "passc", "t": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: extccomp.addCompileOptionCmd(arg) of "passl", "l": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: extccomp.addLinkOptionCmd(arg) of "cincludes": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: cIncludes.add arg.processPath(info) of "clibdir": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: cLibs.add arg.processPath(info) of "clib": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: cLinkedLibs.add arg.processPath(info) of "header": if config != nil: config.headerFile = arg incl(gGlobalOptions, optGenIndex) of "index": processOnOffSwitchG({optGenIndex}, arg, pass, info) of "import": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: implicitImports.add arg of "include": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: implicitIncludes.add arg of "listcmd": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optListCmd) of "genmapping": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optGenMapping) of "os": expectArg(switch, arg, pass, info) if pass in {passCmd1, passPP}: theOS = platform.nameToOS(arg) if theOS == osNone: localError(info, errUnknownOS, arg) elif theOS != platform.hostOS: setTarget(theOS, targetCPU) of "cpu": expectArg(switch, arg, pass, info) if pass in {passCmd1, passPP}: cpu = platform.nameToCPU(arg) if cpu == cpuNone: localError(info, errUnknownCPU, arg) elif cpu != platform.hostCPU: setTarget(targetOS, cpu) of "run", "r": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optRun) of "verbosity": expectArg(switch, arg, pass, info) gVerbosity = parseInt(arg) gNotes = NotesVerbosity[gVerbosity] incl(gNotes, enableNotes) excl(gNotes, disableNotes) gMainPackageNotes = gNotes of "parallelbuild": expectArg(switch, arg, pass, info) gNumberOfProcessors = parseInt(arg) of "version", "v": expectNoArg(switch, arg, pass, info) writeVersionInfo(pass) of "advanced": expectNoArg(switch, arg, pass, info) writeAdvancedUsage(pass) of "help", "h": expectNoArg(switch, arg, pass, info) helpOnError(pass) of "symbolfiles": case arg.normalize of "on": gSymbolFiles = enabledSf of "off": gSymbolFiles = disabledSf of "writeonly": gSymbolFiles = writeOnlySf of "readonly": gSymbolFiles = readOnlySf of "v2": gSymbolFiles = v2Sf else: localError(info, errOnOrOffExpectedButXFound, arg) of "skipcfg": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optSkipConfigFile) of "skipprojcfg": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optSkipProjConfigFile) of "skipusercfg": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optSkipUserConfigFile) of "skipparentcfg": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optSkipParentConfigFiles) of "genscript", "gendeps": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optGenScript) of "colors": processOnOffSwitchG({optUseColors}, arg, pass, info) of "lib": expectArg(switch, arg, pass, info) libpath = processPath(arg, info, notRelativeToProj=true) of "putenv": expectArg(switch, arg, pass, info) splitSwitch(arg, key, val, pass, info) os.putEnv(key, val) of "cc": expectArg(switch, arg, pass, info) setCC(arg) of "track": expectArg(switch, arg, pass, info) track(arg, info) of "trackdirty": expectArg(switch, arg, pass, info) trackDirty(arg, info) of "suggest": expectNoArg(switch, arg, pass, info) gIdeCmd = ideSug of "def": expectNoArg(switch, arg, pass, info) gIdeCmd = ideDef of "eval": expectArg(switch, arg, pass, info) gEvalExpr = arg of "context": expectNoArg(switch, arg, pass, info) gIdeCmd = ideCon of "usages": expectNoArg(switch, arg, pass, info) gIdeCmd = ideUse of "stdout": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optStdout) of "listfullpaths": expectNoArg(switch, arg, pass, info) gListFullPaths = true of "dynliboverride": dynlibOverride(switch, arg, pass, info) of "dynliboverrideall": expectNoArg(switch, arg, pass, info) gDynlibOverrideAll = true of "cs": # only supported for compatibility. Does nothing. expectArg(switch, arg, pass, info) of "experimental": expectNoArg(switch, arg, pass, info) gExperimentalMode = true of "nocppexceptions": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optNoCppExceptions) defineSymbol("noCppExceptions") of "cppdefine": expectArg(switch, arg, pass, info) if config != nil: config.cppDefine(arg) of "newruntime": expectNoArg(switch, arg, pass, info) newDestructors = true defineSymbol("nimNewRuntime") else: if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg) else: invalidCmdLineOption(pass, switch, info) proc processCommand(switch: string, pass: TCmdLinePass) = var cmd, arg: string splitSwitch(switch, cmd, arg, pass, gCmdLineInfo) processSwitch(cmd, arg, pass, gCmdLineInfo) var arguments* = "" # the arguments to be passed to the program that # should be run proc processSwitch*(pass: TCmdLinePass; p: OptParser) = # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off") # we fix this here var bracketLe = strutils.find(p.key, '[') if bracketLe >= 0: var key = substr(p.key, 0, bracketLe - 1) var val = substr(p.key, bracketLe + 1) & ':' & p.val processSwitch(key, val, pass, gCmdLineInfo) else: processSwitch(p.key, p.val, pass, gCmdLineInfo) proc processArgument*(pass: TCmdLinePass; p: OptParser; argsCount: var int): bool = if argsCount == 0: # nim filename.nims is the same as "nim e filename.nims": if p.key.endswith(".nims"): options.command = "e" options.gProjectName = unixToNativePath(p.key) arguments = cmdLineRest(p) result = true elif pass != passCmd2: options.command = p.key else: if pass == passCmd1: options.commandArgs.add p.key if argsCount == 1: # support UNIX style filenames everywhere for portable build scripts: options.gProjectName = unixToNativePath(p.key) arguments = cmdLineRest(p) result = true inc argsCount