diff options
| author | Ganesh Viswanathan <dev@genotrance.com> | 2017-11-13 16:42:56 -0600 |
|---|---|---|
| committer | Ganesh Viswanathan <dev@genotrance.com> | 2017-11-13 16:42:56 -0600 |
| commit | a02cbbeebaf2c56850e6a6d1507063bf068ae0cb (patch) | |
| tree | b08ad75e6040dd811fc4dcce3e76a48c0c903241 | |
| parent | a515978acfa21961a9f797b365eaaea391803c81 (diff) | |
| download | nimgen-a02cbbeebaf2c56850e6a6d1507063bf068ae0cb.tar.gz nimgen-a02cbbeebaf2c56850e6a6d1507063bf068ae0cb.zip | |
- Support for C++ wrapping
- Fix module naming
- Remove file caching
- Fix bug that was deleting .nim file
- Add test case
| -rw-r--r-- | nimgen.nim | 174 | ||||
| -rw-r--r-- | nimgen.nimble | 7 | ||||
| -rw-r--r-- | tests/nimgentest.nims | 8 |
3 files changed, 97 insertions, 92 deletions
@@ -9,7 +9,6 @@ import streams import strutils import tables -var FILES: TableRef[string, string] = newTable[string, string]() var DONE: seq[string] = @[] var CONFIG: Config @@ -44,10 +43,9 @@ proc execProc(cmd: string): string = # File loction proc getnimout(file: string): string = - var nimout = file.splitFile().name & ".nim" + var nimout = file.splitFile().name.replace(re"[\-\.]", "_") & ".nim" if OUTPUT != "": nimout = OUTPUT/nimout - removeFile(nimout) return nimout @@ -80,61 +78,64 @@ proc search(file: string): string = # ### # Loading / unloading -proc loadfile(file: string) = - if FILES.hasKey(file): - return +template withFile(file: string, body: untyped): untyped = + if fileExists(file): + var f: File + while true: + try: + f = open(file) + break + except: + sleep(100) - FILES[file] = readFile(file) + var contentOrig = f.readAll() + f.close() + var content {.inject.} = contentOrig -proc savefile(file: string) = - try: - if FILES.hasKey(file): - writeFile(file, FILES[file]) - - FILES.del(file) - except: - echo "Failed to save " & file - echo getCurrentExceptionMsg() - -proc savefiles() = - for file in FILES.keys(): - savefile(file) + body + + 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="") = - loadfile(file) - if search == "": - FILES[file] = data & FILES[file] - else: - let idx = FILES[file].find(search) - if idx != -1: - FILES[file] = FILES[file][0..<idx] & data & FILES[file][idx..<FILES[file].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="") = - loadfile(file) - if search == "": - FILES[file] &= data - else: - let idx = FILES[file].find(search) - let idy = idx + search.len() - if idx != -1: - FILES[file] = FILES[file][0..<idy] & data & FILES[file][idy..<FILES[file].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="") = - loadfile(file) - if pattern in FILES[file]: - FILES[file] = FILES[file].replace(pattern, repl) + withFile(file): + if pattern in content: + content = content.replace(pattern, repl) proc freplace(file: string, pattern: Regex, repl="") = - loadfile(file) - if FILES[file].find(pattern).isSome(): - if "$#" in repl: - for m in FILES[file].findIter(pattern): - FILES[file] = FILES[file].replace(m.match, repl % m.captures[0]) - else: - FILES[file] = FILES[file].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 compile(dir="", file=""): string = proc fcompile(file: string): string = @@ -151,39 +152,36 @@ proc compile(dir="", file=""): string = return data proc fixfuncprotos(file: string) = - var data = readFile(file) - - var edit = false - for fp in data.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]] - data = data.replace(fp.match, tdout) - edit = true - - if edit: - writeFile(file, data) + 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): seq[string] = - loadfile(file) result = @[] - for f in FILES[file].findIter(re"(?m)^\s*#\s*include\s+(.*?)$"): - var inc = f.captures[0].replace(re"""[<>"]""", "").strip() - if FILTER in inc and (not exclude(inc)): - result.add(inc) + withFile(file): + for f in content.findIter(re"(?m)^\s*#\s*include\s+(.*?)$"): + var inc = f.captures[0].replace(re"""[<>"]""", "").strip() + if FILTER in inc and (not exclude(inc)): + result.add(inc) - result = result.deduplicate() + result = result.deduplicate() proc getdefines(file: string): string = - loadfile(file) - result = "" - for def in FILES[file].findIter(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d.x]+)(?:\r|//|/*).*?$"): - result &= def.captures[0] & "\n" - -proc preprocess(file, ppflags: string): string = - var cmd = "gcc -E $# $#" % [ppflags, file] + withFile(file): + result = "" + for def in content.findIter(re"(?m)^(\s*#\s*define\s+[\w\d_]+\s+[\d.x]+)(?:\r|//|/*).*?$"): + result &= def.captures[0] & "\n" + +proc preprocess(file, ppflags, flags: string): string = + var pproc = "gcc" + if flags.contains("cpp"): + pproc = "g++" + var cmd = "$# -E $# $#" % [pproc, ppflags, file] for inc in INCLUDES: cmd &= " -I " & inc @@ -229,7 +227,7 @@ proc ctags(file: string): string = return fdata -proc c2nim(fl, outfile, flags, ppflags: string, recurse, preproc, ctag, define: bool, compile, dynlib: seq[string] = @[]) = +proc c2nim(fl, outfile, flags, ppflags: string, recurse, preproc, ctag, define: bool, dynlib, compile: seq[string] = @[]) = var file = search(fl) if file == "": return @@ -246,30 +244,27 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, preproc, ctag, define: if recurse: var incls = getincls(file) for inc in incls: - incout &= "import " & inc.splitFile().name.replace(re"[-_\.]", "") & "\n" - c2nim(inc, getnimout(inc), flags, ppflags, recurse, preproc, ctag, define, compile, dynlib) + incout &= "import " & inc.splitFile().name.replace(re"[\-\.]", "_") & "\n" + c2nim(inc, getnimout(inc), flags, ppflags, recurse, preproc, ctag, define, dynlib) var cfile = file if preproc: - cfile = "temp.c" - writeFile(cfile, preprocess(file, ppflags)) + cfile = "temp-$#.c" % [outfile.extractFilename()] + writeFile(cfile, preprocess(file, ppflags, flags)) elif ctag: - cfile = "temp.c" + cfile = "temp-$#.c" % [outfile.extractFilename()] writeFile(cfile, ctags(file)) if define and (preproc or ctag): prepend(cfile, getdefines(file)) - savefile(cfile) var extflags = "" var passC = "" var outlib = "" - if compile.len() != 0: - passC = "import strutils\n" - for inc in INCLUDES: - passC &= ("""{.passC: "-I\"" & gorge("nimble path $#").strip() & "/$#\"".}""" % [OUTPUT, inc]) & "\n" - passC &= "{.push importc.}\n{.push header: \"$#\".}\n" % fl - #extflags = "--header:\"$#\"" % fl + + passC = "import strutils\n" + for inc in INCLUDES: + passC &= ("""{.passC: "-I\"" & gorge("nimble path $#").strip() & "/$#\"".}""" % [OUTPUT, inc]) & "\n" if dynlib.len() != 0: let win = "when defined(Windows):\n" @@ -293,6 +288,9 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, preproc, ctag, define: if outlib != "": extflags &= " --dynlib:dynlib$#" % OUTPUT + else: + passC &= "const header$# = \"$#\"\n" % [OUTPUT, fl] + extflags = "--header:header$#" % OUTPUT # Run c2nim on generated file var cmd = "c2nim $# $# --out:$# $#" % [flags, extflags, outfile, cfile] @@ -300,9 +298,9 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, preproc, ctag, define: cmd = "cmd /c " & cmd discard execProc(cmd) - if preproc: + if preproc or ctag: try: - removeFile("temp.c") + removeFile(cfile) except: discard @@ -324,7 +322,6 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, preproc, ctag, define: # Add header file and include paths if passC != "": prepend(outfile, passC) - append(outfile, "\n{.pop.}\n{.pop.}\n") # Add dynamic library if outlib != "": @@ -399,9 +396,6 @@ proc runcfg(cfg: string) = var flags = "--stdcall" var ppflags = "" - # Save C files in case they have changed - savefile(sfile) - for act in CONFIG[file].keys(): if CONFIG[file][act] == "true": if act == "recurse": @@ -420,7 +414,7 @@ proc runcfg(cfg: string) = ppflags = CONFIG[file][act] if not noprocess: - c2nim(file, getnimout(file), flags, ppflags, recurse, preproc, ctag, define, compile, dynlib) + c2nim(file, getnimout(file), flags, ppflags, recurse, preproc, ctag, define, dynlib, compile) # ### # Main loop @@ -431,5 +425,3 @@ if paramCount() == 0: for i in 1..paramCount(): runcfg(paramStr(i)) - -savefiles() diff --git a/nimgen.nimble b/nimgen.nimble index d849bf5..af6e501 100644 --- a/nimgen.nimble +++ b/nimgen.nimble @@ -5,8 +5,13 @@ author = "genotrance" description = "c2nim helper to simpilfy and automate the wrapping of C libraries" license = "MIT" +skipDirs = @["tests"] + # Dependencies requires "nim >= 0.16.0", "c2nim >= 0.9.13" -bin = @["nimgen"]
\ No newline at end of file +bin = @["nimgen"] + +task test, "Test nimgen": + exec "nim e tests/nimgentest.nims" diff --git a/tests/nimgentest.nims b/tests/nimgentest.nims new file mode 100644 index 0000000..693d133 --- /dev/null +++ b/tests/nimgentest.nims @@ -0,0 +1,8 @@ +import ospaths +import strutils + +for comp in @["nimbass", "nimfuzz", "nimssl"]: + cd(".."/comp) + exec "nimble install -y" + exec "nimble test" + cd(".."/"nimgen") |
