diff options
-rw-r--r-- | compiler/babelcmd.nim | 76 | ||||
-rwxr-xr-x | compiler/commands.nim | 27 | ||||
-rwxr-xr-x | compiler/lists.nim | 9 | ||||
-rwxr-xr-x | doc/advopt.txt | 4 | ||||
-rwxr-xr-x | lib/pure/strtabs.nim | 14 |
5 files changed, 108 insertions, 22 deletions
diff --git a/compiler/babelcmd.nim b/compiler/babelcmd.nim new file mode 100644 index 000000000..99513e58b --- /dev/null +++ b/compiler/babelcmd.nim @@ -0,0 +1,76 @@ +# +# +# The Nimrod Compiler +# (c) Copyright 2012 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Implements some helper procs for Babel (Nimrod's package manager) support. + +import parseutils, strtabs, os, options, msgs, lists + +proc addPath*(path: string, info: TLineInfo) = + if not contains(options.searchPaths, path): + lists.PrependStr(options.searchPaths, path) + +proc versionSplitPos(s: string): int = + result = s.len-2 + while result > 1 and s[result] in {'0'..'9', '.'}: dec result + if s[result] != '-': result = s.len + +const + latest = "head" + +proc `<.`(a, b: string): bool = + # wether a has a smaller version than b: + if a == latest: return false + var i = 0 + var j = 0 + var verA = 0 + var verB = 0 + while true: + let ii = parseInt(a, verA, i) + let jj = parseInt(b, verB, j) + # if A has no number left, but B has, B is prefered: 0.8 vs 0.8.3 + if ii <= 0 or jj <= 0: return jj > 0 + if verA < verB: return true + elif verA > verB: return false + # else: same version number; continue: + inc i, ii + inc j, jj + if a[i] == '.': inc i + if b[j] == '.': inc j + +proc addPackage(packages: PStringTable, p: string) = + let x = versionSplitPos(p) + let name = p.subStr(0, x-1) + if x < p.len: + let version = p.subStr(x+1) + if packages[name] <. version: + packages[name] = version + else: + packages[name] = latest + +iterator chosen(packages: PStringTable): string = + for key, val in pairs(packages): + let res = if val == latest: key else: key & '-' & val + yield res + +proc addPathRec(dir: string, info: TLineInfo) = + var packages = newStringTable(modeStyleInsensitive) + var pos = dir.len-1 + if dir[pos] in {DirSep, AltSep}: inc(pos) + for k,p in os.walkDir(dir): + if k == pcDir and p[pos] != '.': + addPackage(packages, p) + + for p in packages.chosen: + if not contains(options.searchPaths, p): + Message(info, hintPath, p) + lists.PrependStr(options.searchPaths, p) + +proc babelPath*(path: string, info: TLineInfo) = + addPathRec(path, info) + addPath(path, info) diff --git a/compiler/commands.nim b/compiler/commands.nim index ad5f2b7e7..4a72e25f3 100755 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -11,7 +11,7 @@ import os, msgs, options, nversion, condsyms, strutils, extccomp, platform, lists, - wordrecg, parseutils + wordrecg, parseutils, babelcmd proc writeCommandLineUsage*() @@ -193,19 +193,6 @@ proc processPath(path: string): string = "projectname", options.gProjectName, "projectpath", options.gProjectPath]) -proc addPath(path: string, info: TLineInfo) = - if not contains(options.searchPaths, path): - lists.PrependStr(options.searchPaths, path) - -proc addPathRec(dir: string, info: TLineInfo) = - var pos = dir.len-1 - if dir[pos] in {DirSep, AltSep}: inc(pos) - for k,p in os.walkDir(dir): - if k == pcDir and p[pos] != '.': - if not contains(options.searchPaths, p): - #Message(info, hintPath, p) - lists.PrependStr(options.searchPaths, p) - proc track(arg: string, info: TLineInfo) = var a = arg.split(',') if a.len != 3: LocalError(info, errTokenExpected, "FILE,LINE,COLUMN") @@ -225,11 +212,15 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = of "path", "p": expectArg(switch, arg, pass, info) addPath(processPath(arg), info) - of "shallowpath": + of "babelpath": + if pass in {passCmd2, passPP}: + expectArg(switch, arg, pass, info) + let path = processPath(arg) + babelpath(path, info) + of "excludepath": expectArg(switch, arg, pass, info) - var path = processPath(arg) - addPathRec(path, info) - addPath(path, info) + let path = processPath(arg) + lists.ExcludeStr(options.searchPaths, path) of "nimcache": expectArg(switch, arg, pass, info) options.nimcacheDir = processPath(arg) diff --git a/compiler/lists.nim b/compiler/lists.nim index 1998581ce..9da4db177 100755 --- a/compiler/lists.nim +++ b/compiler/lists.nim @@ -89,7 +89,14 @@ proc Remove*(list: var TLinkedList, entry: PListEntry) = list.head = entry.next if entry.next != nil: entry.next.prev = entry.prev if entry.prev != nil: entry.prev.next = entry.next - + +proc ExcludeStr*(list: var TLinkedList, data: string) = + var it = list.head + while it != nil: + let nxt = it.next + if PStrEntry(it).data == data: remove(list, it) + it = nxt + proc Find*(list: TLinkedList, fn: TCompareProc, closure: Pointer): PListEntry = result = list.head while result != nil: diff --git a/doc/advopt.txt b/doc/advopt.txt index 2498df0bc..bd387e041 100755 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -25,8 +25,6 @@ Advanced options: --warning[X]:on|off turn specific warning X on|off --hints:on|off turn all hints on|off --hint[X]:on|off turn specific hint X on|off - --shallowPath:PATH add a path and all of its subdirectories (but - not recursively) --lib:PATH set the system library path --import:PATH add an automatically imported module --include:PATH add an automatically included module @@ -65,6 +63,8 @@ Advanced options: --gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC --index:on|off turn index file generation on|off --putenv:key=value set an environment variable + --babelPath:PATH add a path for Babel support + --excludePath:PATH exclude a path from the list of search paths --listCmd list the commands used to execute external programs --parallelBuild=0|1|... perform a parallel build value = number of processors (0 for auto-detect) diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 09a243e97..77b463fc0 100755 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -36,11 +36,23 @@ proc len*(t: PStringTable): int {.rtl, extern: "nst$1".} = result = t.counter iterator pairs*(t: PStringTable): tuple[key, value: string] = - ## iterates over any (key, value) pair in the table `t`. + ## iterates over every (key, value) pair in the table `t`. for h in 0..high(t.data): if not isNil(t.data[h].key): yield (t.data[h].key, t.data[h].val) +iterator keys*(t: PStringTable): string = + ## iterates over every key in the table `t`. + for h in 0..high(t.data): + if not isNil(t.data[h].key): + yield t.data[h].key + +iterator values*(t: PStringTable): string = + ## iterates over every value in the table `t`. + for h in 0..high(t.data): + if not isNil(t.data[h].key): + yield t.data[h].val + type TFormatFlag* = enum ## flags for the `%` operator useEnvironment, ## use environment variable if the ``$key`` |