commands.nim 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This module handles the parsing of command line arguments.
  10. # We do this here before the 'import' statement so 'defined' does not get
  11. # confused with 'TGCMode.gcGenerational' etc.
  12. template bootSwitch(name, expr, userString) =
  13. # Helper to build boot constants, for debugging you can 'echo' the else part.
  14. const name = if expr: " " & userString else: ""
  15. bootSwitch(usedRelease, defined(release), "-d:release")
  16. bootSwitch(usedDanger, defined(danger), "-d:danger")
  17. # `useLinenoise` deprecated in favor of `nimUseLinenoise`, kept for backward compatibility
  18. bootSwitch(useLinenoise, defined(nimUseLinenoise) or defined(useLinenoise), "-d:nimUseLinenoise")
  19. bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm")
  20. bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep")
  21. bootSwitch(usedGenerational, defined(gcgenerational), "--gc:generational")
  22. bootSwitch(usedGoGC, defined(gogc), "--gc:go")
  23. bootSwitch(usedNoGC, defined(nogc), "--gc:none")
  24. import
  25. os, msgs, options, nversion, condsyms, strutils, extccomp, platform,
  26. wordrecg, parseutils, nimblecmd, parseopt, sequtils, lineinfos,
  27. pathutils, strtabs
  28. from incremental import nimIncremental
  29. from ast import eqTypeFlags, tfGcSafe, tfNoSideEffect
  30. # but some have deps to imported modules. Yay.
  31. bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
  32. bootSwitch(usedNativeStacktrace,
  33. defined(nativeStackTrace) and nativeStackTraceSupported,
  34. "-d:nativeStackTrace")
  35. bootSwitch(usedFFI, hasFFI, "-d:nimHasLibFFI")
  36. type
  37. TCmdLinePass* = enum
  38. passCmd1, # first pass over the command line
  39. passCmd2, # second pass over the command line
  40. passPP # preprocessor called processCommand()
  41. const
  42. HelpMessage = "Nim Compiler Version $1 [$2: $3]\n" &
  43. "Compiled at $4\n" &
  44. "Copyright (c) 2006-" & copyrightYear & " by Andreas Rumpf\n"
  45. proc genFeatureDesc[T: enum](t: typedesc[T]): string {.compileTime.} =
  46. var x = ""
  47. for f in low(T)..high(T):
  48. if x.len > 0: x.add "|"
  49. x.add $f
  50. x
  51. const
  52. Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
  53. AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % [genFeatureDesc(Feature), genFeatureDesc(LegacyFeature)]
  54. proc getCommandLineDesc(conf: ConfigRef): string =
  55. result = (HelpMessage % [VersionAsString, platform.OS[conf.target.hostOS].name,
  56. CPU[conf.target.hostCPU].name, CompileDate]) &
  57. Usage
  58. proc helpOnError(conf: ConfigRef; pass: TCmdLinePass) =
  59. if pass == passCmd1:
  60. msgWriteln(conf, getCommandLineDesc(conf), {msgStdout})
  61. msgQuit(0)
  62. proc writeAdvancedUsage(conf: ConfigRef; pass: TCmdLinePass) =
  63. if pass == passCmd1:
  64. msgWriteln(conf, (HelpMessage % [VersionAsString,
  65. platform.OS[conf.target.hostOS].name,
  66. CPU[conf.target.hostCPU].name, CompileDate]) &
  67. AdvancedUsage,
  68. {msgStdout})
  69. msgQuit(0)
  70. proc writeFullhelp(conf: ConfigRef; pass: TCmdLinePass) =
  71. if pass == passCmd1:
  72. msgWriteln(conf, `%`(HelpMessage, [VersionAsString,
  73. platform.OS[conf.target.hostOS].name,
  74. CPU[conf.target.hostCPU].name, CompileDate]) &
  75. Usage & AdvancedUsage,
  76. {msgStdout})
  77. msgQuit(0)
  78. proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) =
  79. if pass == passCmd1:
  80. msgWriteln(conf, `%`(HelpMessage, [VersionAsString,
  81. platform.OS[conf.target.hostOS].name,
  82. CPU[conf.target.hostCPU].name, CompileDate]),
  83. {msgStdout})
  84. const gitHash {.strdefine.} = gorge("git log -n 1 --format=%H").strip
  85. when gitHash.len == 40:
  86. msgWriteln(conf, "git hash: " & gitHash, {msgStdout})
  87. msgWriteln(conf, "active boot switches:" & usedRelease & usedDanger &
  88. usedTinyC & useLinenoise & usedNativeStacktrace &
  89. usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC,
  90. {msgStdout})
  91. msgQuit(0)
  92. proc writeCommandLineUsage*(conf: ConfigRef) =
  93. msgWriteln(conf, getCommandLineDesc(conf), {msgStdout})
  94. proc addPrefix(switch: string): string =
  95. if switch.len <= 1: result = "-" & switch
  96. else: result = "--" & switch
  97. const
  98. errInvalidCmdLineOption = "invalid command line option: '$1'"
  99. errOnOrOffExpectedButXFound = "'on' or 'off' expected, but '$1' found"
  100. errOnOffOrListExpectedButXFound = "'on', 'off' or 'list' expected, but '$1' found"
  101. errOffHintsError = "'off', 'hint' or 'error' expected, but '$1' found"
  102. proc invalidCmdLineOption(conf: ConfigRef; pass: TCmdLinePass, switch: string, info: TLineInfo) =
  103. if switch == " ": localError(conf, info, errInvalidCmdLineOption % "-")
  104. else: localError(conf, info, errInvalidCmdLineOption % addPrefix(switch))
  105. proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TCmdLinePass,
  106. info: TLineInfo) =
  107. cmd = ""
  108. var i = 0
  109. if i < switch.len and switch[i] == '-': inc(i)
  110. if i < switch.len and switch[i] == '-': inc(i)
  111. while i < switch.len:
  112. case switch[i]
  113. of 'a'..'z', 'A'..'Z', '0'..'9', '_', '.': cmd.add(switch[i])
  114. else: break
  115. inc(i)
  116. if i >= switch.len: arg = ""
  117. # cmd:arg => (cmd,arg)
  118. elif switch[i] in {':', '='}: arg = substr(switch, i + 1)
  119. # cmd[sub]:rest => (cmd,[sub]:rest)
  120. elif switch[i] == '[': arg = substr(switch, i)
  121. else: invalidCmdLineOption(conf, pass, switch, info)
  122. proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
  123. info: TLineInfo) =
  124. case arg.normalize
  125. of "","on": conf.options = conf.options + op
  126. of "off": conf.options = conf.options - op
  127. else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
  128. proc processOnOffSwitchOrList(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
  129. info: TLineInfo): bool =
  130. result = false
  131. case arg.normalize
  132. of "on": conf.options = conf.options + op
  133. of "off": conf.options = conf.options - op
  134. of "list": result = true
  135. else: localError(conf, info, errOnOffOrListExpectedButXFound % arg)
  136. proc processOnOffSwitchG(conf: ConfigRef; op: TGlobalOptions, arg: string, pass: TCmdLinePass,
  137. info: TLineInfo) =
  138. case arg.normalize
  139. of "", "on": conf.globalOptions = conf.globalOptions + op
  140. of "off": conf.globalOptions = conf.globalOptions - op
  141. else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
  142. proc expectArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
  143. if arg == "":
  144. localError(conf, info, "argument for command line option expected: '$1'" % addPrefix(switch))
  145. proc expectNoArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
  146. if arg != "":
  147. localError(conf, info, "invalid argument for command line option: '$1'" % addPrefix(switch))
  148. proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
  149. info: TLineInfo; orig: string; conf: ConfigRef) =
  150. var id = "" # arg = key or [key] or key:val or [key]:val; with val=on|off
  151. var i = 0
  152. var n = hintMin
  153. var isBracket = false
  154. if i < arg.len and arg[i] == '[':
  155. isBracket = true
  156. inc(i)
  157. while i < arg.len and (arg[i] notin {':', '=', ']'}):
  158. id.add(arg[i])
  159. inc(i)
  160. if isBracket:
  161. if i < arg.len and arg[i] == ']': inc(i)
  162. else: invalidCmdLineOption(conf, pass, orig, info)
  163. if i == arg.len: discard
  164. elif i < arg.len and (arg[i] in {':', '='}): inc(i)
  165. else: invalidCmdLineOption(conf, pass, orig, info)
  166. if state == wHint:
  167. let x = findStr(lineinfos.HintsToStr, id)
  168. if x >= 0: n = TNoteKind(x + ord(hintMin))
  169. else: localError(conf, info, "unknown hint: " & id)
  170. else:
  171. let x = findStr(lineinfos.WarningsToStr, id)
  172. if x >= 0: n = TNoteKind(x + ord(warnMin))
  173. else: localError(conf, info, "unknown warning: " & id)
  174. var val = substr(arg, i).normalize
  175. if val == "": val = "on"
  176. if val notin ["on", "off"]:
  177. localError(conf, info, errOnOrOffExpectedButXFound % arg)
  178. elif n notin conf.cmdlineNotes or pass == passCmd1:
  179. if pass == passCmd1: incl(conf.cmdlineNotes, n)
  180. incl(conf.modifiedyNotes, n)
  181. case val
  182. of "on":
  183. if state == wWarningAsError:
  184. incl(conf.warningAsErrors, n)
  185. else:
  186. incl(conf.notes, n)
  187. incl(conf.mainPackageNotes, n)
  188. of "off":
  189. if state == wWarningAsError:
  190. excl(conf.warningAsErrors, n)
  191. else:
  192. excl(conf.notes, n)
  193. excl(conf.mainPackageNotes, n)
  194. excl(conf.foreignPackageNotes, n)
  195. proc processCompile(conf: ConfigRef; filename: string) =
  196. var found = findFile(conf, filename)
  197. if found.isEmpty: found = AbsoluteFile filename
  198. extccomp.addExternalFileToCompile(conf, found)
  199. const
  200. errNoneBoehmRefcExpectedButXFound = "'none', 'boehm' or 'refc' expected, but '$1' found"
  201. errNoneSpeedOrSizeExpectedButXFound = "'none', 'speed' or 'size' expected, but '$1' found"
  202. errGuiConsoleOrLibExpectedButXFound = "'gui', 'console' or 'lib' expected, but '$1' found"
  203. errInvalidExceptionSystem = "'goto', 'setjump', 'cpp' or 'quirky' expected, but '$1' found"
  204. proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
  205. case switch.normalize
  206. of "gc":
  207. case arg.normalize
  208. of "boehm": result = conf.selectedGC == gcBoehm
  209. of "refc": result = conf.selectedGC == gcRefc
  210. of "v2": result = false
  211. of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
  212. of "generational": result = false
  213. of "destructors", "arc": result = conf.selectedGC == gcArc
  214. of "orc": result = conf.selectedGC == gcOrc
  215. of "hooks": result = conf.selectedGC == gcHooks
  216. of "go": result = conf.selectedGC == gcGo
  217. of "none": result = conf.selectedGC == gcNone
  218. of "stack", "regions": result = conf.selectedGC == gcRegions
  219. else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
  220. of "opt":
  221. case arg.normalize
  222. of "speed": result = contains(conf.options, optOptimizeSpeed)
  223. of "size": result = contains(conf.options, optOptimizeSize)
  224. of "none": result = conf.options * {optOptimizeSpeed, optOptimizeSize} == {}
  225. else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg)
  226. of "verbosity": result = $conf.verbosity == arg
  227. of "app":
  228. case arg.normalize
  229. of "gui": result = contains(conf.globalOptions, optGenGuiApp)
  230. of "console": result = not contains(conf.globalOptions, optGenGuiApp)
  231. of "lib": result = contains(conf.globalOptions, optGenDynLib) and
  232. not contains(conf.globalOptions, optGenGuiApp)
  233. of "staticlib": result = contains(conf.globalOptions, optGenStaticLib) and
  234. not contains(conf.globalOptions, optGenGuiApp)
  235. else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
  236. of "dynliboverride":
  237. result = isDynlibOverride(conf, arg)
  238. of "exceptions":
  239. case arg.normalize
  240. of "cpp": result = conf.exc == excCpp
  241. of "setjmp": result = conf.exc == excSetjmp
  242. of "quirky": result = conf.exc == excQuirky
  243. of "goto": result = conf.exc == excGoto
  244. else: localError(conf, info, errInvalidExceptionSystem % arg)
  245. else: invalidCmdLineOption(conf, passCmd1, switch, info)
  246. proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool =
  247. case switch.normalize
  248. of "debuginfo": result = contains(conf.globalOptions, optCDebug)
  249. of "compileonly", "c": result = contains(conf.globalOptions, optCompileOnly)
  250. of "nolinking": result = contains(conf.globalOptions, optNoLinking)
  251. of "nomain": result = contains(conf.globalOptions, optNoMain)
  252. of "forcebuild", "f": result = contains(conf.globalOptions, optForceFullMake)
  253. of "warnings", "w": result = contains(conf.options, optWarns)
  254. of "hints": result = contains(conf.options, optHints)
  255. of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis)
  256. of "stacktrace": result = contains(conf.options, optStackTrace)
  257. of "stacktracemsgs": result = contains(conf.options, optStackTraceMsgs)
  258. of "linetrace": result = contains(conf.options, optLineTrace)
  259. of "debugger": result = contains(conf.globalOptions, optCDebug)
  260. of "profiler": result = contains(conf.options, optProfiler)
  261. of "memtracker": result = contains(conf.options, optMemTracker)
  262. of "checks", "x": result = conf.options * ChecksOptions == ChecksOptions
  263. of "floatchecks":
  264. result = conf.options * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck}
  265. of "infchecks": result = contains(conf.options, optInfCheck)
  266. of "nanchecks": result = contains(conf.options, optNaNCheck)
  267. of "nilchecks": result = false # not a thing
  268. of "objchecks": result = contains(conf.options, optObjCheck)
  269. of "fieldchecks": result = contains(conf.options, optFieldCheck)
  270. of "rangechecks": result = contains(conf.options, optRangeCheck)
  271. of "boundchecks": result = contains(conf.options, optBoundsCheck)
  272. of "refchecks": result = contains(conf.options, optRefCheck)
  273. of "overflowchecks": result = contains(conf.options, optOverflowCheck)
  274. of "staticboundchecks": result = contains(conf.options, optStaticBoundsCheck)
  275. of "stylechecks": result = contains(conf.options, optStyleCheck)
  276. of "linedir": result = contains(conf.options, optLineDir)
  277. of "assertions", "a": result = contains(conf.options, optAssert)
  278. of "run", "r": result = contains(conf.globalOptions, optRun)
  279. of "symbolfiles": result = conf.symbolFiles != disabledSf
  280. of "genscript": result = contains(conf.globalOptions, optGenScript)
  281. of "threads": result = contains(conf.globalOptions, optThreads)
  282. of "taintmode": result = contains(conf.globalOptions, optTaintMode)
  283. of "tlsemulation": result = contains(conf.globalOptions, optTlsEmulation)
  284. of "implicitstatic": result = contains(conf.options, optImplicitStatic)
  285. of "patterns", "trmacros": result = contains(conf.options, optTrMacros)
  286. of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace)
  287. of "nilseqs": result = contains(conf.options, optNilSeqs)
  288. else: invalidCmdLineOption(conf, passCmd1, switch, info)
  289. proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
  290. notRelativeToProj = false): AbsoluteDir =
  291. let p = if os.isAbsolute(path) or '$' in path:
  292. path
  293. elif notRelativeToProj:
  294. getCurrentDir() / path
  295. else:
  296. conf.projectPath.string / path
  297. try:
  298. result = AbsoluteDir pathSubs(conf, p, toFullPath(conf, info).splitFile().dir)
  299. except ValueError:
  300. localError(conf, info, "invalid path: " & p)
  301. result = AbsoluteDir p
  302. proc processCfgPath(conf: ConfigRef; path: string, info: TLineInfo): AbsoluteDir =
  303. let path = if path.len > 0 and path[0] == '"': strutils.unescape(path)
  304. else: path
  305. let basedir = toFullPath(conf, info).splitFile().dir
  306. let p = if os.isAbsolute(path) or '$' in path:
  307. path
  308. else:
  309. basedir / path
  310. try:
  311. result = AbsoluteDir pathSubs(conf, p, basedir)
  312. except ValueError:
  313. localError(conf, info, "invalid path: " & p)
  314. result = AbsoluteDir p
  315. const
  316. errInvalidNumber = "$1 is not a valid number"
  317. proc trackDirty(conf: ConfigRef; arg: string, info: TLineInfo) =
  318. var a = arg.split(',')
  319. if a.len != 4: localError(conf, info,
  320. "DIRTY_BUFFER,ORIGINAL_FILE,LINE,COLUMN expected")
  321. var line, column: int
  322. if parseUtils.parseInt(a[2], line) <= 0:
  323. localError(conf, info, errInvalidNumber % a[1])
  324. if parseUtils.parseInt(a[3], column) <= 0:
  325. localError(conf, info, errInvalidNumber % a[2])
  326. let dirtyOriginalIdx = fileInfoIdx(conf, AbsoluteFile a[1])
  327. if dirtyOriginalIdx.int32 >= 0:
  328. msgs.setDirtyFile(conf, dirtyOriginalIdx, AbsoluteFile a[0])
  329. conf.m.trackPos = newLineInfo(dirtyOriginalIdx, line, column)
  330. proc track(conf: ConfigRef; arg: string, info: TLineInfo) =
  331. var a = arg.split(',')
  332. if a.len != 3: localError(conf, info, "FILE,LINE,COLUMN expected")
  333. var line, column: int
  334. if parseUtils.parseInt(a[1], line) <= 0:
  335. localError(conf, info, errInvalidNumber % a[1])
  336. if parseUtils.parseInt(a[2], column) <= 0:
  337. localError(conf, info, errInvalidNumber % a[2])
  338. conf.m.trackPos = newLineInfo(conf, AbsoluteFile a[0], line, column)
  339. proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
  340. if pass in {passCmd2, passPP}:
  341. expectArg(conf, switch, arg, pass, info)
  342. options.inclDynlibOverride(conf, arg)
  343. proc handleStdinInput*(conf: ConfigRef) =
  344. conf.projectName = "stdinfile"
  345. conf.projectFull = conf.projectName.AbsoluteFile
  346. conf.projectPath = AbsoluteDir getCurrentDir()
  347. conf.projectIsStdin = true
  348. if conf.outDir.isEmpty:
  349. conf.outDir = getNimcacheDir(conf)
  350. proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
  351. conf: ConfigRef) =
  352. var
  353. key, val: string
  354. case switch.normalize
  355. of "path", "p":
  356. expectArg(conf, switch, arg, pass, info)
  357. for path in nimbleSubs(conf, arg):
  358. addPath(conf, if pass == passPP: processCfgPath(conf, path, info)
  359. else: processPath(conf, path, info), info)
  360. of "nimblepath", "babelpath":
  361. # keep the old name for compat
  362. if pass in {passCmd2, passPP} and optNoNimblePath notin conf.globalOptions:
  363. expectArg(conf, switch, arg, pass, info)
  364. var path = processPath(conf, arg, info, notRelativeToProj=true)
  365. let nimbleDir = AbsoluteDir getEnv("NIMBLE_DIR")
  366. if not nimbleDir.isEmpty and pass == passPP:
  367. path = nimbleDir / RelativeDir"pkgs"
  368. nimblePath(conf, path, info)
  369. of "nonimblepath", "nobabelpath":
  370. expectNoArg(conf, switch, arg, pass, info)
  371. disableNimblePath(conf)
  372. of "clearnimblepath":
  373. expectNoArg(conf, switch, arg, pass, info)
  374. clearNimblePath(conf)
  375. of "excludepath":
  376. expectArg(conf, switch, arg, pass, info)
  377. let path = processPath(conf, arg, info)
  378. conf.searchPaths.keepItIf(it != path)
  379. conf.lazyPaths.keepItIf(it != path)
  380. of "nimcache":
  381. expectArg(conf, switch, arg, pass, info)
  382. conf.nimcacheDir = processPath(conf, arg, info, notRelativeToProj=true)
  383. of "out", "o":
  384. expectArg(conf, switch, arg, pass, info)
  385. let f = splitFile(processPath(conf, arg, info, notRelativeToProj=true).string)
  386. conf.outFile = RelativeFile f.name & f.ext
  387. conf.outDir = toAbsoluteDir f.dir
  388. of "outdir":
  389. expectArg(conf, switch, arg, pass, info)
  390. conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
  391. of "usenimcache":
  392. processOnOffSwitchG(conf, {optUseNimcache}, arg, pass, info)
  393. of "docseesrcurl":
  394. expectArg(conf, switch, arg, pass, info)
  395. conf.docSeeSrcUrl = arg
  396. of "docroot":
  397. conf.docRoot = if arg.len == 0: docRootDefault else: arg
  398. of "backend", "b":
  399. let backend = parseEnum(arg.normalize, TBackend.default)
  400. if backend == TBackend.default: localError(conf, info, "invalid backend: '$1'" % arg)
  401. conf.backend = backend
  402. of "doccmd": conf.docCmd = arg
  403. of "mainmodule", "m":
  404. discard "allow for backwards compatibility, but don't do anything"
  405. of "define", "d":
  406. expectArg(conf, switch, arg, pass, info)
  407. if {':', '='} in arg:
  408. splitSwitch(conf, arg, key, val, pass, info)
  409. if cmpIgnoreStyle(key, "nimQuirky") == 0:
  410. conf.exc = excQuirky
  411. defineSymbol(conf.symbols, key, val)
  412. else:
  413. if cmpIgnoreStyle(arg, "nimQuirky") == 0:
  414. conf.exc = excQuirky
  415. defineSymbol(conf.symbols, arg)
  416. of "undef", "u":
  417. expectArg(conf, switch, arg, pass, info)
  418. undefSymbol(conf.symbols, arg)
  419. of "symbol":
  420. expectArg(conf, switch, arg, pass, info)
  421. # deprecated, do nothing
  422. of "compile":
  423. expectArg(conf, switch, arg, pass, info)
  424. if pass in {passCmd2, passPP}: processCompile(conf, arg)
  425. of "link":
  426. expectArg(conf, switch, arg, pass, info)
  427. if pass in {passCmd2, passPP}:
  428. addExternalFileToLink(conf, AbsoluteFile arg)
  429. of "debuginfo":
  430. processOnOffSwitchG(conf, {optCDebug}, arg, pass, info)
  431. of "embedsrc":
  432. processOnOffSwitchG(conf, {optEmbedOrigSrc}, arg, pass, info)
  433. of "compileonly", "c":
  434. processOnOffSwitchG(conf, {optCompileOnly}, arg, pass, info)
  435. of "nolinking":
  436. processOnOffSwitchG(conf, {optNoLinking}, arg, pass, info)
  437. of "nomain":
  438. processOnOffSwitchG(conf, {optNoMain}, arg, pass, info)
  439. of "forcebuild", "f":
  440. processOnOffSwitchG(conf, {optForceFullMake}, arg, pass, info)
  441. of "project":
  442. processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info)
  443. of "gc":
  444. expectArg(conf, switch, arg, pass, info)
  445. if pass in {passCmd2, passPP}:
  446. case arg.normalize
  447. of "boehm":
  448. conf.selectedGC = gcBoehm
  449. defineSymbol(conf.symbols, "boehmgc")
  450. incl conf.globalOptions, optTlsEmulation # Boehm GC doesn't scan the real TLS
  451. of "refc":
  452. conf.selectedGC = gcRefc
  453. of "v2":
  454. message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
  455. of "markandsweep":
  456. conf.selectedGC = gcMarkAndSweep
  457. defineSymbol(conf.symbols, "gcmarkandsweep")
  458. of "destructors", "arc":
  459. conf.selectedGC = gcArc
  460. defineSymbol(conf.symbols, "gcdestructors")
  461. defineSymbol(conf.symbols, "gcarc")
  462. incl conf.globalOptions, optSeqDestructors
  463. incl conf.globalOptions, optTinyRtti
  464. if pass in {passCmd2, passPP}:
  465. defineSymbol(conf.symbols, "nimSeqsV2")
  466. defineSymbol(conf.symbols, "nimV2")
  467. of "orc":
  468. conf.selectedGC = gcOrc
  469. defineSymbol(conf.symbols, "gcdestructors")
  470. defineSymbol(conf.symbols, "gcorc")
  471. incl conf.globalOptions, optSeqDestructors
  472. incl conf.globalOptions, optTinyRtti
  473. if pass in {passCmd2, passPP}:
  474. defineSymbol(conf.symbols, "nimSeqsV2")
  475. defineSymbol(conf.symbols, "nimV2")
  476. of "hooks":
  477. conf.selectedGC = gcHooks
  478. defineSymbol(conf.symbols, "gchooks")
  479. incl conf.globalOptions, optSeqDestructors
  480. processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
  481. if pass in {passCmd2, passPP}:
  482. defineSymbol(conf.symbols, "nimSeqsV2")
  483. of "go":
  484. conf.selectedGC = gcGo
  485. defineSymbol(conf.symbols, "gogc")
  486. of "none":
  487. conf.selectedGC = gcNone
  488. defineSymbol(conf.symbols, "nogc")
  489. of "stack", "regions":
  490. conf.selectedGC = gcRegions
  491. defineSymbol(conf.symbols, "gcregions")
  492. else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
  493. of "warnings", "w":
  494. if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
  495. of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
  496. of "hint": processSpecificNote(arg, wHint, pass, info, switch, conf)
  497. of "warningaserror": processSpecificNote(arg, wWarningAsError, pass, info, switch, conf)
  498. of "hints":
  499. if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf)
  500. of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info)
  501. of "stacktrace": processOnOffSwitch(conf, {optStackTrace}, arg, pass, info)
  502. of "stacktracemsgs": processOnOffSwitch(conf, {optStackTraceMsgs}, arg, pass, info)
  503. of "excessivestacktrace": processOnOffSwitchG(conf, {optExcessiveStackTrace}, arg, pass, info)
  504. of "linetrace": processOnOffSwitch(conf, {optLineTrace}, arg, pass, info)
  505. of "debugger":
  506. case arg.normalize
  507. of "on", "native", "gdb":
  508. conf.globalOptions.incl optCDebug
  509. conf.options.incl optLineDir
  510. #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
  511. of "off":
  512. conf.globalOptions.excl optCDebug
  513. else:
  514. localError(conf, info, "expected native|gdb|on|off but found " & arg)
  515. of "g": # alias for --debugger:native
  516. conf.globalOptions.incl optCDebug
  517. conf.options.incl optLineDir
  518. #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
  519. of "profiler":
  520. processOnOffSwitch(conf, {optProfiler}, arg, pass, info)
  521. if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler")
  522. else: undefSymbol(conf.symbols, "profiler")
  523. of "memtracker":
  524. processOnOffSwitch(conf, {optMemTracker}, arg, pass, info)
  525. if optMemTracker in conf.options: defineSymbol(conf.symbols, "memtracker")
  526. else: undefSymbol(conf.symbols, "memtracker")
  527. of "hotcodereloading":
  528. processOnOffSwitchG(conf, {optHotCodeReloading}, arg, pass, info)
  529. if conf.hcrOn:
  530. defineSymbol(conf.symbols, "hotcodereloading")
  531. defineSymbol(conf.symbols, "useNimRtl")
  532. # hardcoded linking with dynamic runtime for MSVC for smaller binaries
  533. # should do the same for all compilers (wherever applicable)
  534. if isVSCompatible(conf):
  535. extccomp.addCompileOptionCmd(conf, "/MD")
  536. else:
  537. undefSymbol(conf.symbols, "hotcodereloading")
  538. undefSymbol(conf.symbols, "useNimRtl")
  539. of "nilseqs": processOnOffSwitch(conf, {optNilSeqs}, arg, pass, info)
  540. of "checks", "x": processOnOffSwitch(conf, ChecksOptions, arg, pass, info)
  541. of "floatchecks":
  542. processOnOffSwitch(conf, {optNaNCheck, optInfCheck}, arg, pass, info)
  543. of "infchecks": processOnOffSwitch(conf, {optInfCheck}, arg, pass, info)
  544. of "nanchecks": processOnOffSwitch(conf, {optNaNCheck}, arg, pass, info)
  545. of "nilchecks": discard "no such thing anymore"
  546. of "objchecks": processOnOffSwitch(conf, {optObjCheck}, arg, pass, info)
  547. of "fieldchecks": processOnOffSwitch(conf, {optFieldCheck}, arg, pass, info)
  548. of "rangechecks": processOnOffSwitch(conf, {optRangeCheck}, arg, pass, info)
  549. of "boundchecks": processOnOffSwitch(conf, {optBoundsCheck}, arg, pass, info)
  550. of "refchecks": processOnOffSwitch(conf, {optRefCheck}, arg, pass, info)
  551. of "overflowchecks": processOnOffSwitch(conf, {optOverflowCheck}, arg, pass, info)
  552. of "staticboundchecks": processOnOffSwitch(conf, {optStaticBoundsCheck}, arg, pass, info)
  553. of "stylechecks": processOnOffSwitch(conf, {optStyleCheck}, arg, pass, info)
  554. of "linedir": processOnOffSwitch(conf, {optLineDir}, arg, pass, info)
  555. of "assertions", "a": processOnOffSwitch(conf, {optAssert}, arg, pass, info)
  556. of "deadcodeelim": discard # deprecated, dead code elim always on
  557. of "threads":
  558. processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
  559. #if optThreads in conf.globalOptions: conf.setNote(warnGcUnsafe)
  560. of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
  561. of "taintmode": processOnOffSwitchG(conf, {optTaintMode}, arg, pass, info)
  562. of "implicitstatic":
  563. processOnOffSwitch(conf, {optImplicitStatic}, arg, pass, info)
  564. of "patterns", "trmacros":
  565. processOnOffSwitch(conf, {optTrMacros}, arg, pass, info)
  566. of "opt":
  567. expectArg(conf, switch, arg, pass, info)
  568. case arg.normalize
  569. of "speed":
  570. incl(conf.options, optOptimizeSpeed)
  571. excl(conf.options, optOptimizeSize)
  572. of "size":
  573. excl(conf.options, optOptimizeSpeed)
  574. incl(conf.options, optOptimizeSize)
  575. of "none":
  576. excl(conf.options, optOptimizeSpeed)
  577. excl(conf.options, optOptimizeSize)
  578. else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg)
  579. of "app":
  580. expectArg(conf, switch, arg, pass, info)
  581. case arg.normalize
  582. of "gui":
  583. incl(conf.globalOptions, optGenGuiApp)
  584. defineSymbol(conf.symbols, "executable")
  585. defineSymbol(conf.symbols, "guiapp")
  586. of "console":
  587. excl(conf.globalOptions, optGenGuiApp)
  588. defineSymbol(conf.symbols, "executable")
  589. defineSymbol(conf.symbols, "consoleapp")
  590. of "lib":
  591. incl(conf.globalOptions, optGenDynLib)
  592. excl(conf.globalOptions, optGenGuiApp)
  593. defineSymbol(conf.symbols, "library")
  594. defineSymbol(conf.symbols, "dll")
  595. of "staticlib":
  596. incl(conf.globalOptions, optGenStaticLib)
  597. excl(conf.globalOptions, optGenGuiApp)
  598. defineSymbol(conf.symbols, "library")
  599. defineSymbol(conf.symbols, "staticlib")
  600. else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
  601. of "passc", "t":
  602. expectArg(conf, switch, arg, pass, info)
  603. if pass in {passCmd2, passPP}: extccomp.addCompileOptionCmd(conf, arg)
  604. of "passl", "l":
  605. expectArg(conf, switch, arg, pass, info)
  606. if pass in {passCmd2, passPP}: extccomp.addLinkOptionCmd(conf, arg)
  607. of "cincludes":
  608. expectArg(conf, switch, arg, pass, info)
  609. if pass in {passCmd2, passPP}: conf.cIncludes.add processPath(conf, arg, info)
  610. of "clibdir":
  611. expectArg(conf, switch, arg, pass, info)
  612. if pass in {passCmd2, passPP}: conf.cLibs.add processPath(conf, arg, info)
  613. of "clib":
  614. expectArg(conf, switch, arg, pass, info)
  615. if pass in {passCmd2, passPP}:
  616. conf.cLinkedLibs.add processPath(conf, arg, info).string
  617. of "header":
  618. if conf != nil: conf.headerFile = arg
  619. incl(conf.globalOptions, optGenIndex)
  620. of "index":
  621. processOnOffSwitchG(conf, {optGenIndex}, arg, pass, info)
  622. of "import":
  623. expectArg(conf, switch, arg, pass, info)
  624. if pass in {passCmd2, passPP}:
  625. conf.implicitImports.add findModule(conf, arg, toFullPath(conf, info)).string
  626. of "include":
  627. expectArg(conf, switch, arg, pass, info)
  628. if pass in {passCmd2, passPP}:
  629. conf.implicitIncludes.add findModule(conf, arg, toFullPath(conf, info)).string
  630. of "listcmd":
  631. processOnOffSwitchG(conf, {optListCmd}, arg, pass, info)
  632. of "asm":
  633. processOnOffSwitchG(conf, {optProduceAsm}, arg, pass, info)
  634. of "genmapping":
  635. processOnOffSwitchG(conf, {optGenMapping}, arg, pass, info)
  636. of "os":
  637. expectArg(conf, switch, arg, pass, info)
  638. let theOS = platform.nameToOS(arg)
  639. if theOS == osNone:
  640. let osList = platform.listOSnames().join(", ")
  641. localError(conf, info, "unknown OS: '$1'. Available options are: $2" % [arg, $osList])
  642. else:
  643. setTarget(conf.target, theOS, conf.target.targetCPU)
  644. of "cpu":
  645. expectArg(conf, switch, arg, pass, info)
  646. let cpu = platform.nameToCPU(arg)
  647. if cpu == cpuNone:
  648. let cpuList = platform.listCPUnames().join(", ")
  649. localError(conf, info, "unknown CPU: '$1'. Available options are: $2" % [ arg, cpuList])
  650. else:
  651. setTarget(conf.target, conf.target.targetOS, cpu)
  652. of "run", "r":
  653. processOnOffSwitchG(conf, {optRun}, arg, pass, info)
  654. of "maxloopiterationsvm":
  655. expectArg(conf, switch, arg, pass, info)
  656. conf.maxLoopIterationsVM = parseInt(arg)
  657. of "errormax":
  658. expectArg(conf, switch, arg, pass, info)
  659. # Note: `nim check` (etc) can overwrite this.
  660. # `0` is meaningless, give it a useful meaning as in clang's -ferror-limit
  661. # If user doesn't set this flag and the code doesn't either, it'd
  662. # have the same effect as errorMax = 1
  663. let ret = parseInt(arg)
  664. conf.errorMax = if ret == 0: high(int) else: ret
  665. of "verbosity":
  666. expectArg(conf, switch, arg, pass, info)
  667. let verbosity = parseInt(arg)
  668. if verbosity notin {0..3}:
  669. localError(conf, info, "invalid verbosity level: '$1'" % arg)
  670. conf.verbosity = verbosity
  671. var verb = NotesVerbosity[conf.verbosity]
  672. ## We override the default `verb` by explicitly modified (set/unset) notes.
  673. conf.notes = (conf.modifiedyNotes * conf.notes + verb) -
  674. (conf.modifiedyNotes * verb - conf.notes)
  675. conf.mainPackageNotes = conf.notes
  676. of "parallelbuild":
  677. expectArg(conf, switch, arg, pass, info)
  678. conf.numberOfProcessors = parseInt(arg)
  679. of "version", "v":
  680. expectNoArg(conf, switch, arg, pass, info)
  681. writeVersionInfo(conf, pass)
  682. of "advanced":
  683. expectNoArg(conf, switch, arg, pass, info)
  684. writeAdvancedUsage(conf, pass)
  685. of "fullhelp":
  686. expectNoArg(conf, switch, arg, pass, info)
  687. writeFullhelp(conf, pass)
  688. of "help", "h":
  689. expectNoArg(conf, switch, arg, pass, info)
  690. helpOnError(conf, pass)
  691. of "symbolfiles": discard "ignore for backwards compat"
  692. of "incremental":
  693. when not nimIncremental:
  694. localError(conf, info, "the compiler was not built with " &
  695. "incremental compilation features; bootstrap with " &
  696. "-d:nimIncremental to enable")
  697. case arg.normalize
  698. of "on": conf.symbolFiles = v2Sf
  699. of "off": conf.symbolFiles = disabledSf
  700. of "writeonly": conf.symbolFiles = writeOnlySf
  701. of "readonly": conf.symbolFiles = readOnlySf
  702. of "v2": conf.symbolFiles = v2Sf
  703. else: localError(conf, info, "invalid option for --incremental: " & arg)
  704. of "skipcfg":
  705. processOnOffSwitchG(conf, {optSkipSystemConfigFile}, arg, pass, info)
  706. of "skipprojcfg":
  707. processOnOffSwitchG(conf, {optSkipProjConfigFile}, arg, pass, info)
  708. of "skipusercfg":
  709. processOnOffSwitchG(conf, {optSkipUserConfigFile}, arg, pass, info)
  710. of "skipparentcfg":
  711. processOnOffSwitchG(conf, {optSkipParentConfigFiles}, arg, pass, info)
  712. of "genscript", "gendeps":
  713. processOnOffSwitchG(conf, {optGenScript}, arg, pass, info)
  714. processOnOffSwitchG(conf, {optCompileOnly}, arg, pass, info)
  715. of "colors": processOnOffSwitchG(conf, {optUseColors}, arg, pass, info)
  716. of "lib":
  717. expectArg(conf, switch, arg, pass, info)
  718. conf.libpath = processPath(conf, arg, info, notRelativeToProj=true)
  719. of "putenv":
  720. expectArg(conf, switch, arg, pass, info)
  721. splitSwitch(conf, arg, key, val, pass, info)
  722. os.putEnv(key, val)
  723. of "cc":
  724. expectArg(conf, switch, arg, pass, info)
  725. setCC(conf, arg, info)
  726. of "track":
  727. expectArg(conf, switch, arg, pass, info)
  728. track(conf, arg, info)
  729. of "trackdirty":
  730. expectArg(conf, switch, arg, pass, info)
  731. trackDirty(conf, arg, info)
  732. of "suggest":
  733. expectNoArg(conf, switch, arg, pass, info)
  734. conf.ideCmd = ideSug
  735. of "def":
  736. expectNoArg(conf, switch, arg, pass, info)
  737. conf.ideCmd = ideDef
  738. of "eval":
  739. expectArg(conf, switch, arg, pass, info)
  740. conf.evalExpr = arg
  741. of "context":
  742. expectNoArg(conf, switch, arg, pass, info)
  743. conf.ideCmd = ideCon
  744. of "usages":
  745. expectNoArg(conf, switch, arg, pass, info)
  746. conf.ideCmd = ideUse
  747. of "stdout":
  748. processOnOffSwitchG(conf, {optStdout}, arg, pass, info)
  749. of "listfullpaths":
  750. processOnOffSwitchG(conf, {optListFullPaths}, arg, pass, info)
  751. of "dynliboverride":
  752. dynlibOverride(conf, switch, arg, pass, info)
  753. of "dynliboverrideall":
  754. processOnOffSwitchG(conf, {optDynlibOverrideAll}, arg, pass, info)
  755. of "cs":
  756. # only supported for compatibility. Does nothing.
  757. expectArg(conf, switch, arg, pass, info)
  758. of "experimental":
  759. if arg.len == 0:
  760. conf.features.incl oldExperimentalFeatures
  761. else:
  762. try:
  763. conf.features.incl parseEnum[Feature](arg)
  764. except ValueError:
  765. localError(conf, info, "unknown experimental feature")
  766. of "legacy":
  767. try:
  768. conf.legacyFeatures.incl parseEnum[LegacyFeature](arg)
  769. except ValueError:
  770. localError(conf, info, "unknown obsolete feature")
  771. of "nocppexceptions":
  772. expectNoArg(conf, switch, arg, pass, info)
  773. conf.exc = low(ExceptionSystem)
  774. defineSymbol(conf.symbols, "noCppExceptions")
  775. of "exceptions":
  776. case arg.normalize
  777. of "cpp": conf.exc = excCpp
  778. of "setjmp": conf.exc = excSetjmp
  779. of "quirky": conf.exc = excQuirky
  780. of "goto": conf.exc = excGoto
  781. else: localError(conf, info, errInvalidExceptionSystem % arg)
  782. of "cppdefine":
  783. expectArg(conf, switch, arg, pass, info)
  784. if conf != nil:
  785. conf.cppDefine(arg)
  786. of "newruntime":
  787. expectNoArg(conf, switch, arg, pass, info)
  788. if pass in {passCmd2, passPP}:
  789. doAssert(conf != nil)
  790. incl(conf.features, destructor)
  791. incl(conf.globalOptions, optTinyRtti)
  792. incl(conf.globalOptions, optOwnedRefs)
  793. incl(conf.globalOptions, optSeqDestructors)
  794. defineSymbol(conf.symbols, "nimV2")
  795. conf.selectedGC = gcHooks
  796. defineSymbol(conf.symbols, "gchooks")
  797. defineSymbol(conf.symbols, "nimSeqsV2")
  798. defineSymbol(conf.symbols, "nimOwnedEnabled")
  799. of "seqsv2":
  800. processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
  801. if pass in {passCmd2, passPP}:
  802. defineSymbol(conf.symbols, "nimSeqsV2")
  803. of "stylecheck":
  804. case arg.normalize
  805. of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError}
  806. of "hint": conf.globalOptions = conf.globalOptions + {optStyleHint} - {optStyleError}
  807. of "error": conf.globalOptions = conf.globalOptions + {optStyleError}
  808. else: localError(conf, info, errOffHintsError % arg)
  809. of "showallmismatches":
  810. processOnOffSwitchG(conf, {optShowAllMismatches}, arg, pass, info)
  811. of "cppcompiletonamespace":
  812. if arg.len > 0:
  813. conf.cppCustomNamespace = arg
  814. else:
  815. conf.cppCustomNamespace = "Nim"
  816. defineSymbol(conf.symbols, "cppCompileToNamespace", conf.cppCustomNamespace)
  817. of "docinternal":
  818. processOnOffSwitchG(conf, {optDocInternal}, arg, pass, info)
  819. of "multimethods":
  820. processOnOffSwitchG(conf, {optMultiMethods}, arg, pass, info)
  821. of "expandmacro":
  822. expectArg(conf, switch, arg, pass, info)
  823. conf.macrosToExpand[arg] = "T"
  824. of "oldgensym":
  825. processOnOffSwitchG(conf, {optNimV019}, arg, pass, info)
  826. of "useversion":
  827. expectArg(conf, switch, arg, pass, info)
  828. case arg
  829. of "1.0":
  830. defineSymbol(conf.symbols, "NimMajor", "1")
  831. defineSymbol(conf.symbols, "NimMinor", "0")
  832. # always be compatible with 1.0.100:
  833. defineSymbol(conf.symbols, "NimPatch", "100")
  834. # old behaviors go here:
  835. defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
  836. ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
  837. conf.globalOptions.incl optNimV1Emulation
  838. else:
  839. localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
  840. of "benchmarkvm":
  841. processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
  842. of "sinkinference":
  843. processOnOffSwitch(conf, {optSinkInference}, arg, pass, info)
  844. of "panics":
  845. processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
  846. if optPanics in conf.globalOptions:
  847. defineSymbol(conf.symbols, "nimPanics")
  848. of "sourcemap":
  849. conf.globalOptions.incl optSourcemap
  850. conf.options.incl optLineDir
  851. # processOnOffSwitchG(conf, {optSourcemap, opt}, arg, pass, info)
  852. of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
  853. handleStdinInput(conf)
  854. else:
  855. if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
  856. else: invalidCmdLineOption(conf, pass, switch, info)
  857. proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
  858. var cmd, arg: string
  859. splitSwitch(config, switch, cmd, arg, pass, gCmdLineInfo)
  860. processSwitch(cmd, arg, pass, gCmdLineInfo, config)
  861. proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) =
  862. # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
  863. # we transform it to (key = hint, val = [X]:off)
  864. var bracketLe = strutils.find(p.key, '[')
  865. if bracketLe >= 0:
  866. var key = substr(p.key, 0, bracketLe - 1)
  867. var val = substr(p.key, bracketLe) & ':' & p.val
  868. processSwitch(key, val, pass, gCmdLineInfo, config)
  869. else:
  870. processSwitch(p.key, p.val, pass, gCmdLineInfo, config)
  871. proc processArgument*(pass: TCmdLinePass; p: OptParser;
  872. argsCount: var int; config: ConfigRef): bool =
  873. if argsCount == 0:
  874. # nim filename.nims is the same as "nim e filename.nims":
  875. if p.key.endsWith(".nims"):
  876. config.command = "e"
  877. incl(config.globalOptions, optWasNimscript)
  878. config.projectName = unixToNativePath(p.key)
  879. config.arguments = cmdLineRest(p)
  880. result = true
  881. elif pass != passCmd2:
  882. config.command = p.key
  883. else:
  884. if pass == passCmd1: config.commandArgs.add p.key
  885. if argsCount == 1:
  886. # support UNIX style filenames everywhere for portable build scripts:
  887. if config.projectName.len == 0:
  888. config.projectName = unixToNativePath(p.key)
  889. config.arguments = cmdLineRest(p)
  890. result = true
  891. inc argsCount