Comment lines feature, remove docopt

This commit is contained in:
Ganesh Viswanathan 2018-03-08 22:28:41 -06:00
commit bcace601d3
4 changed files with 93 additions and 52 deletions

View file

@ -12,7 +12,7 @@ This will download, build and install nimgen in the standard Nimble package loca
__Usage__ __Usage__
Nimgen is driven by a simple .cfg file that is read using the Nim [parsecfg](https://nim-lang.org/docs/parsecfg.html) module. The sections of the file are described further below. Nimgen is driven by a simple .cfg file that is read using the Nim [parsecfg](https://nim-lang.org/docs/parsecfg.html) module. The sections of the file are described further below.
```> nimgen package.cfg``` ```> nimgen package.cfg```
@ -31,20 +31,25 @@ __Capabilities & Limitations__
Nimgen supports compiling in C/C++ sources as well as loading in dynamic libraries at this time. Support for static libraries (.a, .lib) are still to come. Nimgen supports compiling in C/C++ sources as well as loading in dynamic libraries at this time. Support for static libraries (.a, .lib) are still to come.
To see examples of nimgen in action check out the following wrappers:- To see examples of nimgen in action check out the following wrappers:-
* [nimbass](https://github.com/genotrance/nimbass) - BASS audio wrapper * Link with a dynamic library
* download ZIP with headers and binary * [nimbass](https://github.com/genotrance/nimbass) - BASS audio wrapper
* link with a dynamic library * download ZIP with headers and binary
* [nimfuzz](https://github.com/genotrance/nimfuzz) - fts_fuzzy_match wrapper
* git checkout
* Compile C code into binary
* [nimssl](https://github.com/genotrance/nimssl) - OpenSSL wrapper
* git sparse checkout
* Compile C code into binary
* [nimssh2](https://github.com/genotrance/nimssh2) - libssh2 wrapper
* git sparse checkout
* Compile libssh2 in as static binary
Nimgen only supports the ```gcc``` preprocessor at this time. Support for detecting and using other preprocessors is TBD. * Compile C code into binary
* [nimfuzz](https://github.com/genotrance/nimfuzz) - fts_fuzzy_match wrapper
* git checkout
* [nimkerberos](https://github.com/genotrance/nimkerberos) - WinKerberos wrapper
* git sparse checkout
* [nimssl](https://github.com/genotrance/nimssl) - OpenSSL wrapper
* git sparse checkout
* [libsvm](https://github.com/genotrance/libsvm) - libsvm wrapper
* git sparse checkout
* Compile in as static binary
* [nimssh2](https://github.com/genotrance/nimssh2) - libssh2 wrapper
* git sparse checkout
Nimgen only supports the ```gcc``` preprocessor at this time. Support for detecting and using other preprocessors will be based on interest.
__Config file__ __Config file__
@ -130,6 +135,8 @@ The following keys apply to library source code (before processing) and generate
```replace``` = string value to replace search string in file ```replace``` = string value to replace search string in file
```comment``` = number of lines to comment from search location
__Feedback__ __Feedback__
Nimgen is a work in progress and any feedback or suggestions are welcome. It is hosted on [GitHub](https://github.com/genotrance/nimgen) with an MIT license so issues, forks and PRs are most appreciated. Nimgen is a work in progress and any feedback or suggestions are welcome. It is hosted on [GitHub](https://github.com/genotrance/nimgen) with an MIT license so issues, forks and PRs are most appreciated.

View file

@ -1,4 +1,3 @@
import docopt
import nre import nre
import os import os
import ospaths import ospaths
@ -31,8 +30,6 @@ Options:
-f delete all artifacts and regenerate -f delete all artifacts and regenerate
""" """
let ARGS = docopt(DOC)
# ### # ###
# Helpers # Helpers
@ -90,7 +87,7 @@ proc gitReset() =
discard execProc("git reset --hard HEAD") discard execProc("git reset --hard HEAD")
proc gitRemotePull(url: string, pull=true) = proc gitRemotePull(url: string, pull=true) =
if dirExists(OUTPUT): if dirExists(OUTPUT/".git"):
if pull: if pull:
gitReset() gitReset()
return return
@ -114,7 +111,7 @@ proc gitSparseCheckout(plist: string) =
setCurrentDir(OUTPUT) setCurrentDir(OUTPUT)
defer: setCurrentDir("..") defer: setCurrentDir("..")
discard execProc("git config core.sparsecheckout true") discard execProc("git config core.sparsecheckout true")
writeFile(sparsefile, plist) writeFile(sparsefile, plist)
@ -157,11 +154,11 @@ proc search(file: string): string =
result = file result = file
if file.splitFile().ext == ".nim": if file.splitFile().ext == ".nim":
result = getNimout(file) result = getNimout(file)
elif not fileExists(result): elif not fileExists(result) and not dirExists(result):
var found = false var found = false
for inc in INCLUDES: for inc in INCLUDES:
result = inc/file result = inc/file
if fileExists(result): if fileExists(result) or dirExists(result):
found = true found = true
break break
if not found: if not found:
@ -169,7 +166,7 @@ proc search(file: string): string =
quit(1) quit(1)
return result.replace(re"[\\/]", $DirSep) return result.replace(re"[\\/]", $DirSep)
# ### # ###
# Loading / unloading # Loading / unloading
@ -217,7 +214,7 @@ proc append(file: string, data: string, search="") =
let idy = idx + search.len() let idy = idx + search.len()
if idx != -1: if idx != -1:
content = content[0..<idy] & data & content[idy..<content.len()] content = content[0..<idy] & data & content[idy..<content.len()]
proc freplace(file: string, pattern: string, repl="") = proc freplace(file: string, pattern: string, repl="") =
withFile(file): withFile(file):
if pattern in content: if pattern in content:
@ -232,15 +229,36 @@ proc freplace(file: string, pattern: Regex, repl="") =
else: else:
content = content.replace(pattern, repl) 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 compile(dir="", file=""): string = proc compile(dir="", file=""): string =
proc fcompile(file: string): string = proc fcompile(file: string): string =
return "{.compile: \"$#\".}" % file.replace("\\", "/") return "{.compile: \"$#\".}" % file.replace("\\", "/")
var data = "" var data = ""
if dir != "" and dirExists(dir): if dir != "" and dirExists(dir):
for f in walkFiles(dir / "*.c"): for f in walkFiles(dir / "*.c"):
data &= fcompile(f) & "\n" data &= fcompile(f) & "\n"
if file != "" and fileExists(file): if file != "" and fileExists(file):
data &= fcompile(file) & "\n" data &= fcompile(file) & "\n"
@ -252,7 +270,7 @@ proc fixFuncProtos(file: string) =
var tdout = "typedef $# (*type_$#)($#);\n" % [fp.captures[0], fp.captures[1], fp.captures[3]] & var tdout = "typedef $# (*type_$#)($#);\n" % [fp.captures[0], fp.captures[1], fp.captures[3]] &
"type_$# $#($#);" % [fp.captures[1], fp.captures[1], fp.captures[2]] "type_$# $#($#);" % [fp.captures[1], fp.captures[1], fp.captures[2]]
content = content.replace(fp.match, tdout) content = content.replace(fp.match, tdout)
# ### # ###
# Convert to Nim # Convert to Nim
@ -268,21 +286,21 @@ proc getIncls(file: string, inline=false): seq[string] =
result.add(inc.replace(re"""[<>"]""", "").strip()) result.add(inc.replace(re"""[<>"]""", "").strip())
result = result.deduplicate() result = result.deduplicate()
DONE_INLINE.add(file) DONE_INLINE.add(file)
if inline: if inline:
var sres = newSeq[string]() var sres = newSeq[string]()
for incl in result: for incl in result:
let sincl = search(incl) let sincl = search(incl)
if sincl == "": if sincl == "":
continue continue
sres.add(getIncls(sincl, inline)) sres.add(getIncls(sincl, inline))
result.add(sres) result.add(sres)
result = result.deduplicate() result = result.deduplicate()
proc getDefines(file: string, inline=false): string = proc getDefines(file: string, inline=false): string =
result = "" result = ""
if inline: if inline:
@ -351,12 +369,12 @@ proc runCtags(file: string): string =
return fdata return fdata
proc runFile(file: string, cfgin: OrderedTableRef) proc runFile(file: string, cfgin: OrderedTableRef)
proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, ctags, defines: bool, dynlib, compile, pragma: seq[string] = @[]) = proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, ctags, defines: bool, dynlib, compile, pragma: seq[string] = @[]) =
var file = search(fl) var file = search(fl)
if file == "": if file == "":
return return
if file in DONE: if file in DONE:
return return
@ -426,7 +444,7 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, cta
outlib &= lin & linlib & "\n" outlib &= lin & linlib & "\n"
if osxlib != "": if osxlib != "":
outlib &= osx & osxlib & "\n" outlib &= osx & osxlib & "\n"
if outlib != "": if outlib != "":
extflags &= " --dynlib:dynlib$#" % fname extflags &= " --dynlib:dynlib$#" % fname
else: else:
@ -436,7 +454,7 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, cta
# Run c2nim on generated file # Run c2nim on generated file
var cmd = "c2nim $# $# --out:$# $#" % [flags, extflags, outfile, cfile] var cmd = "c2nim $# $# --out:$# $#" % [flags, extflags, outfile, cfile]
when defined(windows): when defined(windows):
cmd = "cmd /c " & cmd cmd = "cmd /c " & cmd
discard execProc(cmd) discard execProc(cmd)
if preprocess or ctags: if preprocess or ctags:
@ -455,10 +473,11 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, cta
# Include {.compile.} directives # Include {.compile.} directives
for cpl in compile: for cpl in compile:
if getFileInfo(cpl).kind == pcFile: let fcpl = search(cpl)
prepend(outfile, compile(file=cpl)) if getFileInfo(fcpl).kind == pcFile:
prepend(outfile, compile(file=fcpl))
else: else:
prepend(outfile, compile(dir=cpl)) prepend(outfile, compile(dir=fcpl))
# Add any pragmas # Add any pragmas
if outpragma != "": if outpragma != "":
@ -468,7 +487,7 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, cta
if passC != "": if passC != "":
prepend(outfile, passC) prepend(outfile, passC)
# Add dynamic library # Add dynamic library
if outlib != "": if outlib != "":
prepend(outfile, outlib) prepend(outfile, outlib)
@ -478,7 +497,7 @@ proc c2nim(fl, outfile, flags, ppflags: string, recurse, inline, preprocess, cta
proc runFile(file: string, cfgin: OrderedTableRef) = proc runFile(file: string, cfgin: OrderedTableRef) =
var cfg = cfgin var cfg = cfgin
var sfile = search(file) var sfile = search(file)
for pattern in WILDCARDS.keys(): for pattern in WILDCARDS.keys():
let pat = pattern.replace(".", "\\.").replace("*", ".*").replace("?", ".?") let pat = pattern.replace(".", "\\.").replace("*", ".*").replace("?", ".?")
if file.find(re(pat)).isSome(): if file.find(re(pat)).isSome():
@ -496,7 +515,7 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
if action == "create": if action == "create":
createDir(file.splitPath().head) createDir(file.splitPath().head)
writeFile(file, cfg[act]) writeFile(file, cfg[act])
elif action in @["prepend", "append", "replace", "compile", "dynlib", "pragma"] and sfile != "": elif action in @["prepend", "append", "replace", "comment", "compile", "dynlib", "pragma"] and sfile != "":
if action == "prepend": if action == "prepend":
if srch != "": if srch != "":
prepend(sfile, cfg[act], cfg[srch]) prepend(sfile, cfg[act], cfg[srch])
@ -510,6 +529,9 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
elif action == "replace": elif action == "replace":
if srch != "": if srch != "":
freplace(sfile, cfg[srch], cfg[act]) freplace(sfile, cfg[srch], cfg[act])
elif action == "comment":
if srch != "":
comment(sfile, cfg[srch], cfg[act])
elif action == "compile": elif action == "compile":
compile.add(cfg[act]) compile.add(cfg[act])
elif action == "dynlib": elif action == "dynlib":
@ -519,7 +541,7 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
srch = "" srch = ""
elif action == "search": elif action == "search":
srch = act srch = act
if file.splitFile().ext != ".nim": if file.splitFile().ext != ".nim":
var recurse = false var recurse = false
var inline = false var inline = false
@ -555,7 +577,7 @@ proc runFile(file: string, cfgin: OrderedTableRef) =
if not noprocess: if not noprocess:
c2nim(file, getNimout(file), flags, ppflags, recurse, inline, preprocess, ctags, defines, dynlib, compile, pragma) c2nim(file, getNimout(file), flags, ppflags, recurse, inline, preprocess, ctags, defines, dynlib, compile, pragma)
proc runCfg(cfg: string) = proc runCfg(cfg: string) =
if not fileExists(cfg): if not fileExists(cfg):
echo "Config doesn't exist: " & cfg echo "Config doesn't exist: " & cfg
@ -567,7 +589,7 @@ proc runCfg(cfg: string) =
if CONFIG["n.global"].hasKey("output"): if CONFIG["n.global"].hasKey("output"):
OUTPUT = CONFIG["n.global"]["output"] OUTPUT = CONFIG["n.global"]["output"]
if dirExists(OUTPUT): if dirExists(OUTPUT):
if ARGS["-f"]: if "-f" in commandLineParams():
try: try:
removeDir(OUTPUT) removeDir(OUTPUT)
except OSError: except OSError:
@ -587,7 +609,7 @@ proc runCfg(cfg: string) =
if CONFIG["n.global"].hasKey("quotes"): if CONFIG["n.global"].hasKey("quotes"):
if CONFIG["n.global"]["quotes"] == "false": if CONFIG["n.global"]["quotes"] == "false":
QUOTES = false QUOTES = false
if CONFIG.hasKey("n.include"): if CONFIG.hasKey("n.include"):
for inc in CONFIG["n.include"].keys(): for inc in CONFIG["n.include"].keys():
INCLUDES.add(inc) INCLUDES.add(inc)
@ -632,5 +654,6 @@ proc runCfg(cfg: string) =
# ### # ###
# Main loop # Main loop
for i in ARGS["<file.cfg>"]: for i in commandLineParams():
runCfg(i) if i != "-f":
runCfg(i)

View file

@ -1,6 +1,6 @@
# Package # Package
version = "0.1.3" version = "0.1.4"
author = "genotrance" author = "genotrance"
description = "c2nim helper to simplify and automate the wrapping of C libraries" description = "c2nim helper to simplify and automate the wrapping of C libraries"
license = "MIT" license = "MIT"
@ -9,7 +9,7 @@ skipDirs = @["tests"]
# Dependencies # Dependencies
requires "nim >= 0.16.0", "c2nim >= 0.9.13", "docopt >= 0.6.5" requires "nim >= 0.17.2", "c2nim >= 0.9.13"
bin = @["nimgen"] bin = @["nimgen"]

View file

@ -1,7 +1,18 @@
import distros
import ospaths import ospaths
import strutils import strutils
for comp in @["nimbass", "nimfuzz", "nimssl", "nimssh2"]: var comps = @["libsvm", "nimbass", "nimfuzz", "nimssl", "nimssh2"]
withDir(".."/comp): if detectOs(Windows):
exec "nimble install -y" comps.add("nimkerberos")
exec "nimble test"
for comp in comps:
if dirExists(".."/comp):
exec "nimble uninstall -y " & comp
withDir(".."/comp):
rmDir(comp)
exec "nimble install -y"
exec "nimble test"
exec "nimble install -y"
exec "nimble test"