diff options
| author | Ganesh Viswanathan <dev@genotrance.com> | 2018-06-11 01:47:08 -0500 |
|---|---|---|
| committer | Ganesh Viswanathan <dev@genotrance.com> | 2018-06-11 01:47:08 -0500 |
| commit | 7fbc8fbcdeb7460c13073ced6b86227175a79b6a (patch) | |
| tree | aab89dc4faa0d4e2354e00fc295e96ee927393dc | |
| parent | 5e784f09ef3ea5ef3b428d667ca195c47f34db51 (diff) | |
| download | nimgen-7fbc8fbcdeb7460c13073ced6b86227175a79b6a.tar.gz nimgen-7fbc8fbcdeb7460c13073ced6b86227175a79b6a.zip | |
Style fixes
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | nimgen.nim | 1156 | ||||
| -rw-r--r-- | tests/nimgentest.nims | 7 |
3 files changed, 590 insertions, 575 deletions
@@ -48,6 +48,8 @@ To see examples of nimgen in action check out the following wrappers:- * download header file * [nimkerberos](https://github.com/genotrance/nimkerberos) - WinKerberos wrapper: [docs](http://nimgen.genotrance.com/nimkerberos) * git sparse checkout + * [nimpcre](https://github.com/genotrance/nimpcre) - PCRE wrapper: [docs](http://nimgen.genotrance.com/nimpcre) + * git checkout * [nimrax](https://github.com/genotrance/nimrax) - Radix tree wrapper: [docs](http://nimgen.genotrance.com/nimrax) * git checkout * [nimssl](https://github.com/genotrance/nimssl) - OpenSSL wrapper: [docs](http://nimgen.genotrance.com/nimssl) @@ -1,26 +1,17 @@ -import nre -import os -import ospaths -import osproc -import parsecfg -import pegs -import ropes -import sequtils -import streams -import strutils -import tables - -var DONE: seq[string] = @[] -var DONE_INLINE: seq[string] = @[] - -var CONFIG: Config -var FILTER = "" -var QUOTES = true -var OUTPUT = "" -var INCLUDES: seq[string] = @[] -var EXCLUDES: seq[string] = @[] -var RENAMES = initTable[string, string]() -var WILDCARDS = newConfig() +import nre, os, ospaths, osproc, parsecfg, pegs, ropes, sequtils, streams, strutils, tables + +var + DONE: seq[string] = @[] + DONE_INLINE: seq[string] = @[] + + CONFIG: Config + FILTER = "" + QUOTES = true + OUTPUT = "" + INCLUDES: seq[string] = @[] + EXCLUDES: seq[string] = @[] + RENAMES = initTable[string, string]() + WILDCARDS = newConfig() const DOC = """ Nimgen is a helper for c2nim to simpilfy and automate the wrapping of C libraries @@ -29,672 +20,691 @@ Usage: nimgen [options] <file.cfg>... Options: - -f delete all artifacts and regenerate + -f delete all artifacts and regenerate """ # ### # Helpers proc execProc(cmd: string): string = - var p = startProcess(cmd, options = {poStdErrToStdOut, poUsePath, poEvalCommand}) - - result = "" - var outp = outputStream(p) - var line = newStringOfCap(120).TaintedString - while true: - if outp.readLine(line): - result.add(line) - result.add("\n") - elif not running(p): break - - var x = p.peekExitCode() - if x != 0: - echo "Command failed: " & $x - echo cmd - echo result - quit(1) + result = "" + var + p = startProcess(cmd, options = {poStdErrToStdOut, poUsePath, poEvalCommand}) + + outp = outputStream(p) + line = newStringOfCap(120).TaintedString + + while true: + if outp.readLine(line): + result.add(line) + result.add("\n") + elif not running(p): break + + var x = p.peekExitCode() + if x != 0: + echo "Command failed: " & $x + echo cmd + echo result + quit(1) proc extractZip(zipfile: string) = - var cmd = "unzip -o $#" - if defined(Windows): - cmd = "powershell -nologo -noprofile -command \"& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('$#', '.'); }\"" + var cmd = "unzip -o $#" + if defined(Windows): + cmd = "powershell -nologo -noprofile -command \"& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('$#', '.'); }\"" - setCurrentDir(OUTPUT) - defer: setCurrentDir("..") + setCurrentDir(OUTPUT) + defer: setCurrentDir("..") - echo "Extracting " & zipfile - discard execProc(cmd % zipfile) + echo "Extracting " & zipfile + discard execProc(cmd % zipfile) proc downloadUrl(url: string) = - let file = url.extractFilename() - let ext = file.splitFile().ext.toLowerAscii() + let + file = url.extractFilename() + ext = file.splitFile().ext.toLowerAscii() - var cmd = "curl $# -o $#" - if defined(Windows): - cmd = "powershell wget $# -OutFile $#" + var cmd = "curl $# -o $#" + if defined(Windows): + cmd = "powershell wget $# -OutFile $#" - if not (ext == ".zip" and fileExists(OUTPUT/file)): - echo "Downloading " & file - discard execProc(cmd % [url, OUTPUT/file]) + if not (ext == ".zip" and fileExists(OUTPUT/file)): + echo "Downloading " & file + discard execProc(cmd % [url, OUTPUT/file]) - if ext == ".zip": - extractZip(file) + if ext == ".zip": + extractZip(file) proc gitReset() = - echo "Resetting Git repo" + echo "Resetting Git repo" - setCurrentDir(OUTPUT) - defer: setCurrentDir("..") + setCurrentDir(OUTPUT) + defer: setCurrentDir("..") - discard execProc("git reset --hard HEAD") + discard execProc("git reset --hard HEAD") proc gitRemotePull(url: string, pull=true) = - if dirExists(OUTPUT/".git"): - if pull: - gitReset() - return + if dirExists(OUTPUT/".git"): + if pull: + gitReset() + return - setCurrentDir(OUTPUT) - defer: setCurrentDir("..") + setCurrentDir(OUTPUT) + defer: setCurrentDir("..") - echo "Setting up Git repo" - discard execProc("git init .") - discard execProc("git remote add origin " & url) + echo "Setting up Git repo" + discard execProc("git init .") + discard execProc("git remote add origin " & url) - if pull: - echo "Checking out artifacts" - discard execProc("git pull --depth=1 origin master") + if pull: + echo "Checking out artifacts" + discard execProc("git pull --depth=1 origin master") proc gitSparseCheckout(plist: string) = - let sparsefile = ".git/info/sparse-checkout" - if fileExists(OUTPUT/sparsefile): - gitReset() - return + let sparsefile = ".git/info/sparse-checkout" + if fileExists(OUTPUT/sparsefile): + gitReset() + return - setCurrentDir(OUTPUT) - defer: setCurrentDir("..") + setCurrentDir(OUTPUT) + defer: setCurrentDir("..") - discard execProc("git config core.sparsecheckout true") - writeFile(sparsefile, plist) + discard execProc("git config core.sparsecheckout true") + writeFile(sparsefile, plist) - echo "Checking out artifacts" - discard execProc("git pull --depth=1 origin master") + echo "Checking out artifacts" + discard execProc("git pull --depth=1 origin master") proc getKey(ukey: string): tuple[key: string, val: bool] = - var kv = ukey.replace(re"\..*", "").split("-", 1) - if kv.len() == 1: - kv.add("") + var kv = ukey.replace(re"\..*", "").split("-", 1) + if kv.len() == 1: + kv.add("") - if (kv[1] == "") or - (kv[1] == "win" and defined(Windows)) or - (kv[1] == "lin" and defined(Linux)) or - (kv[1] == "osx" and defined(MacOSX)): - return (kv[0], true) + if (kv[1] == "") or + (kv[1] == "win" and defined(Windows)) or + (kv[1] == "lin" and defined(Linux)) or + (kv[1] == "osx" and defined(MacOSX)): + return (kv[0], true) - return (kv[0], false) + return (kv[0], false) # ### # File loction proc getNimout(file: string, rename=true): string = - result = file.splitFile().name.replace(re"[\-\.]", "_") & ".nim" - if OUTPUT != "": - result = OUTPUT/result + result = file.splitFile().name.replace(re"[\-\.]", "_") & ".nim" + if OUTPUT != "": + result = OUTPUT/result - if not rename: - return + if not rename: + return - if RENAMES.hasKey(file): - result = RENAMES[file] + if RENAMES.hasKey(file): + result = RENAMES[file] - if not dirExists(parentDir(result)): - createDir(parentDir(result)) + if not dirExists(parentDir(result)): + createDir(parentDir(result)) proc exclude(file: string): bool = - for excl in EXCLUDES: - if excl in file: - return true - return false + for excl in EXCLUDES: + if excl in file: + return true + return false proc search(file: string): string = - if exclude(file): - return "" - - result = file - if file.splitFile().ext == ".nim": - result = getNimout(file) - elif not fileExists(result) and not dirExists(result): - var found = false - for inc in INCLUDES: - result = inc/file - if fileExists(result) or dirExists(result): - found = true - break - if not found: - echo "File doesn't exist: " & file - quit(1) + if exclude(file): + return "" + + result = file + if file.splitFile().ext == ".nim": + result = getNimout(file) + elif not fileExists(result) and not dirExists(result): + var found = false + for inc in INCLUDES: + result = inc/file + if fileExists(result) or dirExists(result): + found = true + break + if not found: + echo "File doesn't exist: " & file + quit(1) - return result.replace(re"[\\/]", $DirSep) + return result.replace(re"[\\/]", $DirSep) # ### # Loading / unloading template withFile(file: string, body: untyped): untyped = - if fileExists(file): - var f: File - while true: - try: - f = open(file) - break - except: - sleep(100) + if fileExists(file): + var f: File + while true: + try: + f = open(file) + break + except: + sleep(100) - var contentOrig = f.readAll() - f.close() - var content {.inject.} = contentOrig + var contentOrig = f.readAll() + f.close() + var content {.inject.} = contentOrig - body + body - if content != contentOrig: - var f = open(file, fmWrite) - write(f, content) - f.close() - else: - echo "Missing file " & file + if content != contentOrig: + var f = open(file, fmWrite) + write(f, content) + f.close() + else: + echo "Missing file " & file # ### # Manipulating content proc prepend(file: string, data: string, search="") = - withFile(file): - if search == "": - content = data & content - else: - let idx = content.find(search) - if idx != -1: - content = content[0..<idx] & data & content[idx..<content.len()] + withFile(file): + if search == "": + content = data & content + else: + let idx = content.find(search) + if idx != -1: + content = content[0..<idx] & data & content[idx..<content.len()] proc append(file: string, data: string, search="") = - withFile(file): - if search == "": - content &= data - else: - let idx = content.find(search) - let idy = idx + search.len() - if idx != -1: - content = content[0..<idy] & data & content[idy..<content.len()] + withFile(file): + if search == "": + content &= data + else: + let idx = content.find(search) + let idy = idx + search.len() + if idx != -1: + content = content[0..<idy] & data & content[idy..<content.len()] proc freplace(file: string, pattern: string, repl="") = - withFile(file): - if pattern in content: - content = content.replace(pattern, repl) + withFile(file): + if pattern in content: + content = content.replace(pattern, repl) proc freplace(file: string, pattern: Regex, repl="") = - withFile(file): - if content.find(pattern).isSome(): - if "$#" in repl: - for m in content.findIter(pattern): - content = content.replace(m.match, repl % m.captures[0]) - else: - content = content.replace(pattern, repl) + withFile(file): + if content.find(pattern).isSome(): + if "$#" in repl: + for m in content.findIter(pattern): + content = content.replace(m.match, repl % m.captures[0]) + else: + content = content.replace(pattern, repl) proc comment(file: string, pattern: string, numlines: string) = - let ext = file.splitFile().ext.toLowerAscii() - let cmtchar = if ext == ".nim": "#" else: "//" - withFile(file): - var idx = content.find(pattern) - var num = 0 - try: - num = numlines.parseInt() - except ValueError: - echo "Bad comment value, should be integer: " & numlines - if idx != -1: - for i in 0 .. num-1: - if idx >= content.len(): - break - content = content[0..<idx] & cmtchar & content[idx..<content.len()] - while idx < content.len(): - idx += 1 - if content[idx] == '\L': - idx += 1 - break - -proc rename(file: string, renfile: string) = - if file.splitFile().ext == ".nim": - return + let + ext = file.splitFile().ext.toLowerAscii() + cmtchar = if ext == ".nim": "#" else: "//" + withFile(file): var - nimout = getNimout(file, false) - newname = renfile.replace("$nimout", extractFilename(nimout)) + idx = content.find(pattern) + num = 0 + + try: + num = numlines.parseInt() + except ValueError: + echo "Bad comment value, should be integer: " & numlines + if idx != -1: + for i in 0 .. num-1: + if idx >= content.len(): + break + content = content[0..<idx] & cmtchar & content[idx..<content.len()] + while idx < content.len(): + idx += 1 + if content[idx] == '\L': + idx += 1 + break - #if newname =~ peg"(!\$.)*{'$replace'\s*'('\s*{(!\,\S)+}\s*','\s*{(!\)\S)+}\s*')'}": - if newname =~ peg"(!\$.)*{'$replace'\s*'('\s*{(!\)\S)+}')'}": - var final = nimout.extractFilename() - for entry in matches[1].split(","): - let spl = entry.split("=") - if spl.len() != 2: - echo "Bad replace syntax: " & renfile - quit(1) +proc rename(file: string, renfile: string) = + if file.splitFile().ext == ".nim": + return + + var + nimout = getNimout(file, false) + newname = renfile.replace("$nimout", extractFilename(nimout)) + + #if newname =~ peg"(!\$.)*{'$replace'\s*'('\s*{(!\,\S)+}\s*','\s*{(!\)\S)+}\s*')'}": + if newname =~ peg"(!\$.)*{'$replace'\s*'('\s*{(!\)\S)+}')'}": + var final = nimout.extractFilename() + for entry in matches[1].split(","): + let spl = entry.split("=") + if spl.len() != 2: + echo "Bad replace syntax: " & renfile + quit(1) - var - srch = spl[0].strip() - repl = spl[1].strip() + var + srch = spl[0].strip() + repl = spl[1].strip() - final = final.replace(srch, repl) - newname = newname.replace(matches[0], final) + final = final.replace(srch, repl) + newname = newname.replace(matches[0], final) - RENAMES[file] = OUTPUT/newname + RENAMES[file] = OUTPUT/newname proc compile(dir="", file=""): string = - proc fcompile(file: string): string = - return "{.compile: \"$#\".}" % file.replace("\\", "/") + proc fcompile(file: string): string = + return "{.compile: \"$#\".}" % file.replace("\\", "/") - var data = "" - if dir != "" and dirExists(dir): - for f in walkFiles(dir / "*.c"): - data &= fcompile(f) & "\n" + var data = "" + if dir != "" and dirExists(dir): + for f in walkFiles(dir / "*.c"): + data &= fcompile(f) & "\n" - if file != "" and fileExists(file): - data &= fcompile(file) & "\n" + if file != "" and fileExists(file): + data &= fcompile(file) & "\n" - return data + return data proc fixFuncProtos(file: string) = - withFile(file): - for fp in content.findIter(re"(?m)(^.*?)[ ]*\(\*(.*?)\((.*?)\)\)[ \r\n]*\((.*?[\r\n]*.*?)\);"): - var tdout = "typedef $# (*type_$#)($#);\n" % [fp.captures[0], fp.captures[1], fp.captures[3]] & - "type_$# $#($#);" % [fp.captures[1], fp.captures[1], fp.captures[2]] - content = content.replace(fp.match, tdout) + withFile(file): + for fp in content.findIter(re"(?m)(^.*?)[ ]*\(\*(.*?)\((.*?)\)\)[ \r\n]*\((.*?[\r\n]*.*?)\);"): + var tdout = "typedef $# (*type_$#)($#);\n" % [fp.captures[0], fp.captures[1], fp.captures[3]] & + "type_$# $#($#);" % [fp.captures[1], fp.captures[1], fp.captures[2]] + content = content.replace(fp.match, tdout) # ### # Convert to Nim proc getIncls(file: string, inline=false): seq[string] = - result = @[] - if inline and file in DONE_INLINE: - return + result = @[] + if inline and file in DONE_INLINE: + return - withFile(file): - for f in content.findIter(re"(?m)^\s*#\s*include\s+(.*?)$"): - var inc = f.captures[0].strip() - if ((QUOTES and inc.contains("\"")) or (FILTER != "" and FILTER in inc)) and (not exclude(inc)): - result.add( - inc.replace(re"""[<>"]""", "").replace(re"\/[\*\/].*$", "").strip()) + withFile(file): + for f in content.findIter(re"(?m)^\s*#\s*include\s+(.*?)$"): + var inc = f.captures[0].strip() + if ((QUOTES and inc.contains("\"")) or (FILTER != "" and FILTER in inc)) and (not exclude(inc)): + result.add( + inc.replace(re"""[<>"]""", "").replace(re"\/[\*\/].*$", "").strip()) - result = result.deduplicate() + result = result.deduplicate() - DONE_INLINE.add(file) + DONE_INLINE.add(file) - if inline: - var sres = newSeq[string]() - for incl in result: - let sincl = search(incl) - if sincl == "": - continue + if inline: + var sres = newSeq[string]() + for incl in result: + let sincl = search(incl) + if sincl == "": + continue - sres.add(getIncls(sincl, inline)) - result.add(sres) + sres.add(getIncls(sincl, inline)) + result.add(sres) - result = result.deduplicate() + result = result.deduplicate() proc getDefines(file: string, inline=false): string = - result = "" - if inline: - var incls = getIncls(file, inline) - for incl in incls: - let sincl = search(incl) - if sincl != "": - echo "Inlining " & sincl - result &= getDefines(sincl) - withFile(file): - for def in content.findIter(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d\-.xf]+)(?:\r|//|/*).*?$"): - result &= def.captures[0] & "\n" + result = "" + if inline: + var incls = getIncls(file, inline) + for incl in incls: + let sincl = search(incl) + if sincl != "": + echo "Inlining " & sincl + result &= getDefines(sincl) + withFile(file): + for def in content.findIter(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d\-.xf]+)(?:\r|//|/*).*?$"): + result &= def.captures[0] & "\n" proc runPreprocess(file, ppflags, flags: string, inline: bool): string = - var pproc = "gcc" - if flags.contains("cpp"): - pproc = "g++" - var cmd = "$# -E $# $#" % [pproc, ppflags, file] - for inc in INCLUDES: - cmd &= " -I " & inc - - # Run preprocessor - var data = execProc(cmd) - - # Include content only from file - var rdata: Rope - var start = false - var sfile = file.replace("\\", "/") - if inline: - sfile = sfile.parentDir() - for line in data.splitLines(): - if line.strip() != "": - if line[0] == '#' and not line.contains("#pragma"): - start = false - if sfile in line.replace("\\", "/").replace("//", "/"): - start = true - if not ("\\" in line) and not ("/" in line) and extractFilename(sfile) in line: - start = true - else: - if start: - rdata.add( - line.replace("_Noreturn", "") - .replace("(())", "") - .replace("WINAPI", "") - .replace("__attribute__", "") - .replace("extern \"C\"", "") - .replace(re"\(\([_a-z]+?\)\)", "") - .replace(re"\(\(__format__[\s]*\(__[gnu_]*printf__, [\d]+, [\d]+\)\)\);", ";") & "\n" - ) - return $rdata + var + pproc = if flags.contains("cpp"): "g++" else: "gcc" + cmd = "$# -E $# $#" % [pproc, ppflags, file] + + for inc in INCLUDES: + cmd &= " -I " & inc + + # Run preprocessor + var data = execProc(cmd) + + # Include content only from file + var + rdata: Rope + start = false + sfile = file.replace("\\", "/") + + if inline: + sfile = sfile.parentDir() + for line in data.splitLines(): + if line.strip() != "": + if line[0] == '#' and not line.contains("#pragma"): + start = false + if sfile in line.replace("\\", "/").replace("//", "/"): + start = true + if not ("\\" in line) and not ("/" in line) and extractFilename(sfile) in line: + start = true + else: + if start: + rdata.add( + line.replace("_Noreturn", "") + .replace("(())", "") + .replace("WINAPI", "") + .replace("__attribute__", "") + .replace("extern \"C\"", "") + .replace(re"\(\([_a-z]+?\)\)", "") + .replace(re"\(\(__format__[\s]*\(__[gnu_]*printf__, [\d]+, [\d]+\)\)\);", ";") & "\n" + ) + return $rdata proc runCtags(file: string): string = - var cmd = "ctags -o - --fields=+S+K --c-kinds=p --file-scope=no " & file - var fps = execProc(cmd) - - var fdata = "" - for line in fps.splitLines(): - var spl = line.split(re"\t") - if spl.len() > 4: - if spl[0] != "main": - var fn = "" - var match = spl[2].find(re"/\^(.*?)\(") - if match.isSome(): - fn = match.get().captures[0] - fn &= spl[4].replace("signature:", "") & ";" - fdata &= fn & "\n" - - return fdata + var + cmd = "ctags -o - --fields=+S+K --c-kinds=p --file-scope=no " & file + fps = execProc(cmd) + fdata = "" + + for line in fps.splitLines(): + var spl = line.split(re"\t") + if spl.len() > 4: + if spl[0] != "main": + var fn = "" + var match = spl[2].find(re"/\^(.*?)\(") + if match.isSome(): + fn = match.get().captures[0] + fn &= spl[4].replace("signature:", "") & ";" + fdata &= fn & "\n" + + return fdata proc runFile(file: string, cfgin: OrderedTableRef) proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, ctags, defines: bool, dynlib, compile, pragma: seq[string] = @[]) = - var file = search(fl) - if file == "": - return - - if file in DONE: - return - - echo "Processing $# => $#" % [file, outfile] - DONE.add(file) - - fixFuncProtos(file) - - var incout = "" - if recurse: - var incls = getIncls(file) - for inc in incls: - var cfg = newOrderedTable[string, string]() - if flags != "": cfg["flags"] = flags - if ppflags != "": cfg["ppflags"] = ppflags - if recurse: cfg["recurse"] = $recurse - if preprocess: cfg["preprocess"] = $preprocess - if ctags: cfg["ctags"] = $ctags - if defines: cfg["defines"] = $defines - for i in dynlib: - cfg["dynlib." & i] = i - runFile(inc, cfg) - - incout &= "import $#\n" % inc.search().getNimout()[0 .. ^5] #inc.splitFile().name.replace(re"[\-\.]", "_") & "\n" - - var cfile = file - if preprocess: - cfile = "temp-$#.c" % [outfile.extractFilename()] - writeFile(cfile, runPreprocess(file, ppflags, flags, inline)) - elif ctags: - cfile = "temp-$#.c" % [outfile.extractFilename()] - writeFile(cfile, runCtags(file)) - - if defines and (preprocess or ctags): - prepend(cfile, getDefines(file, inline)) - - var extflags = "" - var passC = "" - var outlib = "" - var outpragma = "" - - passC = "import strutils\n" - for inc in INCLUDES: - passC &= ("""{.passC: "-I\"" & gorge("nimble path $#").strip() & "/$#\"".}""" % [OUTPUT, inc]) & "\n" - - for prag in pragma: - outpragma &= "{." & prag & ".}\n" - - let fname = file.splitFile().name.replace(re"[\.\-]", "_") - if dynlib.len() != 0: - let win = "when defined(Windows):\n" - let lin = "when defined(Linux):\n" - let osx = "when defined(MacOSX):\n" - var winlib, linlib, osxlib: string = "" - for dl in dynlib: - let lib = " const dynlib$# = \"$#\"\n" % [fname, dl] - let ext = dl.splitFile().ext - if ext == ".dll": - winlib &= lib - elif ext == ".so": - linlib &= lib - elif ext == ".dylib": - osxlib &= lib - - if winlib != "": - outlib &= win & winlib & "\n" - if linlib != "": - outlib &= lin & linlib & "\n" - if osxlib != "": - outlib &= osx & osxlib & "\n" - - if outlib != "": - extflags &= " --dynlib:dynlib$#" % fname + var file = search(fl) + if file == "": + return + + if file in DONE: + return + + echo "Processing $# => $#" % [file, outfile] + DONE.add(file) + + fixFuncProtos(file) + + var incout = "" + if recurse: + var incls = getIncls(file) + for inc in incls: + var cfg = newOrderedTable[string, string]() + if flags != "": cfg["flags"] = flags + if ppflags != "": cfg["ppflags"] = ppflags + if recurse: cfg["recurse"] = $recurse + if preprocess: cfg["preprocess"] = $preprocess + if ctags: cfg["ctags"] = $ctags + if defines: cfg["defines"] = $defines + for i in dynlib: + cfg["dynlib." & i] = i + runFile(inc, cfg) + + incout &= "import $#\n" % inc.search().getNimout()[0 .. ^5] #inc.splitFile().name.replace(re"[\-\.]", "_") & "\n" + + var cfile = file + if preprocess: + cfile = "temp-$#.c" % [outfile.extractFilename()] + writeFile(cfile, runPreprocess(file, ppflags, flags, inline)) + elif ctags: + cfile = "temp-$#.c" % [outfile.extractFilename()] + writeFile(cfile, runCtags(file)) + + if defines and (preprocess or ctags): + prepend(cfile, getDefines(file, inline)) + + var + extflags = "" + passC = "" + outlib = "" + outpragma = "" + + passC = "import strutils\n" + for inc in INCLUDES: + passC &= ("""{.passC: "-I\"" & gorge("nimble path $#").strip() & "/$#\"".}""" % [OUTPUT, inc]) & "\n" + + for prag in pragma: + outpragma &= "{." & prag & ".}\n" + + let fname = file.splitFile().name.replace(re"[\.\-]", "_") + if dynlib.len() != 0: + let + win = "when defined(Windows):\n" + lin = "when defined(Linux):\n" + osx = "when defined(MacOSX):\n" + + var winlib, linlib, osxlib: string = "" + for dl in dynlib: + let + lib = " const dynlib$# = \"$#\"\n" % [fname, dl] + ext = dl.splitFile().ext + + if ext == ".dll": + winlib &= lib + elif ext == ".so": + linlib &= lib + elif ext == ".dylib": + osxlib &= lib + + if winlib != "": + outlib &= win & winlib & "\n" + if linlib != "": + outlib &= lin & linlib & "\n" + if osxlib != "": + outlib &= osx & osxlib & "\n" + + if outlib != "": + extflags &= " --dynlib:dynlib$#" % fname + else: + passC &= "const header$# = \"$#\"\n" % [fname, fl] + extflags = "--header:header$#" % fname + + # Run c2nim on generated file + var cmd = "c2nim $# $# --out:$# $#" % [flags, extflags, outfile, cfile] + when defined(windows): + cmd = "cmd /c " & cmd + discard execProc(cmd) + + if preprocess or ctags: + try: + removeFile(cfile) + except: + discard + + # Import nim modules + if recurse: + prepend(outfile, incout) + + # Nim doesn't like {.cdecl.} for type proc() + freplace(outfile, re"(?m)(.*? = proc.*?){.cdecl.}", "$#") + freplace(outfile, " {.cdecl.})", ")") + + # Include {.compile.} directives + for cpl in compile: + let fcpl = search(cpl) + if getFileInfo(fcpl).kind == pcFile: + prepend(outfile, compile(file=fcpl)) else: - passC &= "const header$# = \"$#\"\n" % [fname, fl] - extflags = "--header:header$#" % fname - - # Run c2nim on generated file - var cmd = "c2nim $# $# --out:$# $#" % [flags, extflags, outfile, cfile] - when defined(windows): - cmd = "cmd /c " & cmd - discard execProc(cmd) - - if preprocess or ctags: - try: - removeFile(cfile) - except: - discard - - # Import nim modules - if recurse: - prepend(outfile, incout) - - # Nim doesn't like {.cdecl.} for type proc() - freplace(outfile, re"(?m)(.*? = proc.*?){.cdecl.}", "$#") - freplace(outfile, " {.cdecl.})", ")") - - # Include {.compile.} directives - for cpl in compile: - let fcpl = search(cpl) - if getFileInfo(fcpl).kind == pcFile: - prepend(outfile, compile(file=fcpl)) - else: - prepend(outfile, compile(dir=fcpl)) + prepend(outfile, compile(dir=fcpl)) - # Add any pragmas - if outpragma != "": - prepend(outfile, outpragma) + # Add any pragmas + if outpragma != "": + prepend(outfile, outpragma) - # Add header file and include paths - if passC != "": - prepend(outfile, passC) + # Add header file and include paths + if passC != "": + prepend(outfile, passC) - # Add dynamic library - if outlib != "": - prepend(outfile, outlib) + # Add dynamic library + if outlib != "": + prepend(outfile, outlib) # ### # Processor proc runFile(file: string, cfgin: OrderedTableRef) = - var cfg = cfgin - var sfile = search(file) - - for pattern in WILDCARDS.keys(): - let pat = pattern.replace(".", "\\.").replace("*", ".*").replace("?", ".?") - if file.find(re(pat)).isSome(): - echo "Appending " & file & " " & pattern - for key in WILDCARDS[pattern].keys(): - cfg[key & "." & pattern] = WILDCARDS[pattern][key] - - var srch = "" - var compile: seq[string] = @[] - var dynlib: seq[string] = @[] - var pragma: seq[string] = @[] - for act in cfg.keys(): - let (action, val) = getKey(act) - if val == true: - if action == "create": - createDir(file.splitPath().head) - writeFile(file, cfg[act]) - elif action in @["prepend", "append", "replace", "comment", "rename", "compile", "dynlib", "pragma"] and sfile != "": - if action == "prepend": - if srch != "": - prepend(sfile, cfg[act], cfg[srch]) - else: - prepend(sfile, cfg[act]) - elif action == "append": - if srch != "": - append(sfile, cfg[act], cfg[srch]) - else: - append(sfile, cfg[act]) - elif action == "replace": - if srch != "": - freplace(sfile, cfg[srch], cfg[act]) - elif action == "comment": - if srch != "": - comment(sfile, cfg[srch], cfg[act]) - elif action == "rename": - rename(sfile, cfg[act]) - elif action == "compile": - compile.add(cfg[act]) - elif action == "dynlib": - dynlib.add(cfg[act]) - elif action == "pragma": - pragma.add(cfg[act]) - srch = "" - elif action == "search": - srch = act - - if file.splitFile().ext != ".nim": - var recurse = false - var inline = false - var preprocess = false - var ctags = false - var defines = false - var noprocess = false - var flags = "--stdcall" - var ppflags = "" - - for act in cfg.keys(): - if cfg[act] == "true": - if act == "recurse": - recurse = true - elif act == "inline": - inline = true - elif act == "preprocess": - preprocess = true - elif act == "ctags": - ctags = true - elif act == "defines": - defines = true - elif act == "noprocess": - noprocess = true - elif act == "flags": - flags = cfg[act] - elif act == "ppflags": - ppflags = cfg[act] - - if recurse and inline: - echo "Cannot use recurse and inline simultaneously" - quit(1) + var + cfg = cfgin + sfile = search(file) + + for pattern in WILDCARDS.keys(): + let pat = pattern.replace(".", "\\.").replace("*", ".*").replace("?", ".?") + if file.find(re(pat)).isSome(): + echo "Appending " & file & " " & pattern + for key in WILDCARDS[pattern].keys(): + cfg[key & "." & pattern] = WILDCARDS[pattern][key] + + var + srch = "" + compile: seq[string] = @[] + dynlib: seq[string] = @[] + pragma: seq[string] = @[] + + for act in cfg.keys(): + let (action, val) = getKey(act) + if val == true: + if action == "create": + createDir(file.splitPath().head) + writeFile(file, cfg[act]) + elif action in @["prepend", "append", "replace", "comment", "rename", "compile", "dynlib", "pragma"] and sfile != "": + if action == "prepend": + if srch != "": + prepend(sfile, cfg[act], cfg[srch]) + else: + prepend(sfile, cfg[act]) + elif action == "append": + if srch != "": + append(sfile, cfg[act], cfg[srch]) + else: + append(sfile, cfg[act]) + elif action == "replace": + if srch != "": + freplace(sfile, cfg[srch], cfg[act]) + elif action == "comment": + if srch != "": + comment(sfile, cfg[srch], cfg[act]) + elif action == "rename": + rename(sfile, cfg[act]) + elif action == "compile": + compile.add(cfg[act]) + elif action == "dynlib": + dynlib.add(cfg[act]) + elif action == "pragma": + pragma.add(cfg[act]) + srch = "" + elif action == "search": + srch = act + + if file.splitFile().ext != ".nim": + var + recurse = false + inline = false + preprocess = false + ctags = false + defines = false + noprocess = false + flags = "--stdcall" + ppflags = "" - if not noprocess: - c2nim(file, getNimout(sfile), flags, ppflags, recurse, inline, preprocess, ctags, defines, dynlib, compile, pragma) + for act in cfg.keys(): + if cfg[act] == "true": + if act == "recurse": + recurse = true + elif act == "inline": + inline = true + elif act == "preprocess": + preprocess = true + elif act == "ctags": + ctags = true + elif act == "defines": + defines = true + elif act == "noprocess": + noprocess = true + elif act == "flags": + flags = cfg[act] + elif act == "ppflags": + ppflags = cfg[act] + + if recurse and inline: + echo "Cannot use recurse and inline simultaneously" + quit(1) + + if not noprocess: + c2nim(file, getNimout(sfile), flags, ppflags, recurse, inline, preprocess, ctags, defines, dynlib, compile, pragma) proc runCfg(cfg: string) = - if not fileExists(cfg): - echo "Config doesn't exist: " & cfg - quit(1) + if not fileExists(cfg): + echo "Config doesn't exist: " & cfg + quit(1) + + CONFIG = loadConfig(cfg) + + if CONFIG.hasKey("n.global"): + if CONFIG["n.global"].hasKey("output"): + OUTPUT = CONFIG["n.global"]["output"] + if dirExists(OUTPUT): + if "-f" in commandLineParams(): + try: + removeDir(OUTPUT) + except OSError: + echo "Directory in use: " & OUTPUT + quit(1) + else: + for f in walkFiles(OUTPUT/"*.nim"): + try: + removeFile(f) + except OSError: + echo "Unable to delete: " & f + quit(1) + createDir(OUTPUT) + + if CONFIG["n.global"].hasKey("filter"): + FILTER = CONFIG["n.global"]["filter"] + if CONFIG["n.global"].hasKey("quotes"): + if CONFIG["n.global"]["quotes"] == "false": + QUOTES = false + + if CONFIG.hasKey("n.include"): + for inc in CONFIG["n.include"].keys(): + INCLUDES.add(inc) + + if CONFIG.hasKey("n.exclude"): + for excl in CONFIG["n.exclude"].keys(): + EXCLUDES.add(excl) + + if CONFIG.hasKey("n.prepare"): + for prep in CONFIG["n.prepare"].keys(): + let (key, val) = getKey(prep) + if val == true: + if key == "download": + downloadUrl(CONFIG["n.prepare"][prep]) + elif key == "extract": + extractZip(CONFIG["n.prepare"][prep]) + elif key == "git": + gitRemotePull(CONFIG["n.prepare"][prep]) + elif key == "gitremote": + gitRemotePull(CONFIG["n.prepare"][prep], false) + elif key == "gitsparse": + gitSparseCheckout(CONFIG["n.prepare"][prep]) + elif key == "execute": + discard execProc(CONFIG["n.prepare"][prep]) + + if CONFIG.hasKey("n.wildcard"): + var wildcard = "" + for wild in CONFIG["n.wildcard"].keys(): + let (key, val) = getKey(wild) + if val == true: + if key == "wildcard": + wildcard = CONFIG["n.wildcard"][wild] + else: + WILDCARDS.setSectionKey(wildcard, wild, CONFIG["n.wildcard"][wild]) + + for file in CONFIG.keys(): + if file in @["n.global", "n.include", "n.exclude", "n.prepare", "n.wildcard"]: + continue - CONFIG = loadConfig(cfg) - - if CONFIG.hasKey("n.global"): - if CONFIG["n.global"].hasKey("output"): - OUTPUT = CONFIG["n.global"]["output"] - if dirExists(OUTPUT): - if "-f" in commandLineParams(): - try: - removeDir(OUTPUT) - except OSError: - echo "Directory in use: " & OUTPUT - quit(1) - else: - for f in walkFiles(OUTPUT/"*.nim"): - try: - removeFile(f) - except OSError: - echo "Unable to delete: " & f - quit(1) - createDir(OUTPUT) - - if CONFIG["n.global"].hasKey("filter"): - FILTER = CONFIG["n.global"]["filter"] - if CONFIG["n.global"].hasKey("quotes"): - if CONFIG["n.global"]["quotes"] == "false": - QUOTES = false - - if CONFIG.hasKey("n.include"): - for inc in CONFIG["n.include"].keys(): - INCLUDES.add(inc) - - if CONFIG.hasKey("n.exclude"): - for excl in CONFIG["n.exclude"].keys(): - EXCLUDES.add(excl) - - if CONFIG.hasKey("n.prepare"): - for prep in CONFIG["n.prepare"].keys(): - let (key, val) = getKey(prep) - if val == true: - if key == "download": - downloadUrl(CONFIG["n.prepare"][prep]) - elif key == "extract": - extractZip(CONFIG["n.prepare"][prep]) - elif key == "git": - gitRemotePull(CONFIG["n.prepare"][prep]) - elif key == "gitremote": - gitRemotePull(CONFIG["n.prepare"][prep], false) - elif key == "gitsparse": - gitSparseCheckout(CONFIG["n.prepare"][prep]) - elif key == "execute": - discard execProc(CONFIG["n.prepare"][prep]) - - if CONFIG.hasKey("n.wildcard"): - var wildcard = "" - for wild in CONFIG["n.wildcard"].keys(): - let (key, val) = getKey(wild) - if val == true: - if key == "wildcard": - wildcard = CONFIG["n.wildcard"][wild] - else: - WILDCARDS.setSectionKey(wildcard, wild, CONFIG["n.wildcard"][wild]) - - for file in CONFIG.keys(): - if file in @["n.global", "n.include", "n.exclude", "n.prepare", "n.wildcard"]: - continue - - runFile(file, CONFIG[file]) + runFile(file, CONFIG[file]) # ### # Main loop for i in commandLineParams(): - if i != "-f": - runCfg(i) + if i != "-f": + runCfg(i) diff --git a/tests/nimgentest.nims b/tests/nimgentest.nims index 2001ef2..f5136c6 100644 --- a/tests/nimgentest.nims +++ b/tests/nimgentest.nims @@ -2,8 +2,11 @@ import distros import ospaths import strutils -var full = false -var comps = @["libsvm", "nim7z", "nimarchive", "nimbass", "nimbigwig", "nimfuzz", "nimrax", "nimssl", "nimssh2"] +var + full = false + comps = @["libsvm", "nim7z", "nimarchive", "nimbass", "nimbigwig", "nimfuzz", + "nimpcre", "nimrax", "nimssl", "nimssh2"] + if detectOs(Windows): comps.add("nimkerberos") |
