aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2018-11-27 14:56:47 -0600
committerGanesh Viswanathan <dev@genotrance.com>2018-11-27 14:56:47 -0600
commit9ee67da1c254db70b84712a96c33389f5f3feb9b (patch)
tree400da5fe5dbe8535f89d83a75dbd8fe1833a4de7
parent14b75cea31bb923801dd7857699abb3d2a30c9d6 (diff)
downloadnimterop-9ee67da1c254db70b84712a96c33389f5f3feb9b.tar.gz
nimterop-9ee67da1c254db70b84712a96c33389f5f3feb9b.zip
Add preprocessor step in toast
-rw-r--r--nimterop/getters.nim41
-rw-r--r--nimterop/git.nim9
-rw-r--r--nimterop/globals.nim2
-rw-r--r--nimterop/lisp.nim2
-rw-r--r--toast.nim51
5 files changed, 83 insertions, 22 deletions
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index 6ba83e8..c9ac3b9 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -1,9 +1,12 @@
-import macros, strformat, strutils
+import macros, ospaths, strformat, strutils
import regex
import git, globals
+proc sanitizePath*(path: string): string =
+ path.multiReplace([("\\\\", $DirSep), ("\\", $DirSep), ("//", $DirSep)])
+
proc getIdentifier*(str: string): string =
result = str.strip(chars={'_'})
@@ -42,12 +45,42 @@ proc getPreprocessor*(fullpath: string, mode = "cpp"): string =
var
mmode = if mode == "cpp": "c++" else: mode
cmd = &"gcc -E -dD -x{mmode} "
+ gdef, gdir: seq[string]
+
+ rdata: seq[string] = @[]
+ start = false
+ sfile = fullpath.sanitizePath
- for inc in gIncludeDirs:
+ when nimvm:
+ gdef = gDefines
+ gdir = gIncludeDirs
+ else:
+ gdef = gDefinesRT
+ gdir = gIncludeDirsRT
+
+ for inc in gdir:
cmd &= &"-I\"{inc}\" "
- for def in gDefines:
+ for def in gdef:
cmd &= &"-D{def} "
cmd &= &"\"{fullpath}\""
- return staticExec(cmd) \ No newline at end of file
+
+ # Include content only from file
+ for line in execAction(cmd).splitLines():
+ if line.strip() != "":
+ if line[0] == '#' and not line.contains("#pragma") and not line.contains("define"):
+ start = false
+ if sfile in line.sanitizePath:
+ start = true
+ if not ("\\" in line) and not ("/" in line) and extractFilename(sfile) in line:
+ start = true
+ else:
+ if start:
+ rdata.add(
+ line.multiReplace([("_Noreturn", ""), ("(())", ""), ("WINAPI", ""),
+ ("__attribute__", ""), ("extern \"C\"", "")])
+ .replace(re"\(\([_a-z]+?\)\)", "")
+ .replace(re"\(\(__format__[\s]*\(__[gnu_]*printf__, [\d]+, [\d]+\)\)\);", ";")
+ )
+ return rdata.join("\n")
diff --git a/nimterop/git.nim b/nimterop/git.nim
index b55b365..51ea756 100644
--- a/nimterop/git.nim
+++ b/nimterop/git.nim
@@ -1,4 +1,4 @@
-import macros, os, regex, strformat, strutils
+import macros, os, osproc, regex, strformat, strutils
import globals
@@ -11,7 +11,10 @@ proc execAction*(cmd: string): string =
when defined(Linux) or defined(MacOSX):
ccmd = "bash -c '" & cmd & "'"
- (result, ret) = gorgeEx(ccmd)
+ when nimvm:
+ (result, ret) = gorgeEx(ccmd)
+ else:
+ (result, ret) = execCmdEx(ccmd)
if ret != 0:
echo "Command failed: " & $ret
echo ccmd
@@ -66,7 +69,7 @@ macro gitPull*(url: static string, outdirN = "", plistN = "", checkoutN = ""): u
outdir = getProjectPath()/outdirN.strVal()
plist = plistN.strVal()
checkout = checkoutN.strVal()
-
+
if dirExists(outdir/".git"):
discard quote do:
gitReset(`outdirN`)
diff --git a/nimterop/globals.nim b/nimterop/globals.nim
index ccc4ec2..ae3d03b 100644
--- a/nimterop/globals.nim
+++ b/nimterop/globals.nim
@@ -20,10 +20,12 @@ type
var
gDefines* {.compiletime.}: seq[string]
+ gDefinesRT*: seq[string]
gCompile* {.compiletime.}: seq[string]
gConsts* {.compiletime.}: seq[string]
gHeaders* {.compiletime.}: seq[string]
gIncludeDirs* {.compiletime.}: seq[string]
+ gIncludeDirsRT*: seq[string]
gProcs* {.compiletime.}: seq[string]
gSearchDirs* {.compiletime.}: seq[string]
gTypes* {.compiletime.}: seq[string]
diff --git a/nimterop/lisp.nim b/nimterop/lisp.nim
index 2727c18..c4a3b54 100644
--- a/nimterop/lisp.nim
+++ b/nimterop/lisp.nim
@@ -1,7 +1,5 @@
import strutils
-import regex
-
import globals
var
diff --git a/toast.nim b/toast.nim
index b117f05..4e01de7 100644
--- a/toast.nim
+++ b/toast.nim
@@ -1,13 +1,17 @@
import os, strutils
-import regex
-
import treesitter/[runtime, c, cpp]
+import nimterop/[globals, getters]
+
const HELP = """
> toast header.h
--m minimized output - non-pretty
--c C mode - CPP is default"""
+-a print AST output
+-c C mode - CPP is default
+-m print minimized AST output - non-pretty (implies -a)
+-p run preprocessor on header
+-D definitions to pass to preprocessor
+-I include directory to pass to preprocessor"""
proc printLisp(root: TSNode, data: var string, pretty = true) =
var
@@ -20,6 +24,8 @@ proc printLisp(root: TSNode, data: var string, pretty = true) =
if pretty:
stdout.write spaces(depth)
stdout.write "(" & $node.tsNodeType() & " " & $node.tsNodeStartByte() & " " & $node.tsNodeEndByte()
+ else:
+ return
if node.tsNodeNamedChildCount() != 0:
if pretty:
@@ -37,6 +43,8 @@ proc printLisp(root: TSNode, data: var string, pretty = true) =
while true:
node = node.tsNodeParent()
depth -= 1
+ if depth == -1:
+ break
if pretty:
echo spaces(depth) & ")"
else:
@@ -52,7 +60,7 @@ proc printLisp(root: TSNode, data: var string, pretty = true) =
if node == root:
break
-proc process(path: string, mode="cpp", pretty = true) =
+proc process(path: string, mode="cpp", past, pretty, preprocess: bool) =
if not existsFile(path):
echo "Invalid path " & path
return
@@ -61,7 +69,7 @@ proc process(path: string, mode="cpp", pretty = true) =
parser = tsParserNew()
ext = path.splitFile().ext
pmode = ""
- data = readFile(path)
+ data = ""
defer:
parser.tsParserDelete()
@@ -73,8 +81,10 @@ proc process(path: string, mode="cpp", pretty = true) =
elif ext in [".hxx", ".hpp", ".hh", ".H", ".h++", ".cpp", ".cxx", ".cc", ".C", ".c++"]:
pmode = "cpp"
- if "cplusplus" in data or "extern \"C\"" in data:
- pmode = "cpp"
+ if preprocess:
+ data = getPreprocessor(path)
+ else:
+ data = readFile(path)
if pmode == "c":
if not parser.tsParserSetLanguage(treeSitterC()):
@@ -95,23 +105,38 @@ proc process(path: string, mode="cpp", pretty = true) =
defer:
tree.tsTreeDelete()
- printLisp(root, data, pretty)
+ if past:
+ printLisp(root, data, pretty)
proc parseCli() =
var
mode = "cpp"
params = commandLineParams()
+
+ past = false
pretty = true
+ preprocess = false
for param in params:
- if param in ["-h", "--help", "-?", "/?", "/h"]:
+ let flag = if param.len() <= 2: param else: param[0..<2]
+
+ if flag in ["-h", "--help", "-?", "/?", "/h"]:
echo HELP
quit()
- elif param == "-c":
+ elif flag == "-a":
+ past = true
+ elif flag == "-c":
mode = "c"
- elif param == "-m":
+ elif flag == "-m":
+ past = true
pretty = false
+ elif flag == "-p":
+ preprocess = true
+ elif flag == "-D":
+ gDefinesRT.add(param[2..^1])
+ elif flag == "-I":
+ gIncludeDirsRT.add(param[2..^1])
else:
- process(param, mode, pretty)
+ process(param, mode, past, pretty, preprocess)
parseCli() \ No newline at end of file