Skip to content

Commit 3dfd742

Browse files
elcritchJaremy J. Creechley
andauthored
Add varargs to defines, defines as C imports, and CLI mangle option (#222)
* adjust parser to accept C preprocessor vararg macros * enable setting define's as imports * fixing handling of untyped arguments * setup constant defines to be var importable * var define kind of working * fixing outputting var consts * adding mangle option for command line Co-authored-by: Jaremy J. Creechley <[email protected]>
1 parent bc8edce commit 3dfd742

File tree

4 files changed

+117
-3
lines changed

4 files changed

+117
-3
lines changed

c2nim.nim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,17 @@ Options:
4141
--noconv annotate procs with ``{.noconv.}``
4242
--stdcall annotate procs with ``{.stdcall.}``
4343
--importc annotate procs with ``{.importc.}``
44+
--importdefines import C defines as procs or vars with ``{.importc.}``
45+
--importfuncdefines import C define funcs as procs with ``{.importc.}``
4446
--ref convert typ* to ref typ (default: ptr typ)
4547
--prefix:PREFIX strip prefix for the generated Nim identifiers
4648
(multiple --prefix options are supported)
4749
--suffix:SUFFIX strip suffix for the generated Nim identifiers
4850
(multiple --suffix options are supported)
51+
--mangle:PEG=FORMAT extra PEG expression to mangle identifiers,
52+
for example `--mangle:'{u?}int{\d+}_t=$1int$2'` to
53+
convert C <stdint.h> to Nim equivalents
54+
(multiple --mangle options are supported)
4955
--paramprefix:PREFIX add prefix to parameter name of the generated Nim proc
5056
--assumedef:IDENT skips #ifndef sections for the given C identifier
5157
(multiple --assumedef options are supported)

compiler/renderer.nim

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,13 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
11731173
else:
11741174
put(g, tkPtr, "ptr")
11751175
of nkVarTy:
1176-
if sonsLen(n) > 0:
1176+
if sonsLen(n) > 2 and n.sons[1].kind == nkPragma:
1177+
putWithSpace(g, tkVar, "var")
1178+
gsub(g, n.sons[0])
1179+
gsub(g, n.sons[1])
1180+
putWithSpace(g, tkColon, ":")
1181+
gsub(g, n.sons[2])
1182+
elif sonsLen(n) > 0:
11771183
putWithSpace(g, tkVar, "var")
11781184
gsub(g, n.sons[0])
11791185
else:

cparser.nim

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ type
6565
classes: StringTableRef
6666
toPreprocess: StringTableRef
6767
inheritable: StringTableRef
68-
debugMode, followNep1, useHeader: bool
68+
debugMode, followNep1: bool
69+
useHeader, importdefines, importfuncdefines: bool
6970
discardablePrefixes: seq[string]
7071
constructor, destructor, importcLit: string
7172
exportPrefix*: string
@@ -148,6 +149,10 @@ proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool =
148149
of "header":
149150
parserOptions.useHeader = true
150151
if val.len > 0: parserOptions.headerOverride = val
152+
of "importfuncdefines":
153+
parserOptions.importfuncdefines = true
154+
of "importdefines":
155+
parserOptions.importdefines = true
151156
of "cdecl": incl(parserOptions.flags, pfCdecl)
152157
of "stdcall": incl(parserOptions.flags, pfStdCall)
153158
of "importc": incl(parserOptions.flags, pfImportc)
@@ -158,6 +163,9 @@ proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool =
158163
if val.len > 0: parserOptions.paramPrefix = val
159164
of "assumedef": parserOptions.assumeDef.add(val)
160165
of "assumendef": parserOptions.assumenDef.add(val)
166+
of "mangle":
167+
let vals = val.split("=")
168+
parserOptions.mangleRules.add((parsePeg(vals[0]), vals[1]))
161169
of "skipinclude": incl(parserOptions.flags, pfSkipInclude)
162170
of "typeprefixes": incl(parserOptions.flags, pfTypePrefixes)
163171
of "skipcomments": incl(parserOptions.flags, pfSkipComments)

preprocessor.nim

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,28 @@ proc parseDefine(p: var Parser; hasParams: bool): PNode =
5454
addSon(params, emptyNode)
5555
if p.tok.xkind != pxParRi:
5656
var identDefs = newNodeP(nkIdentDefs, p)
57+
var isVariable = false
5758
while p.tok.xkind != pxParRi:
59+
if p.tok.xkind == pxDotDotDot:
60+
isVariable = true
61+
getTok(p)
62+
break
5863
addSon(identDefs, skipIdent(p, skParam))
5964
skipStarCom(p, nil)
6065
if p.tok.xkind != pxComma: break
6166
getTok(p)
6267
addSon(identDefs, newIdentNodeP("untyped", p))
6368
addSon(identDefs, emptyNode)
6469
addSon(params, identDefs)
70+
if isVariable:
71+
var vdefs = newNodeP(nkExprColonExpr, p)
72+
addSon(vdefs, newIdentNodeP("xargs", p))
73+
var vdecl =
74+
newTree(nkBracketExpr,
75+
newIdentNodeP("varargs", p),
76+
newIdentNodeP("untyped", p))
77+
addSon(vdefs, vdecl)
78+
addSon(params, vdefs)
6579
eat(p, pxParRi)
6680

6781
addSon(result, emptyNode) # no generic parameters
@@ -91,6 +105,78 @@ proc parseDefine(p: var Parser; hasParams: bool): PNode =
91105
break
92106
assert result != nil
93107

108+
proc parseDefineAsDecls(p: var Parser; hasParams: bool): PNode =
109+
var origName = p.tok.s
110+
if hasParams:
111+
# a macro with parameters:
112+
result = newNodeP(nkProcDef, p)
113+
var name = skipIdentExport(p, skTemplate)
114+
addSon(result, name)
115+
addSon(result, emptyNode)
116+
eat(p, pxParLe)
117+
var params = newNodeP(nkFormalParams, p)
118+
# return type; not known yet:
119+
addSon(params, emptyNode)
120+
121+
var pragmas = newNodeP(nkPragma, p)
122+
123+
if p.tok.xkind != pxParRi:
124+
while p.tok.xkind != pxParRi:
125+
if p.tok.xkind == pxDotDotDot: # handle varargs
126+
getTok(p)
127+
addSon(pragmas, newIdentNodeP("varargs", p))
128+
break
129+
else:
130+
var vdefs = newTree(nkExprColonExpr,
131+
skipIdent(p, skParam),
132+
newIdentNodeP("untyped", p))
133+
addSon(params, vdefs)
134+
135+
skipStarCom(p, nil)
136+
if p.tok.xkind != pxComma:
137+
break
138+
getTok(p)
139+
140+
eat(p, pxParRi)
141+
142+
let iname = cppImportName(p, origName)
143+
addSon(pragmas,
144+
newIdentStrLitPair(p.options.importcLit, iname, p),
145+
getHeaderPair(p))
146+
147+
addSon(result, emptyNode) # no generic parameters
148+
addSon(result, params)
149+
addSon(result, pragmas)
150+
addSon(result, emptyNode)
151+
152+
addSon(result, emptyNode)
153+
skipLine(p)
154+
155+
else:
156+
# a macro without parameters:
157+
result = newNodeP(nkVarTy, p)
158+
159+
while true:
160+
let vname = skipIdentExport(p, skConst)
161+
# skipStarCom(p, result)
162+
let iname = cppImportName(p, origName)
163+
var vpragmas = newNodeP(nkPragma, p)
164+
addSon(vpragmas, newIdentStrLitPair(p.options.importcLit, iname, p))
165+
addSon(vpragmas, getHeaderPair(p))
166+
let vtype = newIdentNodeP("int", p)
167+
168+
addSon(result, vname)
169+
addSon(result, vpragmas)
170+
addSon(result, vtype)
171+
172+
skipCom(p, result)
173+
skipLine(p) # eat the rest of the define, skip parsing
174+
if p.tok.xkind == pxDirective and p.tok.s == "define":
175+
getTok(p)
176+
else:
177+
break
178+
assert result != nil
179+
94180
proc dontTranslateToTemplateHeuristic(body: seq[ref Token]; closedParentheses: int): bool =
95181
# we list all **binary** operators here too: As these cannot start an
96182
# expression, we know the resulting #define cannot be a valid Nim template.
@@ -184,6 +270,9 @@ proc parseDef(p: var Parser, m: var Macro; hasParams: bool): bool =
184270
if hasParams:
185271
eat(p, pxParLe)
186272
while p.tok.xkind != pxParRi:
273+
if p.tok.xkind == pxDotDotDot:
274+
getTok(p)
275+
break
187276
expectIdent(p)
188277
params.add(p.tok.s)
189278
getTok(p)
@@ -510,7 +599,12 @@ proc parseDir(p: var Parser; sectionParser: SectionParser): PNode =
510599
if not parseDef(p, p.options.macros[L], hasParams) and not isDefOverride:
511600
setLen(p.options.macros, L)
512601
backtrackContext(p)
513-
result = parseDefine(p, hasParams)
602+
if p.options.importdefines:
603+
result = parseDefineAsDecls(p, hasParams)
604+
elif p.options.importfuncdefines and hasParams:
605+
result = parseDefineAsDecls(p, hasParams)
606+
else:
607+
result = parseDefine(p, hasParams)
514608
else:
515609
closeContext(p)
516610

0 commit comments

Comments
 (0)