fixes #4579
This commit is contained in:
parent
55e86184a5
commit
f439a2f25f
2 changed files with 48 additions and 33 deletions
|
|
@ -90,43 +90,38 @@ proc pragmaAsm*(c: PContext, n: PNode): char =
|
||||||
else:
|
else:
|
||||||
invalidPragma(it)
|
invalidPragma(it)
|
||||||
|
|
||||||
proc setExternName(s: PSym, extname: string) =
|
proc setExternName(s: PSym, extname: string, info: TLineInfo) =
|
||||||
s.loc.r = rope(extname % s.name.s)
|
# special cases to improve performance:
|
||||||
|
if extname == "$1":
|
||||||
|
s.loc.r = rope(s.name.s)
|
||||||
|
elif '$' notin extname:
|
||||||
|
s.loc.r = rope(extname)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
s.loc.r = rope(extname % s.name.s)
|
||||||
|
except ValueError:
|
||||||
|
localError(info, "invalid extern name: '" & extname & "'. (Forgot to escape '$'?)")
|
||||||
if gCmd == cmdPretty and '$' notin extname:
|
if gCmd == cmdPretty and '$' notin extname:
|
||||||
# note that '{.importc.}' is transformed into '{.importc: "$1".}'
|
# note that '{.importc.}' is transformed into '{.importc: "$1".}'
|
||||||
s.loc.flags.incl(lfFullExternalName)
|
s.loc.flags.incl(lfFullExternalName)
|
||||||
|
|
||||||
proc makeExternImport(s: PSym, extname: string) =
|
proc makeExternImport(s: PSym, extname: string, info: TLineInfo) =
|
||||||
setExternName(s, extname)
|
setExternName(s, extname, info)
|
||||||
incl(s.flags, sfImportc)
|
incl(s.flags, sfImportc)
|
||||||
excl(s.flags, sfForward)
|
excl(s.flags, sfForward)
|
||||||
|
|
||||||
proc validateExternCName(s: PSym, info: TLineInfo) =
|
|
||||||
## Validates that the symbol name in s.loc.r is a valid C identifier.
|
|
||||||
##
|
|
||||||
## Valid identifiers are those alphanumeric including the underscore not
|
|
||||||
## starting with a number. If the check fails, a generic error will be
|
|
||||||
## displayed to the user.
|
|
||||||
let target = $s.loc.r
|
|
||||||
if target.len < 1 or target[0] notin IdentStartChars or
|
|
||||||
not target.allCharsInSet(IdentChars):
|
|
||||||
localError(info, errGenerated, "invalid exported symbol")
|
|
||||||
|
|
||||||
proc makeExternExport(s: PSym, extname: string, info: TLineInfo) =
|
proc makeExternExport(s: PSym, extname: string, info: TLineInfo) =
|
||||||
setExternName(s, extname)
|
setExternName(s, extname, info)
|
||||||
# XXX to fix make it work with nimrtl.
|
|
||||||
#if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC}:
|
|
||||||
# validateExternCName(s, info)
|
|
||||||
incl(s.flags, sfExportc)
|
incl(s.flags, sfExportc)
|
||||||
|
|
||||||
proc processImportCompilerProc(s: PSym, extname: string) =
|
proc processImportCompilerProc(s: PSym, extname: string, info: TLineInfo) =
|
||||||
setExternName(s, extname)
|
setExternName(s, extname, info)
|
||||||
incl(s.flags, sfImportc)
|
incl(s.flags, sfImportc)
|
||||||
excl(s.flags, sfForward)
|
excl(s.flags, sfForward)
|
||||||
incl(s.loc.flags, lfImportCompilerProc)
|
incl(s.loc.flags, lfImportCompilerProc)
|
||||||
|
|
||||||
proc processImportCpp(s: PSym, extname: string) =
|
proc processImportCpp(s: PSym, extname: string, info: TLineInfo) =
|
||||||
setExternName(s, extname)
|
setExternName(s, extname, info)
|
||||||
incl(s.flags, sfImportc)
|
incl(s.flags, sfImportc)
|
||||||
incl(s.flags, sfInfixCall)
|
incl(s.flags, sfInfixCall)
|
||||||
excl(s.flags, sfForward)
|
excl(s.flags, sfForward)
|
||||||
|
|
@ -134,8 +129,8 @@ proc processImportCpp(s: PSym, extname: string) =
|
||||||
incl(m.flags, sfCompileToCpp)
|
incl(m.flags, sfCompileToCpp)
|
||||||
extccomp.gMixedMode = true
|
extccomp.gMixedMode = true
|
||||||
|
|
||||||
proc processImportObjC(s: PSym, extname: string) =
|
proc processImportObjC(s: PSym, extname: string, info: TLineInfo) =
|
||||||
setExternName(s, extname)
|
setExternName(s, extname, info)
|
||||||
incl(s.flags, sfImportc)
|
incl(s.flags, sfImportc)
|
||||||
incl(s.flags, sfNamedParamCall)
|
incl(s.flags, sfNamedParamCall)
|
||||||
excl(s.flags, sfForward)
|
excl(s.flags, sfForward)
|
||||||
|
|
@ -623,10 +618,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||||
of wExportc:
|
of wExportc:
|
||||||
makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
|
makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||||
of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"))
|
of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||||
of wImportCompilerProc:
|
of wImportCompilerProc:
|
||||||
processImportCompilerProc(sym, getOptionalStr(c, it, "$1"))
|
processImportCompilerProc(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||||
of wExtern: setExternName(sym, expectStrLit(c, it))
|
of wExtern: setExternName(sym, expectStrLit(c, it), it.info)
|
||||||
of wImmediate:
|
of wImmediate:
|
||||||
if sym.kind in {skTemplate, skMacro}:
|
if sym.kind in {skTemplate, skMacro}:
|
||||||
incl(sym.flags, sfImmediate)
|
incl(sym.flags, sfImmediate)
|
||||||
|
|
@ -637,9 +632,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||||
if sym.kind == skTemplate: incl(sym.flags, sfDirty)
|
if sym.kind == skTemplate: incl(sym.flags, sfDirty)
|
||||||
else: invalidPragma(it)
|
else: invalidPragma(it)
|
||||||
of wImportCpp:
|
of wImportCpp:
|
||||||
processImportCpp(sym, getOptionalStr(c, it, "$1"))
|
processImportCpp(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||||
of wImportObjC:
|
of wImportObjC:
|
||||||
processImportObjC(sym, getOptionalStr(c, it, "$1"))
|
processImportObjC(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||||
of wAlign:
|
of wAlign:
|
||||||
if sym.typ == nil: invalidPragma(it)
|
if sym.typ == nil: invalidPragma(it)
|
||||||
var align = expectIntLit(c, it)
|
var align = expectIntLit(c, it)
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,20 @@ spelled*:
|
||||||
.. code-block::
|
.. code-block::
|
||||||
proc printf(formatstr: cstring) {.header: "<stdio.h>", importc: "printf", varargs.}
|
proc printf(formatstr: cstring) {.header: "<stdio.h>", importc: "printf", varargs.}
|
||||||
|
|
||||||
Note that this pragma is somewhat of a misnomer: Other backends will provide
|
Note that this pragma is somewhat of a misnomer: Other backends do provide
|
||||||
the same feature under the same name. Also, if one is interfacing with C++
|
the same feature under the same name. Also, if one is interfacing with C++
|
||||||
the `ImportCpp pragma <manual.html#implementation-specific-pragmas-importcpp-pragma>`_ and
|
the `ImportCpp pragma <manual.html#implementation-specific-pragmas-importcpp-pragma>`_ and
|
||||||
interfacing with Objective-C the `ImportObjC pragma
|
interfacing with Objective-C the `ImportObjC pragma
|
||||||
<manual.html#implementation-specific-pragmas-importobjc-pragma>`_ can be used.
|
<manual.html#implementation-specific-pragmas-importobjc-pragma>`_ can be used.
|
||||||
|
|
||||||
|
The string literal passed to ``importc`` can be a format string:
|
||||||
|
|
||||||
|
.. code-block:: Nim
|
||||||
|
proc p(s: cstring) {.importc: "prefix$1".}
|
||||||
|
|
||||||
|
In the example the external name of ``p`` is set to ``prefixp``. Only ``$1``
|
||||||
|
is available and a literal dollar sign must be written as ``$$``.
|
||||||
|
|
||||||
|
|
||||||
Exportc pragma
|
Exportc pragma
|
||||||
--------------
|
--------------
|
||||||
|
|
@ -33,9 +41,19 @@ name is the Nim identifier *exactly as spelled*:
|
||||||
.. code-block:: Nim
|
.. code-block:: Nim
|
||||||
proc callme(formatstr: cstring) {.exportc: "callMe", varargs.}
|
proc callme(formatstr: cstring) {.exportc: "callMe", varargs.}
|
||||||
|
|
||||||
Note that this pragma is somewhat of a misnomer: Other backends will provide
|
Note that this pragma is somewhat of a misnomer: Other backends do provide
|
||||||
the same feature under the same name.
|
the same feature under the same name.
|
||||||
|
|
||||||
|
The string literal passed to ``exportc`` can be a format string:
|
||||||
|
|
||||||
|
.. code-block:: Nim
|
||||||
|
proc p(s: string) {.exportc: "prefix$1".} =
|
||||||
|
echo s
|
||||||
|
|
||||||
|
In the example the external name of ``p`` is set to ``prefixp``. Only ``$1``
|
||||||
|
is available and a literal dollar sign must be written as ``$$``.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Extern pragma
|
Extern pragma
|
||||||
-------------
|
-------------
|
||||||
|
|
@ -46,7 +64,9 @@ mangling. The string literal passed to ``extern`` can be a format string:
|
||||||
proc p(s: string) {.extern: "prefix$1".} =
|
proc p(s: string) {.extern: "prefix$1".} =
|
||||||
echo s
|
echo s
|
||||||
|
|
||||||
In the example the external name of ``p`` is set to ``prefixp``.
|
In the example the external name of ``p`` is set to ``prefixp``. Only ``$1``
|
||||||
|
is available and a literal dollar sign must be written as ``$$``.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Bycopy pragma
|
Bycopy pragma
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue