From 0f73ad6d3f9ec081792e03967b49895a1d53b9b8 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Thu, 14 Jun 2018 17:13:46 +0900 Subject: [PATCH 01/18] Add configurable compiler to global section --- nimgen.nim | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/nimgen.nim b/nimgen.nim index d804657..397ece4 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -7,6 +7,8 @@ var gConfig: Config gFilter = "" gQuotes = true + gCppCompiler = "g++" + gCCompiler = "gcc" gOutput = "" gIncludes: seq[string] = @[] gExcludes: seq[string] = @[] @@ -369,7 +371,7 @@ proc getDefines(file: string, inline=false): string = proc runPreprocess(file, ppflags, flags: string, inline: bool): string = var - pproc = if flags.contains("cpp"): "g++" else: "gcc" + pproc = if flags.contains("cpp"): gCppCompiler else: gCCompiler cmd = "$# -E $# $#" % [pproc, ppflags, file] for inc in gIncludes: @@ -671,6 +673,11 @@ proc runCfg(cfg: string) = quit(1) createDir(gOutput) + if gConfig["n.global"].hasKey("cpp_compiler"): + gCppCompiler = gConfig["n.global"]["cpp_compiler"] + if gConfig["n.global"].hasKey("c_compiler"): + gCCompiler = gConfig["n.global"]["c_compiler"] + if gConfig["n.global"].hasKey("filter"): gFilter = gConfig["n.global"]["filter"] if gConfig["n.global"].hasKey("quotes"): From f275bc0e352734cf6e8bbe125d56355b7949e432 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Sat, 16 Jun 2018 15:17:51 +0900 Subject: [PATCH 02/18] Update readme with compiler spec --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index d47239e..9fc8618 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,10 @@ _[n.global]_ ```filter``` = string to identify and recurse into library .h files in #include statements and exclude standard headers +```cpp_compiler``` = string to specify a CPP compiler executable. [default: g++] + +```c_compiler``` = string to specify a C compiler executable. [default: gcc] + _[n.include]_ List of all directories, one per line, to include in the search path. This is used by:- From 467d0c4eae83d49e677bc03f8c3300a71bd9fcf1 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 20 Jun 2018 13:59:46 +0900 Subject: [PATCH 03/18] Add ability to use environment vars --- nimgen.nim | 54 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/nimgen.nim b/nimgen.nim index 3f9a104..e1e16b7 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -35,6 +35,33 @@ Options: # ### # Helpers +proc addEnv(str: string): string = + var newStr = str + for pair in envPairs(): + try: + newStr = newStr % [pair.key, pair.value.string] + except ValueError: + # Ignore if there are no values to replace. We + # want to continue anyway + discard + + try: + newStr = newStr % ["output", gOutput] + except ValueError: + # Ignore if there are no values to replace. We + # want to continue anyway + discard + + # if there are still format args, print a warning + if newStr.contains("${"): + echo "WARNING: \"", newStr, "\" still contains an uninterpolated value!" + + return newStr + +proc `[]`(table: OrderedTableRef[string, string], key: string): string = + ## Gets table values with env vars inserted + tables.`[]`(table, key).addEnv + proc execProc(cmd: string): string = result = "" var @@ -497,6 +524,7 @@ proc c2nim(fl, outfile: string, c2nimConfig: c2nimConfigObj) = outpragma &= "{." & prag & ".}\n" let fname = file.splitFile().name.replace(re"[\.\-]", "_") + if c2nimConfig.dynlib.len() != 0: let win = "when defined(Windows):\n" @@ -599,7 +627,9 @@ proc runFile(file: string, cfgin: OrderedTableRef) = if action == "create": createDir(file.splitPath().head) writeFile(file, cfg[act]) - elif action in @["prepend", "append", "replace", "comment", "rename", "compile", "dynlib", "pragma", "pipe"] and sfile != "": + elif action in @["prepend", "append", "replace", "comment", + "rename", "compile", "dynlib", "pragma", + "pipe"] and sfile != "": if action == "prepend": if srch != "": prepend(sfile, cfg[act], cfg[srch]) @@ -700,30 +730,31 @@ proc runCfg(cfg: string) = if gConfig.hasKey("n.include"): for inc in gConfig["n.include"].keys(): - gIncludes.add(inc) + gIncludes.add(inc.addEnv()) if gConfig.hasKey("n.exclude"): for excl in gConfig["n.exclude"].keys(): - gExcludes.add(excl) + gExcludes.add(excl.addEnv()) if gConfig.hasKey("n.prepare"): for prep in gConfig["n.prepare"].keys(): let (key, val) = getKey(prep) if val == true: + let prepVal = gConfig["n.prepare"][prep] if key == "download": - downloadUrl(gConfig["n.prepare"][prep]) + downloadUrl(prepVal) elif key == "extract": - extractZip(gConfig["n.prepare"][prep]) + extractZip(prepVal) elif key == "git": - gitRemotePull(gConfig["n.prepare"][prep]) + gitRemotePull(prepVal) elif key == "gitremote": - gitRemotePull(gConfig["n.prepare"][prep], false) + gitRemotePull(prepVal, false) elif key == "gitsparse": - gitSparseCheckout(gConfig["n.prepare"][prep]) + gitSparseCheckout(prepVal) elif key == "execute": - discard execProc(gConfig["n.prepare"][prep]) + discard execProc(prepVal) elif key == "copy": - doCopy(gConfig["n.prepare"][prep]) + doCopy(prepVal) if gConfig.hasKey("n.wildcard"): var wildcard = "" @@ -733,7 +764,8 @@ proc runCfg(cfg: string) = if key == "wildcard": wildcard = gConfig["n.wildcard"][wild] else: - gWildcards.setSectionKey(wildcard, wild, gConfig["n.wildcard"][wild]) + gWildcards.setSectionKey(wildcard, wild, + gConfig["n.wildcard"][wild]) for file in gConfig.keys(): if file in @["n.global", "n.include", "n.exclude", "n.prepare", "n.wildcard"]: From 76020e8f219bda1af3f7e1bc7974ffb1d6b2a6df Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 20 Jun 2018 14:04:14 +0900 Subject: [PATCH 04/18] Add env vars to readme --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 765b6da..f74950b 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,14 @@ __Capabilities & Limitations__ Nimgen supports compiling in C/C++ sources and static libraries as well as loading in dynamic libraries. +Environment variables are supported via Nim's string interpolation `%` symbol imported from the `strutils` module. Simply use double quotes to enclose any value and put `${}` around the environment variable name. In addition, the `output` var from the n.global section is available as ${output}. For example: + + [n.global] + output="src/path" + + [n.include] + "${output}/library/include" + To see examples of nimgen in action check out the following wrappers:- * Link with a dynamic library * [nimbass](https://github.com/genotrance/nimbass) - BASS audio wrapper: [docs](http://nimgen.genotrance.com/nimbass) From 17e54d3b8786422c8643cbe2f405f30ef324ed38 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Mon, 9 Jul 2018 09:16:44 +0900 Subject: [PATCH 05/18] Make c/cpp compiler priority .cfg > CC/CXX > gcc/g++ --- nimgen.nim | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/nimgen.nim b/nimgen.nim index e1e16b7..4f2c251 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -1,5 +1,11 @@ import nre, os, ospaths, osproc, parsecfg, pegs, ropes, sequtils, streams, strutils, tables +const + C_COMPILER_ENV = "CC" + CPP_COMPILER_ENV = "CPP" + DEFAULT_C_COMPILER = "gcc" + DEFAULT_CPP_COMPILER = "g++" + var gDoneRecursive: seq[string] = @[] gDoneInline: seq[string] = @[] @@ -8,8 +14,8 @@ var gConfig: Config gFilter = "" gQuotes = true - gCppCompiler = "g++" - gCCompiler = "gcc" + gCppCompiler = getEnv(CPP_COMPILER_ENV, DEFAULT_C_COMPILER) + gCCompiler = getEnv(C_COMPILER_ENV, DEFAULT_CPP_COMPILER) gOutput = "" gIncludes: seq[string] = @[] gExcludes: seq[string] = @[] @@ -719,8 +725,15 @@ proc runCfg(cfg: string) = if gConfig["n.global"].hasKey("cpp_compiler"): gCppCompiler = gConfig["n.global"]["cpp_compiler"] + else: + # Reset on a per project basis + gCppCompiler = getEnv(CPP_COMPILER_ENV, DEFAULT_CPP_COMPILER) + if gConfig["n.global"].hasKey("c_compiler"): gCCompiler = gConfig["n.global"]["c_compiler"] + else: + # Reset on a per project basis + gCCompiler = getEnv(C_COMPILER_ENV, DEFAULT_C_COMPILER) if gConfig["n.global"].hasKey("filter"): gFilter = gConfig["n.global"]["filter"] From 9c41b5a17644726ff982b65e2740f2cc3e57c54a Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Mon, 9 Jul 2018 09:21:14 +0900 Subject: [PATCH 06/18] Add better example to readme for env vars --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f74950b..78ad979 100644 --- a/README.md +++ b/README.md @@ -30,13 +30,16 @@ __Capabilities & Limitations__ Nimgen supports compiling in C/C++ sources and static libraries as well as loading in dynamic libraries. -Environment variables are supported via Nim's string interpolation `%` symbol imported from the `strutils` module. Simply use double quotes to enclose any value and put `${}` around the environment variable name. In addition, the `output` var from the n.global section is available as ${output}. For example: +Environment variables are supported via Nim's string interpolation `%` symbol imported from the `strutils` module. Simply use double quotes to enclose any value and put `$` or `${}` around the environment variable name. In addition, the `output` var from the n.global section is available as ${output}. For example: [n.global] + c_compiler="$CC" + cpp_compiler="${CPP}-arm" output="src/path" [n.include] "${output}/library/include" + "${MY_INCLUDE_PATH}/include" To see examples of nimgen in action check out the following wrappers:- * Link with a dynamic library From 3b60a0e4b10be17d00e39afbc163702555555d62 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Mon, 9 Jul 2018 09:51:44 +0900 Subject: [PATCH 07/18] Move env var section in readme --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 78ad979..40f7556 100644 --- a/README.md +++ b/README.md @@ -30,17 +30,6 @@ __Capabilities & Limitations__ Nimgen supports compiling in C/C++ sources and static libraries as well as loading in dynamic libraries. -Environment variables are supported via Nim's string interpolation `%` symbol imported from the `strutils` module. Simply use double quotes to enclose any value and put `$` or `${}` around the environment variable name. In addition, the `output` var from the n.global section is available as ${output}. For example: - - [n.global] - c_compiler="$CC" - cpp_compiler="${CPP}-arm" - output="src/path" - - [n.include] - "${output}/library/include" - "${MY_INCLUDE_PATH}/include" - To see examples of nimgen in action check out the following wrappers:- * Link with a dynamic library * [nimbass](https://github.com/genotrance/nimbass) - BASS audio wrapper: [docs](http://nimgen.genotrance.com/nimbass) @@ -76,6 +65,17 @@ Nimgen only supports the ```gcc``` preprocessor at this time. Support for detect __Config file__ +In all sections below, environment variables are supported via Nim's string interpolation `%` symbol imported from the `strutils` module. Simply use double quotes to enclose any value and put `$` or `${}` around the environment variable name. In addition, the `output` var from the n.global section is available as ${output}. For example: + + [n.global] + c_compiler="$CC" + cpp_compiler="${CPP}-arm" + output="src/path" + + [n.include] + "${output}/library/include" + "${MY_INCLUDE_PATH}/include" + _[n.global]_ ```output``` = name of the Nimble project once installed, also location to place generated .nim files From 8e8e5fbd09de38207d13ac0e79b4716308b1d828 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Mon, 9 Jul 2018 09:52:23 +0900 Subject: [PATCH 08/18] Change consts to camel case for nep1 --- nimgen.nim | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/nimgen.nim b/nimgen.nim index 4f2c251..d618142 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -1,10 +1,10 @@ import nre, os, ospaths, osproc, parsecfg, pegs, ropes, sequtils, streams, strutils, tables const - C_COMPILER_ENV = "CC" - CPP_COMPILER_ENV = "CPP" - DEFAULT_C_COMPILER = "gcc" - DEFAULT_CPP_COMPILER = "g++" + cCompilerEnv = "CC" + cppCompilerEnv = "CPP" + defaultCCompiler = "gcc" + defaultCppCompiler = "g++" var gDoneRecursive: seq[string] = @[] @@ -14,8 +14,8 @@ var gConfig: Config gFilter = "" gQuotes = true - gCppCompiler = getEnv(CPP_COMPILER_ENV, DEFAULT_C_COMPILER) - gCCompiler = getEnv(C_COMPILER_ENV, DEFAULT_CPP_COMPILER) + gCppCompiler = getEnv(cppCompilerEnv, defaultCCompiler) + gCCompiler = getEnv(cCompilerEnv, defaultCppCompiler) gOutput = "" gIncludes: seq[string] = @[] gExcludes: seq[string] = @[] @@ -727,13 +727,13 @@ proc runCfg(cfg: string) = gCppCompiler = gConfig["n.global"]["cpp_compiler"] else: # Reset on a per project basis - gCppCompiler = getEnv(CPP_COMPILER_ENV, DEFAULT_CPP_COMPILER) + gCppCompiler = getEnv(cppCompilerEnv, defaultCppCompiler) if gConfig["n.global"].hasKey("c_compiler"): gCCompiler = gConfig["n.global"]["c_compiler"] else: # Reset on a per project basis - gCCompiler = getEnv(C_COMPILER_ENV, DEFAULT_C_COMPILER) + gCCompiler = getEnv(cCompilerEnv, defaultCCompiler) if gConfig["n.global"].hasKey("filter"): gFilter = gConfig["n.global"]["filter"] From b32d39ad08ec630f288958c4c9e0878ab2e8677f Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Sat, 7 Jul 2018 19:16:16 +0900 Subject: [PATCH 09/18] Add preliminary support for removing static funcs --- nimgen.nim | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/nimgen.nim b/nimgen.nim index c132fe1..7a053bb 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -25,7 +25,7 @@ var type c2nimConfigObj = object flags, ppflags: string - recurse, inline, preprocess, ctags, defines: bool + recurse, inline, preprocess, ctags, defines, remove_static: bool dynlib, compile, pragma: seq[string] const DOC = """ @@ -92,7 +92,9 @@ proc execProc(cmd: string): string = 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('$#', '.'); }\"" + cmd = "powershell -nologo -noprofile -command \"& { Add-Type -A " & + "'System.IO.Compression.FileSystem'; " & + "[IO.Compression.ZipFile]::ExtractToDirectory('$#', '.'); }\"" setCurrentDir(gOutput) defer: setCurrentDir(gProjectDir) @@ -322,6 +324,67 @@ proc comment(file: string, pattern: string, numlines: string) = idx += 1 break +proc removeStatic(filename: string) = + + if not fileExists(filename): + echo "Missing file: " & filename + return + + # This function should ideally be a regex. However, I could not + # get it to work as intended with the current re implementation + # in Nim. + # + # withFile(filename): + # content = content.replacef( + # re"(static inline.*?\))([ \r\n]*?\{([ \r\n]*?.*?)*[\n\r]\})", "$1;") + # ) + # + # This currently won't even run, but if the replacef function is modified + # to not have nil checks, it will run on 1/3 of the input file. Maybe there's + # a buffer length issue. + + var + file = open(filename) + stack: seq[string] = @[] + foundBrace = false + foundStatic = false + writeOutput = true + output = newStringofCap(getFileSize(filename)) + + for line in file.lines(): + var modLine = line + + if not foundStatic: + writeOutput = true + if line.startswith("static inline"): + foundStatic = true + let index = modLine.find("{") + if index != -1: + foundBrace = true + modLine.setLen(index) + elif not foundBrace: + writeOutput = true + if modLine.strip().startswith("{"): + foundBrace = true + writeOutput = false + else: + if modLine.startswith("}"): + foundBrace = false + foundStatic = false + output[^1] = ';' + output &= "\n" + + if writeOutput: + output &= modLine + output &= "\n" + writeOutput = false + + file.close() + + var f = open(filename, fmWrite) + write(f, output) + f.close() + proc rename(file: string, renfile: string) = if file.splitFile().ext == ".nim": return @@ -519,6 +582,9 @@ proc c2nim(fl, outfile: string, c2nimConfig: c2nimConfigObj) = if c2nimConfig.defines and (c2nimConfig.preprocess or c2nimConfig.ctags): prepend(cfile, getDefines(file, c2nimConfig.inline)) + if c2nimConfig.remove_static: + removeStatic(cfile) + var extflags = "" passC = "" @@ -697,6 +763,8 @@ proc runFile(file: string, cfgin: OrderedTableRef) = c2nimConfig.ctags = true elif action == "defines": c2nimConfig.defines = true + elif act == "remove_static": + c2nimConfig.remove_static = true elif action == "noprocess": noprocess = true elif action == "flags": From 5321014983a5dff827cecf37392b7ee99985b738 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Sun, 8 Jul 2018 10:03:33 +0900 Subject: [PATCH 10/18] Add readme section about remove_static --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 40f7556..360bec5 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,8 @@ The following keys apply to library source code and help with generating the .ni ```defines``` = pulls out simple #defines of ints, floats and hex values for separate conversion [default: false] - works only when preprocess or ctags is used and helps include useful definitions in generated .nim file +```remove_static``` = pulls out the bodies of inline static functions [default: false] + ```flags``` = flags to pass to the c2nim process in "quotes" [default: --stdcall]. --cdecl, --assumedef, --assumendef may be useful ```ppflags``` = flags to pass to the preprocessor [default: ""]. -D for gcc and others may be useful From 2e894dc90702b92290c226dd683a198b3d092634 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Mon, 18 Jun 2018 19:44:45 +0900 Subject: [PATCH 11/18] Implement relative import support in header files. Fixes #17 --- nimgen.nim | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/nimgen.nim b/nimgen.nim index c132fe1..6baea3b 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -224,6 +224,8 @@ proc search(file: string): string = echo "File doesn't exist: " & file quit(1) + # Only keep relative directory + result = result.replace(gProjectDir & $DirSep, "") return result.replace(re"[\\/]", $DirSep) # ### @@ -376,12 +378,25 @@ proc getIncls(file: string, inline=false): seq[string] = if inline and file in gDoneInline: return + let curPath = splitFile(expandFileName(file)).dir withFile(file): for f in content.findIter(re"(?m)^\s*#\s*include\s+(.*?)$"): var inc = f.captures[0].strip() if ((gQuotes and inc.contains("\"")) or (gFilter != "" and gFilter in inc)) and (not exclude(inc)): - result.add( - inc.replace(re"""[<>"]""", "").replace(re"\/[\*\/].*$", "").strip()) + let addInc = inc.replace(re"""[<>"]""", "").replace(re"\/[\*\/].*$", "").strip() + try: + # Try searching for a local library. expandFilename will throw + # OSError if the file does not exist + let + finc = expandFileName(curPath / addInc) + fname = extractFileName(finc).search() + + if fname.len() > 0: + # only add if the file is non-empty + result.add(fname.search()) + except OSError: + # If it's a system library + result.add(addInc) result = result.deduplicate() From ab3185b611c138ad32c7149ba5260ba67bf0fb4a Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Sun, 8 Jul 2018 13:05:09 +0900 Subject: [PATCH 12/18] Add n.post section --- README.md | 8 ++++++++ nimgen.nim | 13 ++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 40f7556..6bc1cd1 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,14 @@ The following keys can be used to prepare dependencies such as downloading ZIP f ```copy``` = copy a file to another location. Preferred over moving to preserve original. Comma separate for multiple entries. E.g. copy = "output/config.h.in=output/config.h" +_[n.post]_ + +This section is the same as the prepare section, but for performing actions after the project has been processed. + +```reset``` = whether or not to perform a git reset on all files after processing [default: false] + +```execute``` = command to run after processing + _[n.wildcard]_ File wildcards such as *.nim, ssl*.h, etc. can be used to perform tasks across a group of files. This is useful to define common operations such as global text replacements without having to specify an explicit section for every single file. These operations will be performed on every matching file that is defined as a _sourcefile_ or recursed files. Only applies on source files following the wildcard declarations. diff --git a/nimgen.nim b/nimgen.nim index c132fe1..fedbee5 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -797,11 +797,22 @@ proc runCfg(cfg: string) = gConfig["n.wildcard"][wild]) for file in gConfig.keys(): - if file in @["n.global", "n.include", "n.exclude", "n.prepare", "n.wildcard"]: + if file in @["n.global", "n.include", "n.exclude", + "n.prepare", "n.wildcard", "n.post"]: continue runFile(file, gConfig[file]) + if gConfig.hasKey("n.post"): + for post in gConfig["n.post"].keys(): + let (key, val) = getKey(post) + if val == true: + let postVal = gConfig["n.post"][post] + if key == "reset": + gitReset() + elif key == "execute": + discard execProc(postVal) + # ### # Main loop From f5e8535ce83c79d66e32e1ebe2d5f1a945f61c77 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 10 Jul 2018 13:53:53 +0900 Subject: [PATCH 13/18] Fix windows paths --- nimgen.nim | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nimgen.nim b/nimgen.nim index 6baea3b..94fa48c 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -225,8 +225,7 @@ proc search(file: string): string = quit(1) # Only keep relative directory - result = result.replace(gProjectDir & $DirSep, "") - return result.replace(re"[\\/]", $DirSep) + return result.multiReplace([("\\", $DirSep), ("//", $DirSep), (gProjectDir & $DirSep, "")]) # ### # Loading / unloading @@ -389,7 +388,7 @@ proc getIncls(file: string, inline=false): seq[string] = # OSError if the file does not exist let finc = expandFileName(curPath / addInc) - fname = extractFileName(finc).search() + fname = finc.replace(curPath & $DirSep, "") if fname.len() > 0: # only add if the file is non-empty From 0d0506675c6fc91de1fd6ac59faeece0f248ac4a Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 10 Jul 2018 20:09:51 +0900 Subject: [PATCH 14/18] Make static bodies replacement use regex --- nimgen.nim | 64 +++++------------------------------------------------- 1 file changed, 5 insertions(+), 59 deletions(-) diff --git a/nimgen.nim b/nimgen.nim index 7a053bb..e520309 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -325,65 +325,11 @@ proc comment(file: string, pattern: string, numlines: string) = break proc removeStatic(filename: string) = - - if not fileExists(filename): - echo "Missing file: " & filename - return - - # This function should ideally be a regex. However, I could not - # get it to work as intended with the current re implementation - # in Nim. - # - # withFile(filename): - # content = content.replacef( - # re"(static inline.*?\))([ \r\n]*?\{([ \r\n]*?.*?)*[\n\r]\})", "$1;") - # ) - # - # This currently won't even run, but if the replacef function is modified - # to not have nil checks, it will run on 1/3 of the input file. Maybe there's - # a buffer length issue. - - var - file = open(filename) - stack: seq[string] = @[] - foundBrace = false - foundStatic = false - writeOutput = true - output = newStringofCap(getFileSize(filename)) - - for line in file.lines(): - var modLine = line - - if not foundStatic: - writeOutput = true - if line.startswith("static inline"): - foundStatic = true - let index = modLine.find("{") - if index != -1: - foundBrace = true - modLine.setLen(index) - elif not foundBrace: - writeOutput = true - if modLine.strip().startswith("{"): - foundBrace = true - writeOutput = false - else: - if modLine.startswith("}"): - foundBrace = false - foundStatic = false - output[^1] = ';' - output &= "\n" - - if writeOutput: - output &= modLine - output &= "\n" - writeOutput = false - - file.close() - - var f = open(filename, fmWrite) - write(f, output) - f.close() + ## Replace static function bodies with a semicolon + withFile(filename): + content = content.replace( + re"(?m)(static inline.*?\))(\s*\{(\s*?.*?$)*[\n\r]\})", "$1;" + ) proc rename(file: string, renfile: string) = if file.splitFile().ext == ".nim": From 14b119f433f7584f2b9a529f388b4f298f3da874 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 11 Jul 2018 07:02:36 +0900 Subject: [PATCH 15/18] Move remove static and reset after processing --- nimgen.nim | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/nimgen.nim b/nimgen.nim index e520309..32e640b 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -25,7 +25,7 @@ var type c2nimConfigObj = object flags, ppflags: string - recurse, inline, preprocess, ctags, defines, remove_static: bool + recurse, inline, preprocess, ctags, defines, removeStatic: bool dynlib, compile, pragma: seq[string] const DOC = """ @@ -126,6 +126,16 @@ proc gitReset() = discard execProc("git reset --hard HEAD") +proc gitCheckout(filename: string) = + echo "Resetting file: $#" % [filename] + + setCurrentDir(gOutput) + defer: setCurrentDir(gProjectDir) + + let adjustedFile = filename.replace(gOutput & $DirSep, "") + + discard execProc("git checkout $#" % [adjustedFile]) + proc gitRemotePull(url: string, pull=true) = if dirExists(gOutput/".git"): if pull: @@ -528,7 +538,7 @@ proc c2nim(fl, outfile: string, c2nimConfig: c2nimConfigObj) = if c2nimConfig.defines and (c2nimConfig.preprocess or c2nimConfig.ctags): prepend(cfile, getDefines(file, c2nimConfig.inline)) - if c2nimConfig.remove_static: + if c2nimConfig.removeStatic: removeStatic(cfile) var @@ -659,6 +669,9 @@ proc runFile(file: string, cfgin: OrderedTableRef) = if action == "create": createDir(file.splitPath().head) writeFile(file, cfg[act]) + elif action == "removestatic": + removeStatic(sfile) + c2nimConfig.removeStatic = true elif action in @["prepend", "append", "replace", "comment", "rename", "compile", "dynlib", "pragma", "pipe"] and sfile != "": @@ -709,8 +722,6 @@ proc runFile(file: string, cfgin: OrderedTableRef) = c2nimConfig.ctags = true elif action == "defines": c2nimConfig.defines = true - elif act == "remove_static": - c2nimConfig.remove_static = true elif action == "noprocess": noprocess = true elif action == "flags": @@ -725,6 +736,9 @@ proc runFile(file: string, cfgin: OrderedTableRef) = if not noprocess: c2nim(file, getNimout(sfile), c2nimConfig) + if c2nimConfig.removeStatic: + gitCheckout(sfile) + proc runCfg(cfg: string) = if not fileExists(cfg): echo "Config doesn't exist: " & cfg From f62125a4aaed2a15970bdd186dddb7cb9a4bd862 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 11 Jul 2018 07:53:05 +0900 Subject: [PATCH 16/18] Update readme with removestatic --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 360bec5..7f3f256 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ The following keys apply to library source code and help with generating the .ni ```defines``` = pulls out simple #defines of ints, floats and hex values for separate conversion [default: false] - works only when preprocess or ctags is used and helps include useful definitions in generated .nim file -```remove_static``` = pulls out the bodies of inline static functions [default: false] +```removestatic``` = pulls out the bodies of inline static functions [default: false] ```flags``` = flags to pass to the c2nim process in "quotes" [default: --stdcall]. --cdecl, --assumedef, --assumendef may be useful From 685081b6a99c0022e29863e8d70bd873d7fe5876 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 11 Jul 2018 13:36:45 +0900 Subject: [PATCH 17/18] Modify removeStatic to comment out body, then re-comment --- nimgen.nim | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/nimgen.nim b/nimgen.nim index 32e640b..d613386 100644 --- a/nimgen.nim +++ b/nimgen.nim @@ -25,7 +25,7 @@ var type c2nimConfigObj = object flags, ppflags: string - recurse, inline, preprocess, ctags, defines, removeStatic: bool + recurse, inline, preprocess, ctags, defines: bool dynlib, compile, pragma: seq[string] const DOC = """ @@ -126,7 +126,7 @@ proc gitReset() = discard execProc("git reset --hard HEAD") -proc gitCheckout(filename: string) = +proc gitCheckout(filename: string) {.used.} = echo "Resetting file: $#" % [filename] setCurrentDir(gOutput) @@ -335,10 +335,33 @@ proc comment(file: string, pattern: string, numlines: string) = break proc removeStatic(filename: string) = - ## Replace static function bodies with a semicolon + ## Replace static function bodies with a semicolon and commented + ## out body withFile(filename): content = content.replace( - re"(?m)(static inline.*?\))(\s*\{(\s*?.*?$)*[\n\r]\})", "$1;" + re"(?m)(static inline.*?\))(\s*\{(\s*?.*?$)*[\n\r]\})", + proc (match: RegexMatch): string = + let funcDecl = match.captures[0] + let body = match.captures[1].strip() + result = "" + + result.add("$#;" % [funcDecl]) + result.add(body.replace(re"(?m)^", "//")) + ) + +proc reAddStatic(filename: string) = + ## Uncomment out the body and remove the semicolon. Undoes + ## removeStatic + withFile(filename): + content = content.replace( + re"(?m)(static inline.*?\));(\/\/\s*\{(\s*?.*?$)*[\n\r]\/\/\})", + proc (match: RegexMatch): string = + let funcDecl = match.captures[0] + let body = match.captures[1].strip() + result = "" + + result.add("$# " % [funcDecl]) + result.add(body.replace(re"(?m)^\/\/", "")) ) proc rename(file: string, renfile: string) = @@ -538,9 +561,6 @@ proc c2nim(fl, outfile: string, c2nimConfig: c2nimConfigObj) = if c2nimConfig.defines and (c2nimConfig.preprocess or c2nimConfig.ctags): prepend(cfile, getDefines(file, c2nimConfig.inline)) - if c2nimConfig.removeStatic: - removeStatic(cfile) - var extflags = "" passC = "" @@ -669,9 +689,6 @@ proc runFile(file: string, cfgin: OrderedTableRef) = if action == "create": createDir(file.splitPath().head) writeFile(file, cfg[act]) - elif action == "removestatic": - removeStatic(sfile) - c2nimConfig.removeStatic = true elif action in @["prepend", "append", "replace", "comment", "rename", "compile", "dynlib", "pragma", "pipe"] and sfile != "": @@ -733,11 +750,14 @@ proc runFile(file: string, cfgin: OrderedTableRef) = echo "Cannot use recurse and inline simultaneously" quit(1) + # Remove static inline function bodies + removeStatic(sfile) + if not noprocess: c2nim(file, getNimout(sfile), c2nimConfig) - if c2nimConfig.removeStatic: - gitCheckout(sfile) + # Add them back for compilation + reAddStatic(sfile) proc runCfg(cfg: string) = if not fileExists(cfg): From 15ba47946822a80d034c247c3f22b350d4651d74 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 11 Jul 2018 13:54:37 +0900 Subject: [PATCH 18/18] Remove removestatic from readme --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 7f3f256..40f7556 100644 --- a/README.md +++ b/README.md @@ -138,8 +138,6 @@ The following keys apply to library source code and help with generating the .ni ```defines``` = pulls out simple #defines of ints, floats and hex values for separate conversion [default: false] - works only when preprocess or ctags is used and helps include useful definitions in generated .nim file -```removestatic``` = pulls out the bodies of inline static functions [default: false] - ```flags``` = flags to pass to the c2nim process in "quotes" [default: --stdcall]. --cdecl, --assumedef, --assumendef may be useful ```ppflags``` = flags to pass to the preprocessor [default: ""]. -D for gcc and others may be useful