# # # 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, strutils, 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 addBabelPath(p: string, info: TLineInfo) = if not contains(options.searchPaths, p): if gVerbosity >= 1: message(info, hintPath, p) lists.prependStr(options.lazyPaths, p) proc addPathWithNimFiles(p: string, info: TLineInfo) = proc hasNimFile(dir: string): bool = for kind, path in walkDir(dir): if kind == pcFile and path.endsWith(".nim"): result = true break if hasNimFile(p): addBabelPath(p, info) else: for kind, p2 in walkDir(p): if hasNimFile(p2): addBabelPath(p2, info) 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: addBabelPath(p, info) proc babelPath*(path: string, info: TLineInfo) = addPathRec(path, info) addBabelPath(path, info)