summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/babelcmd.nim76
-rwxr-xr-xcompiler/commands.nim27
-rwxr-xr-xcompiler/lists.nim9
-rwxr-xr-xdoc/advopt.txt4
-rwxr-xr-xlib/pure/strtabs.nim14
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``