From 7e7699a856854c2e53b76dd4c41cd92661fb7463 Mon Sep 17 00:00:00 2001 From: wt Date: Mon, 5 Jun 2017 10:52:23 +0800 Subject: [PATCH 01/11] Fix bad tail for status response --- lib/pure/asynchttpserver.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 8d059dbbc..0dd32afc7 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -127,7 +127,7 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] = i.inc protocol.parseInt(result.minor, i) proc sendStatus(client: AsyncSocket, status: string): Future[void] = - client.send("HTTP/1.1 " & status & "\c\L") + client.send("HTTP/1.1 " & status & "\c\L\c\L") proc processClient(client: AsyncSocket, address: string, callback: proc (request: Request): From 622b4a7b47c4a9b0bc7c670fddd37f628c5226af Mon Sep 17 00:00:00 2001 From: wt Date: Tue, 6 Jun 2017 08:52:19 +0800 Subject: [PATCH 02/11] Update asynchttpserver.nim --- lib/pure/asynchttpserver.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 0dd32afc7..a374e80e8 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -127,7 +127,7 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] = i.inc protocol.parseInt(result.minor, i) proc sendStatus(client: AsyncSocket, status: string): Future[void] = - client.send("HTTP/1.1 " & status & "\c\L\c\L") + client.send("HTTP/1.1 " & status & "\c\L\c\L") proc processClient(client: AsyncSocket, address: string, callback: proc (request: Request): From 27e2a343403197af08d20207ac884cf134d4892e Mon Sep 17 00:00:00 2001 From: Parashurama Date: Tue, 6 Jun 2017 13:47:34 +0200 Subject: [PATCH 03/11] fixes parseopt/parseopt2 custom cmdline args. --- lib/pure/parseopt.nim | 45 ++++++++++++++++++++----------- lib/pure/parseopt2.nim | 45 ++++++++++++++++++++----------- tests/misc/tparseopt.nim | 57 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 30 deletions(-) create mode 100644 tests/misc/tparseopt.nim diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index 218f5ab81..23568edb9 100644 --- a/lib/pure/parseopt.nim +++ b/lib/pure/parseopt.nim @@ -149,26 +149,41 @@ proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} = ## retrieves the rest of the command line that has not been parsed yet. result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString +iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key, val: TaintedString] = + ## This is an convenience iterator for iterating over the given OptParser object. + ## Example: + ## + ## .. code-block:: nim + ## var p = initOptParser("--left --debug:3 -l=4 -r:2") + ## for kind, key, val in p.getopt(): + ## case kind + ## of cmdArgument: + ## filename = key + ## of cmdLongOption, cmdShortOption: + ## case key + ## of "help", "h": writeHelp() + ## of "version", "v": writeVersion() + ## of cmdEnd: assert(false) # cannot happen + ## if filename == "": + ## # no filename has been given, so we show the help: + ## writeHelp() + p.pos = 0 + while true: + next(p) + if p.kind == cmdEnd: break + yield (p.kind, p.key, p.val) + when declared(initOptParser): iterator getopt*(): tuple[kind: CmdLineKind, key, val: TaintedString] = - ## This is an convenience iterator for iterating over the command line. - ## This uses the OptParser object. Example: + ## This is an convenience iterator for iterating over the command line arguments. + ## This create a new OptParser object. + ## See above for a more detailed example ## ## .. code-block:: nim - ## var - ## filename = "" ## for kind, key, val in getopt(): - ## case kind - ## of cmdArgument: - ## filename = key - ## of cmdLongOption, cmdShortOption: - ## case key - ## of "help", "h": writeHelp() - ## of "version", "v": writeVersion() - ## of cmdEnd: assert(false) # cannot happen - ## if filename == "": - ## # no filename has been given, so we show the help: - ## writeHelp() + ## # this will iterate over all arguments passed to the cmdline. + ## continue + ## var p = initOptParser() while true: next(p) diff --git a/lib/pure/parseopt2.nim b/lib/pure/parseopt2.nim index 7fd9c60fe..2e8dbe140 100644 --- a/lib/pure/parseopt2.nim +++ b/lib/pure/parseopt2.nim @@ -123,26 +123,41 @@ type {.deprecated: [TGetoptResult: GetoptResult].} +iterator getopt*(p: var OptParser): GetoptResult = + ## This is an convenience iterator for iterating over the given OptParser object. + ## Example: + ## + ## .. code-block:: nim + ## var p = initOptParser("--left --debug:3 -l=4 -r:2") + ## for kind, key, val in p.getopt(): + ## case kind + ## of cmdArgument: + ## filename = key + ## of cmdLongOption, cmdShortOption: + ## case key + ## of "help", "h": writeHelp() + ## of "version", "v": writeVersion() + ## of cmdEnd: assert(false) # cannot happen + ## if filename == "": + ## # no filename has been given, so we show the help: + ## writeHelp() + p.pos = 0 + while true: + next(p) + if p.kind == cmdEnd: break + yield (p.kind, p.key, p.val) + when declared(paramCount): iterator getopt*(): GetoptResult = - ## This is an convenience iterator for iterating over the command line. - ## This uses the OptParser object. Example: + ## This is an convenience iterator for iterating over the command line arguments. + ## This create a new OptParser object. + ## See above for a more detailed example ## ## .. code-block:: nim - ## var - ## filename = "" ## for kind, key, val in getopt(): - ## case kind - ## of cmdArgument: - ## filename = key - ## of cmdLongOption, cmdShortOption: - ## case key - ## of "help", "h": writeHelp() - ## of "version", "v": writeVersion() - ## of cmdEnd: assert(false) # cannot happen - ## if filename == "": - ## # no filename has been given, so we show the help: - ## writeHelp() + ## # this will iterate over all arguments passed to the cmdline. + ## continue + ## var p = initOptParser() while true: next(p) diff --git a/tests/misc/tparseopt.nim b/tests/misc/tparseopt.nim new file mode 100644 index 000000000..1f8375dfd --- /dev/null +++ b/tests/misc/tparseopt.nim @@ -0,0 +1,57 @@ +discard """ + file: "tparseopt.nim" + output: ''' +parseopt +first round +kind: cmdLongOption key:val -- left: +second round +kind: cmdLongOption key:val -- left: +kind: cmdLongOption key:val -- debug:3 +kind: cmdShortOption key:val -- l:4 +kind: cmdShortOption key:val -- r:2 +parseopt2 +first round +kind: cmdLongOption key:val -- left: +second round +kind: cmdLongOption key:val -- left: +kind: cmdLongOption key:val -- debug:3 +kind: cmdShortOption key:val -- l:4 +kind: cmdShortOption key:val -- r:2''' +""" +from parseopt import nil +from parseopt2 import nil + + +block: + echo "parseopt" + for kind, key, val in parseopt.getopt(): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val + + # pass custom cmdline arguments + echo "first round" + var argv = "--left --debug:3 -l=4 -r:2" + var p = parseopt.initOptParser(argv) + for kind, key, val in parseopt.getopt(p): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val + break + # reset getopt iterator and check arguments are returned correctly. + echo "second round" + for kind, key, val in parseopt.getopt(p): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val + +block: + echo "parseopt2" + for kind, key, val in parseopt2.getopt(): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val + + # pass custom cmdline arguments + echo "first round" + var argv: seq[string] = @["--left", "--debug:3", "-l=4", "-r:2"] + var p = parseopt2.initOptParser(argv) + for kind, key, val in parseopt2.getopt(p): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val + break + # reset getopt iterator and check arguments are returned correctly. + echo "second round" + for kind, key, val in parseopt2.getopt(p): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val From bbf9ef606d08a6ae91fdf1efccd6f37aadc41237 Mon Sep 17 00:00:00 2001 From: Parashurama Date: Wed, 7 Jun 2017 08:52:50 +0200 Subject: [PATCH 04/11] restrict casting for closure. (#5948); fixes #5742 * restrict casting for closure. This commit forbid casting a closure to anything other than another closure. use rawEnv/rawProc to access underlaying pointers. * better error message for closure cast * fixes #5742 --- compiler/semexprs.nim | 7 ++++++- tests/misc/tcast.nim | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/misc/tcast.nim diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9c93d54a3..67a718b91 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -152,6 +152,8 @@ proc isCastable(dst, src: PType): bool = result = false elif typeAllowed(dst, skParam) != nil: result = false + elif dst.kind == tyProc and dst.callConv == ccClosure: + result = src.kind == tyProc and src.callConv == ccClosure else: result = (dstSize >= srcSize) or (skipTypes(dst, abstractInst).kind in IntegralTypes) or @@ -227,7 +229,10 @@ proc semCast(c: PContext, n: PNode): PNode = if tfHasMeta in targetType.flags: localError(n.sons[0].info, errCastToANonConcreteType, $targetType) if not isCastable(targetType, castedExpr.typ): - localError(n.info, errExprCannotBeCastToX, $targetType) + let tar = $targetType + let alt = typeToString(targetType, preferDesc) + let msg = if tar != alt: tar & "=" & alt else: tar + localError(n.info, errExprCannotBeCastToX, msg) result = newNodeI(nkCast, n.info) result.typ = targetType addSon(result, copyTree(n.sons[0])) diff --git a/tests/misc/tcast.nim b/tests/misc/tcast.nim new file mode 100644 index 000000000..4e27040fb --- /dev/null +++ b/tests/misc/tcast.nim @@ -0,0 +1,23 @@ +discard """ + output: ''' +Hello World +Hello World''' +""" +type MyProc = proc() {.cdecl.} +type MyProc2 = proc() {.nimcall.} +type MyProc3 = proc() #{.closure.} is implicit + +proc testProc() = echo "Hello World" + +proc callPointer(p: pointer) = + # can cast to proc(){.cdecl.} + let ffunc0 = cast[MyProc](p) + # can cast to proc(){.nimcall.} + let ffunc1 = cast[MyProc2](p) + # cannot cast to proc(){.closure.} + doAssert(not compiles(cast[MyProc3](p))) + + ffunc0() + ffunc1() + +callPointer(cast[pointer](testProc)) From 0c8c878f5a9a33e50be8a998f9b476d078469a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20Talpalaru?= Date: Thu, 8 Jun 2017 09:53:35 +0200 Subject: [PATCH 05/11] support libgo from GCC 6.3 (#5964) --- lib/system/mmdisp.nim | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index 431f84bfd..5b5ba9490 100644 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -255,12 +255,21 @@ elif defined(gogc): next_gc: uint64 # next GC (in heap_alloc time) last_gc: uint64 # last GC (in absolute time) pause_total_ns: uint64 - pause_ns: array[256, uint64] + pause_ns: array[256, uint64] # circular buffer of recent gc pause lengths + pause_end: array[256, uint64] # circular buffer of recent gc end times (nanoseconds since 1970) numgc: uint32 + numforcedgc: uint32 # number of user-forced GCs + gc_cpu_fraction: float64 # fraction of CPU time used by GC enablegc: cbool debuggc: cbool # Statistics about allocation size classes. by_size: array[goNumSizeClasses, goMStats_inner_struct] + # Statistics below here are not exported to MemStats directly. + tinyallocs: uint64 # number of tiny allocations that didn't cause actual allocation; not exported to go directly + gc_trigger: uint64 + heap_live: uint64 + heap_scan: uint64 + heap_marked: uint64 proc goRuntime_ReadMemStats(a2: ptr goMStats) {.cdecl, importc: "runtime_ReadMemStats", From 82effc581d956edabed9f0abd68db264b4dcd509 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 8 Jun 2017 12:57:39 +0200 Subject: [PATCH 06/11] added koch xtemp command for easier compiler development --- koch.nim | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/koch.nim b/koch.nim index 743445094..aaa03d558 100644 --- a/koch.nim +++ b/koch.nim @@ -470,6 +470,17 @@ proc temp(args: string) = copyExe(output, finalDest) if programArgs.len > 0: exec(finalDest & " " & programArgs) +proc xtemp(cmd: string) = + let d = getAppDir() + copyExe(d / "bin" / "nim".exe, d / "bin" / "nim_backup".exe) + try: + withDir(d): + temp"-d:debug" + copyExe(d / "bin" / "nim_temp".exe, d / "bin" / "nim".exe) + exec(cmd) + finally: + copyExe(d / "bin" / "nim_backup".exe, d / "bin" / "nim".exe) + proc pushCsources() = if not dirExists("../csources/.git"): quit "[Error] no csources git repository found" @@ -545,6 +556,7 @@ of cmdArgument: of "testinstall": testUnixInstall() of "test", "tests": tests(op.cmdLineRest) of "temp": temp(op.cmdLineRest) + of "xtemp": xtemp(op.cmdLineRest) of "winrelease": winRelease() of "wintools": bundleWinTools() of "nimble": buildNimble(existsDir(".git")) From 4033929127f940a967d0ef522e7e1ecba049b6f1 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 8 Jun 2017 18:35:37 +0200 Subject: [PATCH 07/11] fixes tproctypecache_falsepositive.nim test case --- compiler/seminst.nim | 3 ++- compiler/semtypinst.nim | 5 +++-- compiler/types.nim | 6 ++++++ tests/generics/tproctypecache_falsepositive.nim | 17 +++++++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 tests/generics/tproctypecache_falsepositive.nim diff --git a/compiler/seminst.nim b/compiler/seminst.nim index b5dca4c1b..486065563 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -88,7 +88,8 @@ proc sameInstantiation(a, b: TInstantiation): bool = if a.concreteTypes.len == b.concreteTypes.len: for i in 0..a.concreteTypes.high: if not compareTypes(a.concreteTypes[i], b.concreteTypes[i], - flags = {ExactTypeDescValues}): return + flags = {ExactTypeDescValues, + ExactGcSafety}): return result = true proc genericCacheGet(genericSym: PSym, entry: TInstantiation; diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 80fb9168b..037b07510 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -243,6 +243,7 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType = proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = # tyGenericInvocation[A, tyGenericInvocation[A, B]] # is difficult to handle: + const eqFlags = eqTypeFlags + {tfGcSafe} var body = t.sons[0] if body.kind != tyGenericBody: internalError(cl.info, "no generic body") var header: PType = t @@ -252,7 +253,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = else: result = searchInstTypes(t) - if result != nil and eqTypeFlags*result.flags == eqTypeFlags*t.flags: return + if result != nil and eqFlags*result.flags == eqFlags*t.flags: return for i in countup(1, sonsLen(t) - 1): var x = t.sons[i] if x.kind in {tyGenericParam}: @@ -267,7 +268,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = if header != t: # search again after first pass: result = searchInstTypes(header) - if result != nil and eqTypeFlags*result.flags == eqTypeFlags*t.flags: return + if result != nil and eqFlags*result.flags == eqFlags*t.flags: return else: header = instCopyType(cl, t) diff --git a/compiler/types.nim b/compiler/types.nim index 2886ac619..13b24ccf8 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -139,6 +139,9 @@ proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string = add(result, ')') if n.sons[0].typ != nil: result.add(": " & typeToString(n.sons[0].typ, prefer)) + result.add "[declared in " + result.add($sym.info) + result.add "]" proc elemType*(t: PType): PType = assert(t != nil) @@ -688,6 +691,7 @@ type ExactTypeDescValues ExactGenericParams ExactConstraints + ExactGcSafety AllowCommonBase TTypeCmpFlags* = set[TTypeCmpFlag] @@ -976,6 +980,8 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = cycleCheck() if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n result = sameChildrenAux(a, b, c) and sameFlags(a, b) + if result and ExactGcSafety in c.flags: + result = a.flags * {tfThread} == b.flags * {tfThread} if result and a.kind == tyProc: result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and ((ExactConstraints notin c.flags) or sameConstraints(a.n, b.n)) diff --git a/tests/generics/tproctypecache_falsepositive.nim b/tests/generics/tproctypecache_falsepositive.nim new file mode 100644 index 000000000..4f24a1fc8 --- /dev/null +++ b/tests/generics/tproctypecache_falsepositive.nim @@ -0,0 +1,17 @@ + +import asyncdispatch + +type + Callback = proc() {.closure, gcsafe.} + GameState = ref object + playerChangeHandlers: seq[Callback] + +#proc dummy() = +# var x = newSeq[proc() {.cdecl, gcsafe.}]() + +proc newGameState(): GameState = + result = GameState( + playerChangeHandlers: newSeq[Callback]() # this fails + ) + +#dummy() From 280941aca675d91abbd348aa45848c6e0585c879 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 9 Jun 2017 13:34:45 +0200 Subject: [PATCH 08/11] make tests green again --- tests/modules/tmismatchedvisibility.nim | 2 +- tests/pragmas/tused.nim | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/modules/tmismatchedvisibility.nim b/tests/modules/tmismatchedvisibility.nim index 325c729c0..91b639a27 100644 --- a/tests/modules/tmismatchedvisibility.nim +++ b/tests/modules/tmismatchedvisibility.nim @@ -1,6 +1,6 @@ discard """ line: 8 - errormsg: "public implementation 'tmismatchedvisibility.foo(a: int)' has non-public forward declaration in " + errormsg: "public implementation 'tmismatchedvisibility.foo(a: int)[declared in tmismatchedvisibility.nim(6,5)]' has non-public forward declaration in " """ proc foo(a: int): int diff --git a/tests/pragmas/tused.nim b/tests/pragmas/tused.nim index 4a317f874..389863aef 100644 --- a/tests/pragmas/tused.nim +++ b/tests/pragmas/tused.nim @@ -1,7 +1,7 @@ discard """ nimout: ''' compile start -tused.nim(15, 8) Hint: 'tused.echoSub(a: int, b: int)' is declared but not used [XDeclaredButNotUsed] +tused.nim(15, 8) Hint: 'tused.echoSub(a: int, b: int)[declared in tused.nim(15,7)]' is declared but not used [XDeclaredButNotUsed] compile end''' output: "8\n8" """ From 72115c2b0996cd7b33ed0f161d4d1a997caaf1db Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 9 Jun 2017 13:39:42 +0200 Subject: [PATCH 09/11] fixes #5969 --- lib/pure/hashes.nim | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index e8c8776c6..b015ed311 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -139,9 +139,14 @@ proc hash*(x: cstring): Hash = ## efficient hashing of null-terminated strings var h: Hash = 0 var i = 0 - while x[i] != 0.char: - h = h !& ord(x[i]) - inc i + when defined(js): + while i < x.len: + h = h !& ord(x[i]) + inc i + else: + while x[i] != 0.char: + h = h !& ord(x[i]) + inc i result = !$h proc hash*(sBuf: string, sPos, ePos: int): Hash = From 0f3e1f17e99fcebdf77fdc837b96c9810b1910bc Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 9 Jun 2017 14:14:47 +0200 Subject: [PATCH 10/11] fixes #5959 --- compiler/sempass2.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 96bdc6cba..c383f352f 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -218,12 +218,11 @@ proc listGcUnsafety(s: PSym; onlyWarning: bool; cycleCheck: var IntSet) = message(s.info, msgKind, "'$#' is not GC-safe as it calls '$#'" % [s.name.s, u.name.s]) - of skParam: + of skParam, skForVar: message(s.info, msgKind, "'$#' is not GC-safe as it performs an indirect call via '$#'" % [s.name.s, u.name.s]) else: - internalAssert u.kind == skUnknown message(u.info, msgKind, "'$#' is not GC-safe as it performs an indirect call here" % s.name.s) From 963679389c6866672b939fcd0bd4c631be81fca7 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Tue, 13 Jun 2017 10:12:23 +0200 Subject: [PATCH 11/11] cgen: #undef some more predefined symbols. (#5831) This is a followup to issue #5171. --- compiler/cgen.nim | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index c67dd6581..3797a92c2 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -601,8 +601,18 @@ proc generateHeaders(m: BModule) = addf(m.s[cfsHeaders], "#include \"$1\"$N", [rope(it)]) else: addf(m.s[cfsHeaders], "#include $1$N", [rope(it)]) + add(m.s[cfsHeaders], "#undef LANGUAGE_C" & tnl) + add(m.s[cfsHeaders], "#undef MIPSEB" & tnl) + add(m.s[cfsHeaders], "#undef MIPSEL" & tnl) + add(m.s[cfsHeaders], "#undef PPC" & tnl) + add(m.s[cfsHeaders], "#undef R3000" & tnl) + add(m.s[cfsHeaders], "#undef R4000" & tnl) + add(m.s[cfsHeaders], "#undef i386" & tnl) add(m.s[cfsHeaders], "#undef linux" & tnl) + add(m.s[cfsHeaders], "#undef mips" & tnl) add(m.s[cfsHeaders], "#undef near" & tnl) + add(m.s[cfsHeaders], "#undef powerpc" & tnl) + add(m.s[cfsHeaders], "#undef unix" & tnl) proc initFrame(p: BProc, procname, filename: Rope): Rope = discard cgsym(p.module, "nimFrame")