aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2019-12-18 23:49:25 -0600
committerGanesh Viswanathan <dev@genotrance.com>2019-12-18 23:49:25 -0600
commitbce8e0907368df20e04252635ab5994cfd579b7b (patch)
tree4626b23c8515566541aff752140aa41b6b9d68ee
parent0db54af54f17c1e62dff4baa44ea40e6d14c676e (diff)
downloadnimterop-bce8e0907368df20e04252635ab5994cfd579b7b.tar.gz
nimterop-bce8e0907368df20e04252635ab5994cfd579b7b.zip
Fix #146 - prefix/suffix for stripping
-rw-r--r--README.md26
-rw-r--r--nimterop/cimport.nim29
-rw-r--r--nimterop/getters.nim13
-rw-r--r--nimterop/globals.nim2
-rw-r--r--nimterop/toast.nim92
-rw-r--r--tests/lzma.nim11
6 files changed, 103 insertions, 70 deletions
diff --git a/README.md b/README.md
index fcab924..502688e 100644
--- a/README.md
+++ b/README.md
@@ -93,23 +93,25 @@ The `toast` binary can also be used directly on the CLI:
toast -h
Usage:
main [optional-params] C/C++ source/header
- Options(opt-arg sep :|=|spc):
+Options(opt-arg sep :|=|spc):
-h, --help print this cligen-erated help
- --help-syntax advanced: prepend, multi-val,..
- -p, --preprocess bool false run preprocessor on header
- -a, --past bool false print AST output
- -n, --pnim bool false print Nim output
- -r, --recurse bool false process #include files
- -c, --nocomments bool false exclude top-level comments from output
+ --help-syntax advanced: prepend,plurals,..
+ -d, --debug bool false enable debug output
-D=, --defines= strings {} definitions to pass to preprocessor
- -I=, --includeDirs= strings {} include directory to pass to preprocessor
-l=, --dynlib= string "" Import symbols from library in specified Nim string
- -O=, --symOverride= strings {} skip generating specified symbols
- --nim= string "nim" use a particular Nim executable (default: $PATH/nim)
- --pluginSourcePath= string "" Nim file to build and load as a plugin
- -d, --debug bool false enable debug output
+ -I=, --includeDirs= strings {} include directory to pass to preprocessor
-m=, --mode= string "cpp" language parser: c or cpp
+ --nim= string "nim" use a particular Nim executable (default: $PATH/nim)
+ -c, --nocomments bool false exclude top-level comments from output
+ -a, --past bool false print AST output
-g, --pgrammar bool false print grammar
+ --pluginSourcePath= string "" Nim file to build and load as a plugin
+ -n, --pnim bool false print Nim output
+ -E=, --prefix= strings {} Strip prefix from identifiers
+ -p, --preprocess bool false run preprocessor on header
+ -r, --recurse bool false process #include files
+ -F=, --suffix= strings {} Strip suffix from identifiers
+ -O=, --symOverride= strings {} skip generating specified symbols
```
__Implementation Details__
diff --git a/nimterop/cimport.nim b/nimterop/cimport.nim
index 65a5401..bebcf3d 100644
--- a/nimterop/cimport.nim
+++ b/nimterop/cimport.nim
@@ -140,7 +140,7 @@ proc getToast(fullpath: string, recurse: bool = false, dynlib: string = "",
cmd.add " --recurse"
if flags.nBl:
- cmd.add flags
+ cmd.add " " & flags
for i in gStateCT.defines:
cmd.add &" --defines+={i.quoteShell}"
@@ -300,13 +300,18 @@ macro cPlugin*(body): untyped =
##
## proc onSymbol(sym: var Symbol) {.exportc, dynlib.}
##
- ## `onSymbol()` can be used to handle symbol name modifications required due to invalid
- ## characters like leading/trailing `_` or rename symbols that would clash due to Nim's style
- ## insensitivity. It can also be used to remove prefixes and suffixes like `SDL_`. The symbol
- ## name and type is provided to the callback and the name can be modified.
+ ## `onSymbol()` can be used to handle symbol name modifications required due
+ ## to invalid characters in identifiers or to rename symbols that would clash
+ ## due to Nim's style insensitivity. The symbol name and type is provided to
+ ## the callback and the name can be modified.
##
- ## Returning a blank name will result in the symbol being skipped. This will fail for `nskParam`
- ## and `nskField` since the generated Nim code will be wrong.
+ ## While `cPlugin` can easily remove leading/trailing `_` or prefixes and
+ ## suffixes like `SDL_`, passing `--prefix` or `--suffix` flags to `cImport`
+ ## in the `flags` parameter is much easier. However, these flags will only be
+ ## considered when no `cPlugin` is specified.
+ ##
+ ## Returning a blank name will result in the symbol being skipped. This will
+ ## fail for `nskParam` and `nskField` since the generated Nim code will be wrong.
##
## Symbol types can be any of the following:
## - `nskConst` for constants
@@ -316,10 +321,12 @@ macro cPlugin*(body): untyped =
## - `nskEnumField` for enum (field) names, though they are in the global namespace as `nskConst`
## - `nskProc` - for proc names
##
- ## `nimterop/plugins` is implicitly imported to provide access to standard plugin facilities.
+ ## `nimterop/plugins` is implicitly imported to provide access to standard
+ ## plugin facilities.
##
## `cPlugin() <cimport.html#cPlugin.m>`_ only affects calls to
- ## `cImport() <cimport.html#cImport.m%2C%2Cstring%2Cstring%2Cstring>`_ that follow it.
+ ## `cImport() <cimport.html#cImport.m%2C%2Cstring%2Cstring%2Cstring>`_ that
+ ## follow it.
runnableExamples:
cPlugin:
import strutils
@@ -572,7 +579,9 @@ macro cImport*(filename: static string, recurse: static bool = false, dynlib: st
## `mode` is purely for forward compatibility when toast adds C++ support. It can
## be ignored for the foreseeable future.
##
- ## `flags` can be used to pass any other command line arguments to `toast`.
+ ## `flags` can be used to pass any other command line arguments to `toast`. A
+ ## good example would be `--prefix` and `--suffix` which strip leading and
+ ## trailing strings from identifiers, `_` being quite common.
##
## `cImport()` consumes and resets preceding `cOverride()` calls. `cPlugin()`
## is retained for the next `cImport()` call unless a new `cPlugin()` call is
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index 53e04f8..1c5f8aa 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -112,6 +112,7 @@ proc getIdentifier*(nimState: NimState, name: string, kind: NimSymKind, parent="
if name notin nimState.gState.symOverride or parent.nBl:
if nimState.gState.onSymbol != nil:
+ # Use onSymbol from plugin provided by user
var
sym = Symbol(name: name, parent: parent, kind: kind)
nimState.gState.onSymbol(sym)
@@ -120,11 +121,23 @@ proc getIdentifier*(nimState: NimState, name: string, kind: NimSymKind, parent="
else:
result = name
+ # Strip out --prefix from CLI if specified
+ for str in nimState.gState.prefix:
+ if result.startsWith(str):
+ result = result[str.len .. ^1]
+
+ # Strip out --suffix from CLI if specified
+ for str in nimState.gState.suffix:
+ if result.endsWith(str):
+ result = result[0 .. ^(str.len+1)]
+
checkIdentifier(result, $kind, parent, name)
if result in gReserved or (result == "object" and kind != nskType):
+ # Enclose in backticks since Nim reserved word
result = &"`{result}`"
else:
+ # Skip identifier since in symOverride
result = ""
proc getUniqueIdentifier*(nimState: NimState, prefix = ""): string =
diff --git a/nimterop/globals.nim b/nimterop/globals.nim
index de29385..7c512b1 100644
--- a/nimterop/globals.nim
+++ b/nimterop/globals.nim
@@ -53,7 +53,7 @@ type
AstTable {.used.} = TableRef[string, seq[ref Ast]]
State = ref object
- compile*, defines*, headers*, includeDirs*, searchDirs*, symOverride*: seq[string]
+ compile*, defines*, headers*, includeDirs*, searchDirs*, prefix*, suffix*, symOverride*: seq[string]
nocache*, nocomments*, debug*, past*, preprocess*, pnim*, pretty*, recurse*: bool
diff --git a/nimterop/toast.nim b/nimterop/toast.nim
index 9da8283..a27d415 100644
--- a/nimterop/toast.nim
+++ b/nimterop/toast.nim
@@ -97,42 +97,51 @@ proc process(gState: State, path: string, astTable: AstTable) =
elif gState.preprocess:
echo gState.code
+# CLI processing with default values
proc main(
- preprocess = false,
- past = false,
- pnim = false,
- recurse = false,
- nocomments = false,
+ debug = false,
defines: seq[string] = @[],
- includeDirs: seq[string] = @[],
dynlib: string = "",
- symOverride: seq[string] = @[],
- nim: string = "nim",
- pluginSourcePath: string = "",
- debug = false,
+ includeDirs: seq[string] = @[],
mode = modeDefault,
+ nim: string = "nim",
+ nocomments = false,
+ past = false,
pgrammar = false,
+ pluginSourcePath: string = "",
+ pnim = false,
+ prefix: seq[string] = @[],
+ preprocess = false,
+ recurse = false,
+ suffix: seq[string] = @[],
+ symOverride: seq[string] = @[],
source: seq[string]
) =
+ # Setup global state with arguments
var gState = State(
- preprocess: preprocess,
- past: past,
- pnim: pnim,
- recurse: recurse,
- nocomments: nocomments,
+ debug: debug,
defines: defines,
- includeDirs: includeDirs,
dynlib: dynlib,
- symOverride: symOverride,
+ includeDirs: includeDirs,
+ mode: mode,
nim: nim,
+ nocomments: nocomments,
+ past: past,
pluginSourcePath: pluginSourcePath,
- debug: debug,
- mode: mode,
- pretty: true
+ pnim: pnim,
+ prefix: prefix,
+ preprocess: preprocess,
+ pretty: true,
+ recurse: recurse,
+ suffix: suffix,
+ symOverride: symOverride
)
+ # Split some arguments with ,
gState.symOverride = gState.symOverride.getSplitComma()
+ gState.prefix = gState.prefix.getSplitComma()
+ gState.suffix = gState.suffix.getSplitComma()
if pluginSourcePath.nBl:
gState.loadPlugin(pluginSourcePath)
@@ -148,33 +157,38 @@ proc main(
gState.process(src.expandSymlinkAbs(), astTable)
when isMainModule:
+ # Setup cligen command line help and short flags
import cligen
dispatch(main, help = {
- "preprocess": "run preprocessor on header",
- "past": "print AST output",
- "pnim": "print Nim output",
- "recurse": "process #include files",
- "nocomments": "exclude top-level comments from output",
+ "debug": "enable debug output",
"defines": "definitions to pass to preprocessor",
- "includeDirs": "include directory to pass to preprocessor",
"dynlib": "Import symbols from library in specified Nim string",
- "symOverride": "skip generating specified symbols",
- "nim": "use a particular Nim executable (default: $PATH/nim)",
- "pluginSourcePath": "Nim file to build and load as a plugin",
- "debug": "enable debug output",
+ "includeDirs": "include directory to pass to preprocessor",
"mode": "language parser: c or cpp",
+ "nim": "use a particular Nim executable (default: $PATH/nim)",
+ "nocomments": "exclude top-level comments from output",
+ "past": "print AST output",
"pgrammar": "print grammar",
- "source" : "C/C++ source/header"
+ "pluginSourcePath": "Nim file to build and load as a plugin",
+ "pnim": "print Nim output",
+ "preprocess": "run preprocessor on header",
+ "recurse": "process #include files",
+ "source" : "C/C++ source/header",
+ "prefix": "Strip prefix from identifiers",
+ "suffix": "Strip suffix from identifiers",
+ "symOverride": "skip generating specified symbols"
}, short = {
- "preprocess": 'p',
+ "debug": 'd',
+ "defines": 'D',
+ "dynlib": 'l',
+ "includeDirs": 'I',
+ "nocomments": 'c',
"past": 'a',
+ "pgrammar": 'g',
"pnim": 'n',
+ "prefix": 'E',
+ "preprocess": 'p',
"recurse": 'r',
- "nocomments": 'c',
- "defines": 'D',
- "includeDirs": 'I',
- "dynlib": 'l',
- "symOverride": 'O',
- "debug": 'd',
- "pgrammar": 'g'
+ "suffix": 'F',
+ "symOverride": 'O'
})
diff --git a/tests/lzma.nim b/tests/lzma.nim
index 785e0bb..b207a46 100644
--- a/tests/lzma.nim
+++ b/tests/lzma.nim
@@ -4,6 +4,7 @@ import nimterop/[build, cimport]
const
baseDir = getProjectCacheDir("nimterop" / "tests" / "liblzma")
+ flags = "--prefix=__,_"
static:
cDebug()
@@ -21,12 +22,6 @@ getHeader(
conFlags = "--disable-xz --disable-xzdec --disable-lzmadec --disable-lzmainfo"
)
-cPlugin:
- import strutils
-
- proc onSymbol*(sym: var Symbol) {.exportc, dynlib.} =
- sym.name = sym.name.strip(chars = {'_'})
-
cOverride:
type
lzma_internal = object
@@ -39,8 +34,8 @@ cOverride:
lzma_index_iter = object
when not lzmaStatic:
- cImport(lzmaPath, recurse = true, dynlib = "lzmaLPath")
+ cImport(lzmaPath, recurse = true, dynlib = "lzmaLPath", flags = flags)
else:
- cImport(lzmaPath, recurse = true)
+ cImport(lzmaPath, recurse = true, flags = flags)
echo "liblzma version = " & $lzma_version_string()