Add preprocessor step in toast
This commit is contained in:
parent
14b75cea31
commit
9ee67da1c2
5 changed files with 83 additions and 22 deletions
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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`)
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
import regex
|
|
||||||
|
|
||||||
import globals
|
import globals
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
|
||||||
51
toast.nim
51
toast.nim
|
|
@ -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()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue