Add preprocessor step in toast

This commit is contained in:
Ganesh Viswanathan 2018-11-27 14:56:47 -06:00
commit 9ee67da1c2
5 changed files with 83 additions and 22 deletions

View file

@ -1,9 +1,12 @@
import macros, strformat, strutils import macros, ospaths, strformat, strutils
import regex import regex
import git, globals import git, globals
proc sanitizePath*(path: string): string =
path.multiReplace([("\\\\", $DirSep), ("\\", $DirSep), ("//", $DirSep)])
proc getIdentifier*(str: string): string = proc getIdentifier*(str: string): string =
result = str.strip(chars={'_'}) result = str.strip(chars={'_'})
@ -42,12 +45,42 @@ proc getPreprocessor*(fullpath: string, mode = "cpp"): string =
var var
mmode = if mode == "cpp": "c++" else: mode mmode = if mode == "cpp": "c++" else: mode
cmd = &"gcc -E -dD -x{mmode} " cmd = &"gcc -E -dD -x{mmode} "
gdef, gdir: seq[string]
for inc in gIncludeDirs: rdata: seq[string] = @[]
start = false
sfile = fullpath.sanitizePath
when nimvm:
gdef = gDefines
gdir = gIncludeDirs
else:
gdef = gDefinesRT
gdir = gIncludeDirsRT
for inc in gdir:
cmd &= &"-I\"{inc}\" " cmd &= &"-I\"{inc}\" "
for def in gDefines: for def in gdef:
cmd &= &"-D{def} " cmd &= &"-D{def} "
cmd &= &"\"{fullpath}\"" cmd &= &"\"{fullpath}\""
return staticExec(cmd)
# 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")

View file

@ -1,4 +1,4 @@
import macros, os, regex, strformat, strutils import macros, os, osproc, regex, strformat, strutils
import globals import globals
@ -11,7 +11,10 @@ proc execAction*(cmd: string): string =
when defined(Linux) or defined(MacOSX): when defined(Linux) or defined(MacOSX):
ccmd = "bash -c '" & cmd & "'" ccmd = "bash -c '" & cmd & "'"
(result, ret) = gorgeEx(ccmd) when nimvm:
(result, ret) = gorgeEx(ccmd)
else:
(result, ret) = execCmdEx(ccmd)
if ret != 0: if ret != 0:
echo "Command failed: " & $ret echo "Command failed: " & $ret
echo ccmd echo ccmd
@ -66,7 +69,7 @@ macro gitPull*(url: static string, outdirN = "", plistN = "", checkoutN = ""): u
outdir = getProjectPath()/outdirN.strVal() outdir = getProjectPath()/outdirN.strVal()
plist = plistN.strVal() plist = plistN.strVal()
checkout = checkoutN.strVal() checkout = checkoutN.strVal()
if dirExists(outdir/".git"): if dirExists(outdir/".git"):
discard quote do: discard quote do:
gitReset(`outdirN`) gitReset(`outdirN`)

View file

@ -20,10 +20,12 @@ type
var var
gDefines* {.compiletime.}: seq[string] gDefines* {.compiletime.}: seq[string]
gDefinesRT*: seq[string]
gCompile* {.compiletime.}: seq[string] gCompile* {.compiletime.}: seq[string]
gConsts* {.compiletime.}: seq[string] gConsts* {.compiletime.}: seq[string]
gHeaders* {.compiletime.}: seq[string] gHeaders* {.compiletime.}: seq[string]
gIncludeDirs* {.compiletime.}: seq[string] gIncludeDirs* {.compiletime.}: seq[string]
gIncludeDirsRT*: seq[string]
gProcs* {.compiletime.}: seq[string] gProcs* {.compiletime.}: seq[string]
gSearchDirs* {.compiletime.}: seq[string] gSearchDirs* {.compiletime.}: seq[string]
gTypes* {.compiletime.}: seq[string] gTypes* {.compiletime.}: seq[string]

View file

@ -1,7 +1,5 @@
import strutils import strutils
import regex
import globals import globals
var var

View file

@ -1,13 +1,17 @@
import os, strutils import os, strutils
import regex
import treesitter/[runtime, c, cpp] import treesitter/[runtime, c, cpp]
import nimterop/[globals, getters]
const HELP = """ const HELP = """
> toast header.h > toast header.h
-m minimized output - non-pretty -a print AST output
-c C mode - CPP is default""" -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) = proc printLisp(root: TSNode, data: var string, pretty = true) =
var var
@ -20,6 +24,8 @@ proc printLisp(root: TSNode, data: var string, pretty = true) =
if pretty: if pretty:
stdout.write spaces(depth) stdout.write spaces(depth)
stdout.write "(" & $node.tsNodeType() & " " & $node.tsNodeStartByte() & " " & $node.tsNodeEndByte() stdout.write "(" & $node.tsNodeType() & " " & $node.tsNodeStartByte() & " " & $node.tsNodeEndByte()
else:
return
if node.tsNodeNamedChildCount() != 0: if node.tsNodeNamedChildCount() != 0:
if pretty: if pretty:
@ -37,6 +43,8 @@ proc printLisp(root: TSNode, data: var string, pretty = true) =
while true: while true:
node = node.tsNodeParent() node = node.tsNodeParent()
depth -= 1 depth -= 1
if depth == -1:
break
if pretty: if pretty:
echo spaces(depth) & ")" echo spaces(depth) & ")"
else: else:
@ -52,7 +60,7 @@ proc printLisp(root: TSNode, data: var string, pretty = true) =
if node == root: if node == root:
break break
proc process(path: string, mode="cpp", pretty = true) = proc process(path: string, mode="cpp", past, pretty, preprocess: bool) =
if not existsFile(path): if not existsFile(path):
echo "Invalid path " & path echo "Invalid path " & path
return return
@ -61,7 +69,7 @@ proc process(path: string, mode="cpp", pretty = true) =
parser = tsParserNew() parser = tsParserNew()
ext = path.splitFile().ext ext = path.splitFile().ext
pmode = "" pmode = ""
data = readFile(path) data = ""
defer: defer:
parser.tsParserDelete() 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++"]: elif ext in [".hxx", ".hpp", ".hh", ".H", ".h++", ".cpp", ".cxx", ".cc", ".C", ".c++"]:
pmode = "cpp" pmode = "cpp"
if "cplusplus" in data or "extern \"C\"" in data: if preprocess:
pmode = "cpp" data = getPreprocessor(path)
else:
data = readFile(path)
if pmode == "c": if pmode == "c":
if not parser.tsParserSetLanguage(treeSitterC()): if not parser.tsParserSetLanguage(treeSitterC()):
@ -95,23 +105,38 @@ proc process(path: string, mode="cpp", pretty = true) =
defer: defer:
tree.tsTreeDelete() tree.tsTreeDelete()
printLisp(root, data, pretty) if past:
printLisp(root, data, pretty)
proc parseCli() = proc parseCli() =
var var
mode = "cpp" mode = "cpp"
params = commandLineParams() params = commandLineParams()
past = false
pretty = true pretty = true
preprocess = false
for param in params: 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 echo HELP
quit() quit()
elif param == "-c": elif flag == "-a":
past = true
elif flag == "-c":
mode = "c" mode = "c"
elif param == "-m": elif flag == "-m":
past = true
pretty = false pretty = false
elif flag == "-p":
preprocess = true
elif flag == "-D":
gDefinesRT.add(param[2..^1])
elif flag == "-I":
gIncludeDirsRT.add(param[2..^1])
else: else:
process(param, mode, pretty) process(param, mode, past, pretty, preprocess)
parseCli() parseCli()