diff --git a/.gitignore b/.gitignore index 91c4083..7de0db5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ nimcache testsuite/tests/*.nim testsuite/cppkeepbodies/*.nim +testsuite/cextras/*.nim testsuite/tester *.exe /c2nim diff --git a/c2nim.nim b/c2nim.nim index 87296b5..65a4af9 100644 --- a/c2nim.nim +++ b/c2nim.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -import std / [strutils, os, times, parseopt, strscans] +import std / [strutils, os, times, md5, parseopt, strscans] import compiler/ [llstream, ast, renderer, options, msgs, nversion] @@ -43,6 +43,10 @@ Options: --importc annotate procs with ``{.importc.}`` --importdefines import C defines as procs or vars with ``{.importc.}`` --importfuncdefines import C define funcs as procs with ``{.importc.}`` + --def:SYM='macro()' define a C macro that gets replaced with the given + definition. It's parsed by the lexer. Use it to fix + function attributes: ``--def:PUBLIC='__attribute__ ()'`` + --reordercomments reorder C comments to match Nim's postfix style --ref convert typ* to ref typ (default: ptr typ) --prefix:PREFIX strip prefix for the generated Nim identifiers (multiple --prefix options are supported) @@ -52,6 +56,7 @@ Options: for example `--mangle:'{u?}int{\d+}_t=$1int$2'` to convert C to Nim equivalents (multiple --mangle options are supported) + --stdints Mangle C stdint's into Nim style int's --paramprefix:PREFIX add prefix to parameter name of the generated Nim proc --assumedef:IDENT skips #ifndef sections for the given C identifier (multiple --assumedef options are supported) @@ -87,7 +92,10 @@ proc parse(infile: string, options: PParserOptions; dllExport: var PNode): PNode var p: Parser if isCpp: options.flags.incl pfCpp openParser(p, infile, stream, options) - result = parseUnit(p).postprocess(pfStructStruct in options.flags) + result = parseUnit(p).postprocess( + structStructMode = pfStructStruct in options.flags, + reorderComments = pfReorderComments in options.flags + ) closeParser(p) if isCpp: options.flags.excl pfCpp if options.exportPrefix.len > 0: @@ -100,18 +108,52 @@ proc parse(infile: string, options: PParserOptions; dllExport: var PNode): PNode proc isC2nimFile(s: string): bool = splitFile(s).ext.toLowerAscii == ".c2nim" +proc parseDefines(val: string): seq[ref Token] = + let tpath = getTempDir() / "macro_" & getMD5(val) & ".h" + let tfl = (open(tpath, fmReadWrite), tpath) + let ss = llStreamOpen(val) + var lex: Lexer + openLexer(lex, tfl[1], ss) + var tk = new Token + var idx = 0 + result = newSeq[ref Token]() + while tk.xkind != pxEof: + tk = new Token + lex.getTok(tk[]) + if tk.xkind == pxEof: + break + result.add tk + inc idx + if idx > 1_000: raise newException(Exception, "parse error") + tfl[0].close() + tfl[1].removeFile() + +proc parseDefineArgs(parserOptions: var PParserOptions, val: string) = + let defs = val.split("=") + var mc: cparser.Macro + let macs = parseDefines(defs[0]) + let toks = parseDefines(defs[1]) + mc.name = macs[0].s + mc.params = -1 + mc.body = toks + for m in macs[1..^1]: + if m.xkind == pxParLe: mc.params = 0 + if m.xkind == pxSymbol: inc mc.params + parserOptions.macros.add(mc) + + var dummy: PNode when not compiles(renderModule(dummy, "")): # newer versions of 'renderModule' take 2 parameters. We workaround this # problem here: - proc renderModule(tree: PNode; filename: string) = - renderModule(tree, filename, filename) + proc renderModule(tree: PNode; filename: string, renderFlags: TRenderFlags) = + renderModule(tree, filename, filename, renderFlags) -proc myRenderModule(tree: PNode; filename: string) = +proc myRenderModule(tree: PNode; filename: string, renderFlags: TRenderFlags) = # also ensure we produced no trailing whitespace: let tmpFile = filename & ".tmp" - renderModule(tree, tmpFile) + renderModule(tree, tmpFile, renderFlags) let b = readFile(tmpFile) removeFile(tmpFile) @@ -149,21 +191,21 @@ proc main(infiles: seq[string], outfile: var string, if not isC2nimFile(infile): if outfile.len == 0: outfile = changeFileExt(infile, "nim") for n in m: tree.add(n) - myRenderModule(tree, outfile) + myRenderModule(tree, outfile, options.renderFlags) else: for infile in infiles: let m = parse(infile, options, dllexport) if not isC2nimFile(infile): if outfile.len > 0: - myRenderModule(m, outfile) + myRenderModule(m, outfile, options.renderFlags) outfile = "" else: let outfile = changeFileExt(infile, "nim") - myRenderModule(m, outfile) + myRenderModule(m, outfile, options.renderFlags) if dllexport != nil: let (path, name, _) = infiles[0].splitFile let outfile = path / name & "_dllimpl" & ".nim" - myRenderModule(dllexport, outfile) + myRenderModule(dllexport, outfile, options.renderFlags) when declared(NimCompilerApiVersion): rawMessage(gConfig, hintSuccessX, [$gLinesCompiled, $(getTime() - start), formatSize(getTotalMem()), ""]) @@ -195,8 +237,13 @@ for kind, key, val in getopt(): " use a list of files and --concat instead" of "exportdll": parserOptions.exportPrefix = val + of "def": + parserOptions.parseDefineArgs(val) else: - if not parserOptions.setOption(key, val): + if key.normalize == "render": + if not parserOptions.renderFlags.setOption(val): + quit("[Error] unknown option: " & key) + elif not parserOptions.setOption(key, val): quit("[Error] unknown option: " & key) of cmdEnd: assert(false) if infiles.len == 0: diff --git a/clexer.nim b/clexer.nim index 8151ecd..6c9178a 100644 --- a/clexer.nim +++ b/clexer.nim @@ -107,6 +107,7 @@ type base*: NumericalBase # the numerical base; only valid for int # or float literals next*: ref Token # for C we need arbitrary look-ahead :-( + lineNumber*: int # line number Lexer* = object of TBaseLexer fileIdx*: (when declared(FileIndex): FileIndex else: int32) @@ -578,8 +579,10 @@ proc scanLineComment(L: var Lexer, tok: var Token) = tok.xkind = pxLineComment var col = getColNumber(L, pos) while true: - inc(pos, 2) # skip // - #add(tok.s, '#') + # FIXME: this should be inc(pos, 3) to not double count space? + inc(pos, 2) # skip // + if buf[pos] == '/': + inc(pos, 1) # skip /// while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}: add(tok.s, buf[pos]) inc(pos) @@ -601,6 +604,9 @@ proc scanStarComment(L: var Lexer, tok: var Token) = var buf = L.buf tok.s = "" tok.xkind = pxStarComment + # skip initial /** + if buf[pos] == '*' and buf[pos] != '/': + inc(pos) while true: case buf[pos] of CR, LF: @@ -613,7 +619,6 @@ proc scanStarComment(L: var Lexer, tok: var Token) = # */ let oldPos = pos while buf[pos] in {' ', '\t'}: - #add(tok.s, ' ') inc(pos) if buf[pos] == '*': if buf[pos+1] != '/': @@ -750,6 +755,7 @@ proc getTok*(L: var Lexer, tok: var Token) = skip(L, tok) if tok.xkind == pxNewLine: return var c = L.buf[L.bufpos] + tok.lineNumber = L.lineNumber if c in SymStartChars: getSymbol(L, tok) if L.buf[L.bufpos] == '"': diff --git a/compiler/renderer.nim b/compiler/renderer.nim index af5f55d..c5dc7c2 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -15,7 +15,7 @@ import type TRenderFlag* = enum renderNone, renderNoBody, renderNoComments, renderDocComments, - renderNoPragmas, renderIds, renderNoProcDefs, renderSyms + renderNoPragmas, renderIds, renderNoProcDefs, renderSyms, renderExtraNewLines TRenderFlags* = set[TRenderFlag] TRenderTok* = object kind*: TTokType @@ -43,6 +43,12 @@ type fid*: FileIndex config*: ConfigRef +proc setOption*(renderOptions: var TRenderFlags, val: string): bool = + result = true + case val.normalize + of "extranewlines": incl(renderOptions, renderExtraNewLines) + else: result = false + # We render the source code in a two phases: The first # determines how long the subtree will likely be, the second # phase appends to a buffer that will be the output. @@ -1281,6 +1287,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = of nkStaticStmt: gstaticStmt(g, n) of nkAsmStmt: gasm(g, n) of nkProcDef: + if renderExtraNewLines in g.flags: putNL(g) if renderNoProcDefs notin g.flags: putWithSpace(g, tkProc, "proc") gproc(g, n) of nkFuncDef: diff --git a/cparser.nim b/cparser.nim index e57c0d3..143c7ed 100644 --- a/cparser.nim +++ b/cparser.nim @@ -46,21 +46,23 @@ type pfIgnoreRValueRefs, ## transform C++'s 'T&&' to 'T' pfKeepBodies, ## do not skip C++ method bodies pfAssumeIfIsTrue, ## assume #if is true - pfStructStruct ## do not treat struct Foo Foo as a forward decl + pfStructStruct, ## do not treat struct Foo Foo as a forward decl + pfReorderComments ## do not treat struct Foo Foo as a forward decl - Macro = object - name: string - params: int # number of parameters; 0 for empty (); -1 for no () at all - body: seq[ref Token] # can contain pxMacroParam tokens + Macro* = object + name*: string + params*: int # number of parameters; 0 for empty (); -1 for no () at all + body*: seq[ref Token] # can contain pxMacroParam tokens ParserOptions = object ## shared parser state! flags*: set[ParserFlag] + renderFlags*: TRenderFlags prefixes, suffixes: seq[string] assumeDef, assumenDef: seq[string] mangleRules: seq[tuple[pattern: Peg, frmt: string]] privateRules: seq[Peg] dynlibSym, headerOverride: string - macros: seq[Macro] + macros*: seq[Macro] toMangle: StringTableRef classes: StringTableRef toPreprocess: StringTableRef @@ -127,6 +129,7 @@ proc newParserOptions*(): PParserOptions = privateRules: @[], discardablePrefixes: @[], flags: {}, + renderFlags: {}, dynlibSym: "", headerOverride: "", toMangle: newStringTable(modeCaseSensitive), @@ -166,6 +169,9 @@ proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool = of "mangle": let vals = val.split("=") parserOptions.mangleRules.add((parsePeg(vals[0]), vals[1])) + of "stdints": + let vals = (r"{u?}int{\d+}_t", r"$1int$2") + parserOptions.mangleRules.add((parsePeg(vals[0]), vals[1])) of "skipinclude": incl(parserOptions.flags, pfSkipInclude) of "typeprefixes": incl(parserOptions.flags, pfTypePrefixes) of "skipcomments": incl(parserOptions.flags, pfSkipComments) @@ -182,6 +188,7 @@ proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool = of "assumeifistrue": incl(parserOptions.flags, pfAssumeIfIsTrue) of "discardableprefix": parserOptions.discardablePrefixes.add(val) of "structstruct": incl(parserOptions.flags, pfStructStruct) + of "reordercomments": incl(parserOptions.flags, pfReorderComments) of "isarray": parserOptions.isArray[val] = "true" else: result = false @@ -202,6 +209,7 @@ proc parMessage(p: Parser, msg: TMsgKind, arg = "") = lexMessage(p.lex, msg, arg) proc parError(p: Parser, arg = "") = + # raise newException(Exception, arg) if p.backtrackB.len == 0: lexMessage(p.lex, errGenerated, arg) else: @@ -249,7 +257,8 @@ proc findMacro(p: Parser): int = proc rawEat(p: var Parser, xkind: Tokkind) = if p.tok.xkind == xkind: rawGetTok(p) - else: parError(p, "token expected: " & tokKindToStr(xkind)) + else: + parError(p, "token expected: " & tokKindToStr(xkind)) proc parseMacroArguments(p: var Parser): seq[seq[ref Token]] = result = @[] @@ -354,6 +363,7 @@ proc skipComAux(p: var Parser, n: PNode) = if pfSkipComments notin p.options.flags: if n.comment.len == 0: n.comment = p.tok.s else: add(n.comment, "\n" & p.tok.s) + n.info.line = p.tok.lineNumber.uint16 else: parMessage(p, warnCommentXIgnored, p.tok.s) getTok(p) @@ -370,6 +380,7 @@ proc getTok(p: var Parser, n: PNode) = proc expectIdent(p: Parser) = if p.tok.xkind != pxSymbol: + # raise newException(Exception, "error") parError(p, "identifier expected, but got: " & debugTok(p.lex, p.tok[])) proc eat(p: var Parser, xkind: Tokkind, n: PNode) = @@ -397,7 +408,9 @@ proc addSon(father, a, b, c: PNode) = addSon(father, c) proc newNodeP(kind: TNodeKind, p: Parser): PNode = - result = newNodeI(kind, getLineInfo(p.lex)) + var info = getLineInfo(p.lex) + info.line = p.tok.lineNumber.uint16 + result = newNodeI(kind, info) proc newNumberNodeP(kind: TNodeKind, number: string, p: Parser): PNode = result = newNodeP(kind, p) @@ -487,7 +500,7 @@ proc declKeyword(p: Parser, s: string): bool = "restrict", "inline", "__inline", "__cdecl", "__stdcall", "__syscall", "__fastcall", "__safecall", "void", "struct", "union", "enum", "typedef", "size_t", "short", "int", "long", "float", "double", "signed", "unsigned", - "char", "__declspec": + "char", "__declspec", "__attribute__": result = true of "class", "mutable", "constexpr", "consteval", "constinit", "decltype": result = p.options.flags.contains(pfCpp) @@ -928,11 +941,23 @@ proc parseBitfield(p: var Parser, i: PNode): PNode = else: result = i +import compiler/nimlexbase + proc parseStructBody(p: var Parser, stmtList: PNode, kind: TNodeKind = nkRecList): PNode = result = newNodeP(kind, p) - eat(p, pxCurlyLe, result) + let com = newNodeP(nkCommentStmt, p) + eat(p, pxCurlyLe, com) + if com.comment.len() > 0: + addSon(result, com) while p.tok.xkind notin {pxEof, pxCurlyRi}: + let ln = p.parLineInfo().line + if p.tok.xkind in {pxLineComment, pxStarComment}: + let com = newNodeP(nkCommentStmt, p) + com.info.line = p.tok.lineNumber.uint16 + addSon(result, com) + skipComAux(p, com) + continue discard skipConst(p) var baseTyp: PNode if p.tok.xkind == pxSymbol and p.tok.s in ["struct", "union"]: @@ -982,7 +1007,9 @@ proc parseStructBody(p: var Parser, stmtList: PNode, addSon(result, def) if p.tok.xkind != pxComma: break getTok(p, def) - eat(p, pxSemicolon, lastSon(result)) + + eat(p, pxSemicolon) + eat(p, pxCurlyRi, result) proc enumPragmas(p: Parser, name: PNode; origName: string): PNode = @@ -1135,6 +1162,10 @@ proc parseCallConv(p: var Parser, pragmas: PNode) = getTok(p, nil) eat(p, pxParLe, nil) while p.tok.xkind notin {pxEof, pxParRi}: getTok(p, nil) + of "__attribute__": + getTok(p, nil) + eat(p, pxParLe, nil) + while p.tok.xkind notin {pxEof, pxParRi}: getTok(p, nil) else: break getTok(p, nil) diff --git a/postprocessor.nim b/postprocessor.nim index fb6f5a0..464315c 100644 --- a/postprocessor.nim +++ b/postprocessor.nim @@ -28,6 +28,7 @@ type Context = object typedefs: Table[string, PNode] structStructMode: bool + reorderComments: bool proc getName(n: PNode): PNode = result = n @@ -113,7 +114,45 @@ proc patchBracket(c: Context; t: PNode; n: var PNode) = if success: n = nn + +import sequtils + +var depth = 0 + +proc reorderComments(n: PNode) = + ## reorder C style comments to Nim style ones + var j = 1 + let commentKinds = {nkTypeSection, nkIdentDefs, nkProcDef, nkConstSection} + template moveComment(idx, off) = + if n[idx+off].len >= 0: + n[idx+off][0].comment = n[idx].comment + delete(n.sons, idx) + + while j < n.safeLen - 1: + if n[j].kind == nkCommentStmt: + # join comments to previous node if line numbers match + if n[j-1].kind in commentKinds: + if n[j-1].info.line == n[j].info.line: + moveComment(j, -1) + inc j + var i = 0 + while i < n.safeLen - 1: + if n[i].kind == nkCommentStmt: + # reorder comments to match Nim ordering + if n[i+1].kind in commentKinds: + moveComment(i, +1) + inc i + proc pp(c: var Context; n: var PNode, stmtList: PNode = nil, idx: int = -1) = + + if c.reorderComments: + reorderComments(n) + + # var s = "" + # inc depth + # for i in 0..depth: s &= " " + # echo s, "PP: ", n.kind, " idx: ", idx, " ln: ", n.info.line, " comment: `", n.comment[0.. + * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] argc The number of arguments in argv. + * \param[in] argv The values of the arguments. + * \param[in] allocator A valid allocator. + * \param[out] args_output A structure that will contain the result of parsing. + * Must be zero initialized before use. + * \return #RCL_RET_OK if the arguments were parsed successfully, or + * \return #RCL_RET_INVALID_ROS_ARGS if an invalid ROS argument is found, or + * \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + * \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + * \return #RCL_RET_ERROR if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_parse_arguments( + int argc, + const char * const * argv, + rcl_allocator_t allocator, + rcl_arguments_t * args_output); + +/// Return the number of arguments that were not ROS specific arguments. +/** + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] args An arguments structure that has been parsed. + * \return number of unparsed arguments, or + * \return -1 if args is `NULL` or zero initialized. + */ +RCL_ALIGNAS(8) +RCL_WARN_UNUSED +int +rcl_arguments_get_count_unparsed( + const rcl_arguments_t * args); + +/// Return a list of indices to non ROS specific arguments. +/** + * Non ROS specific arguments may have been provided i.e. arguments outside a '--ros-args' scope. + * This function populates an array of indices to these arguments in the original argv array. + * Since the first argument is always assumed to be a process name, the list will always contain + * the index 0. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] args An arguments structure that has been parsed. + * \param[in] allocator A valid allocator. + * \param[out] output_unparsed_indices An allocated array of indices into the original argv array. + * This array must be deallocated by the caller using the given allocator. + * If there are no unparsed args then the output will be set to NULL. + * \return #RCL_RET_OK if everything goes correctly, or + * \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + * \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + * \return #RCL_RET_ERROR if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_arguments_get_unparsed( + const rcl_arguments_t * args, + rcl_allocator_t allocator, + int ** output_unparsed_indices); + +/// Return the number of ROS specific arguments that were not successfully parsed. +/** + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] args An arguments structure that has been parsed. + * \return number of unparsed ROS specific arguments, or + * \return -1 if args is `NULL` or zero initialized. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +int +rcl_arguments_get_count_unparsed_ros( + const rcl_arguments_t * args); + +/// Return a list of indices to unknown ROS specific arguments that were left unparsed. +/** + * Some ROS specific arguments may not have been recognized, or were not intended to be + * parsed by rcl. + * This function populates an array of indices to these arguments in the original argv array. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] args An arguments structure that has been parsed. + * \param[in] allocator A valid allocator. + * \param[out] output_unparsed_ros_indices An allocated array of indices into the original argv array. + * This array must be deallocated by the caller using the given allocator. + * If there are no unparsed ROS specific arguments then the output will be set to NULL. + * \return #RCL_RET_OK if everything goes correctly, or + * \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + * \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + * \return #RCL_RET_ERROR if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_arguments_get_unparsed_ros( + const rcl_arguments_t * args, + rcl_allocator_t allocator, + int ** output_unparsed_ros_indices); + +/// Return the number of parameter yaml files given in the arguments. +/** + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] args An arguments structure that has been parsed. + * \return number of yaml files, or + * \return -1 if args is `NULL` or zero initialized. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +int +rcl_arguments_get_param_files_count( + const rcl_arguments_t * args); + + +/// Return a list of yaml parameter file paths specified on the command line. +/** + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] arguments An arguments structure that has been parsed. + * \param[in] allocator A valid allocator. + * \param[out] parameter_files An allocated array of paramter file names. + * This array must be deallocated by the caller using the given allocator. + * The output is NULL if there were no paramter files. + * \return #RCL_RET_OK if everything goes correctly, or + * \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + * \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + * \return #RCL_RET_ERROR if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_arguments_get_param_files( + const rcl_arguments_t * arguments, + rcl_allocator_t allocator, + char *** parameter_files); + +/// Return all parameter overrides parsed from the command line. +/** + * Parameter overrides are parsed directly from command line arguments and + * parameter files provided in the command line. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] arguments An arguments structure that has been parsed. + * \param[out] parameter_overrides Parameter overrides as parsed from command line arguments. + * This structure must be finalized by the caller. + * The output is NULL if no parameter overrides were parsed. + * \return #RCL_RET_OK if everything goes correctly, or + * \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + * \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + * \return #RCL_RET_ERROR if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_arguments_get_param_overrides( + const rcl_arguments_t * arguments, + rcl_params_t ** parameter_overrides); + +/// Return a list of arguments with ROS-specific arguments removed. +/** + * Some arguments may not have been intended as ROS arguments. + * This function populates an array of the aruments in a new argv array. + * Since the first argument is always assumed to be a process name, the list + * will always contain the first value from the argument vector. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] argv The argument vector + * \param[in] args An arguments structure that has been parsed. + * \param[in] allocator A valid allocator. + * \param[out] nonros_argc The count of arguments that aren't ROS-specific + * \param[out] nonros_argv An allocated array of arguments that aren't ROS-specific + * This array must be deallocated by the caller using the given allocator. + * If there are no non-ROS args, then the output will be set to NULL. + * \return #RCL_RET_OK if everything goes correctly, or + * \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + * \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + * \return #RCL_RET_ERROR if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_remove_ros_arguments( + const char * const * argv, + const rcl_arguments_t * args, + rcl_allocator_t allocator, + int * nonros_argc, + const char *** nonros_argv); + +/// Return log levels parsed from the command line. +/** + * Log levels are parsed directly from command line arguments. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] arguments An arguments structure that has been parsed. + * \param[out] log_levels Log levels as parsed from command line arguments. + * The output must be finished by the caller if the function successes. + * \return #RCL_RET_OK if everything goes correctly, or + * \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + * \return #RCL_RET_BAD_ALLOC if allocating memory failed. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_arguments_get_log_levels( + const rcl_arguments_t * arguments, + rcl_log_levels_t * log_levels); + +/// Copy one arguments structure into another. +/** + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] args The structure to be copied. + * Its allocator is used to copy memory into the new structure. + * \param[out] args_out A zero-initialized arguments structure to be copied into. + * \return #RCL_RET_OK if the structure was copied successfully, or + * \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + * \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + * \return #RCL_RET_ERROR if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_arguments_copy( + const rcl_arguments_t * args, + rcl_arguments_t * args_out); + +/// Reclaim resources held inside rcl_arguments_t structure. +/** + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] args The structure to be deallocated. + * \return #RCL_RET_OK if the memory was successfully freed, or + * \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + * \return #RCL_RET_ERROR if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_arguments_fini( + rcl_arguments_t * args); + +#ifdef __cplusplus +} +#endif + +#endif // RCL__ARGUMENTS_H_ diff --git a/testsuite/results/matrix.nim b/testsuite/results/matrix.nim index bf54c53..fa190cc 100644 --- a/testsuite/results/matrix.nim +++ b/testsuite/results/matrix.nim @@ -1,4 +1,4 @@ -## /////////////////////////////////////////////////////////////////////////// +## ////////////////////////////////////////////////////////////////////////// ## Name: wx/matrix.h ## Purpose: wxTransformMatrix class. NOT YET USED ## Author: Chris Breeze, Julian Smart @@ -7,7 +7,7 @@ ## RCS-ID: $Id$ ## Copyright: (c) Julian Smart, Chris Breeze ## Licence: wxWindows licence -## /////////////////////////////////////////////////////////////////////////// +## ////////////////////////////////////////////////////////////////////////// ## ! headerfiles="matrix.h wx/object.h" diff --git a/testsuite/results/rcl_allocator.nim b/testsuite/results/rcl_allocator.nim new file mode 100644 index 0000000..26a719f --- /dev/null +++ b/testsuite/results/rcl_allocator.nim @@ -0,0 +1,35 @@ +type + rcutils_allocator_t* {.importc: "rcutils_allocator_t", header: "rcl_allocator.h", + bycopy.} = object ## + ## The default allocator uses malloc(), free(), calloc(), and realloc(). + ## It can be obtained using rcutils_get_default_allocator(). + ## + ## The allocator should be trivially copyable. + ## Meaning that the struct should continue to work after being assignment + ## copied into a new struct. + ## Specifically the object pointed to by the state pointer should remain valid + ## until all uses of the allocator have been made. + ## Particular care should be taken when giving an allocator to functions like + ## rcutils_*_init() where it is stored within another object and used later. + ## Developers should note that, while the fields of a const-qualified allocator + ## struct cannot be modified, the state of the allocator can be modified. + ## + allocate* {.importc: "allocate".}: proc (size: csize_t; state: pointer): pointer ## allocate: Allocate memory, given a size and the `state` pointer. + deallocate* {.importc: "deallocate".}: proc (pointer: pointer; state: pointer) ## deallocate: Deallocate previously allocated memory, mimicking free(). + ## more lines + reallocate* {.importc: "reallocate".}: proc (pointer: pointer; size: csize_t; + state: pointer): pointer ## reallocate: Also takes the `state` pointer. + zero_allocate* {.importc: "zero_allocate".}: proc (number_of_elements: csize_t; + size_of_element: csize_t; state: pointer): pointer ## zero_allocate: Allocate memory with all elements set to zero, given a number of elements and their size. + reallocate2* {.importc: "reallocate2".}: proc (pointer: pointer; size: csize_t; + state: pointer): pointer ## reallocate2: Also takes the `state` pointer. + state* {.importc: "state".}: pointer ## allocator objects. + + + +proc rcutils_get_zero_initialized_allocator*(): rcutils_allocator_t {. + importc: "rcutils_get_zero_initialized_allocator", header: "rcl_allocator.h".} + ## Return a zero initialized allocator. + ## + ## Note that this is an invalid allocator and should only be used as a placeholder. + ## \ No newline at end of file diff --git a/testsuite/results/rcl_arguments.nim b/testsuite/results/rcl_arguments.nim new file mode 100644 index 0000000..e7ee7f8 --- /dev/null +++ b/testsuite/results/rcl_arguments.nim @@ -0,0 +1,392 @@ +## Copyright 2018 Open Source Robotics Foundation, Inc. +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## @file + +import + rcl/allocator, rcl/log_level, rcl/macros, rcl/types, rcl/visibility_control, + rcl_yaml_param_parser/types + +type + rcl_arguments_impl_t* = rcl_arguments_impl_s + +type + rcl_arguments_t* {.importc: "rcl_arguments_t", header: "rcl_arguments.h", bycopy.} = object ## Hold output of parsing command line arguments. + impl* {.importc: "impl".}: ptr rcl_arguments_impl_t ## Private implementation pointer. + + +const + RCL_ROS_ARGS_FLAG* = "--ros-args" ## The command-line flag that delineates the start of ROS arguments. + +const + RCL_ROS_ARGS_EXPLICIT_END_TOKEN* = "--" ## The token that delineates the explicit end of ROS arguments. + +const + RCL_PARAM_FLAG* = "--param" ## The ROS flag that precedes the setting of a ROS parameter. + +const + RCL_SHORT_PARAM_FLAG* = "-p" ## The short version of the ROS flag that precedes the setting of a ROS parameter. + +const + RCL_PARAM_FILE_FLAG* = "--params-file" ## The ROS flag that precedes a path to a file containing ROS parameters. + +const + RCL_REMAP_FLAG* = "--remap" ## The ROS flag that precedes a ROS remapping rule. + +const + RCL_SHORT_REMAP_FLAG* = "-r" ## The short version of the ROS flag that precedes a ROS remapping rule. + +const + RCL_ENCLAVE_FLAG* = "--enclave" ## The ROS flag that precedes the name of a ROS security enclave. + +const + RCL_SHORT_ENCLAVE_FLAG* = "-e" ## The short version of the ROS flag that precedes the name of a ROS security enclave. + +const + RCL_LOG_LEVEL_FLAG* = "--log-level" ## The ROS flag that precedes the ROS logging level to set. + +const + RCL_EXTERNAL_LOG_CONFIG_FLAG* = "--log-config-file" ## The ROS flag that precedes the name of a configuration file to configure logging. + +const + RCL_LOG_STDOUT_FLAG_SUFFIX* = "stdout-logs" ## The suffix of the ROS flag to enable or disable stdout + ## logging (must be preceded with --enable- or --disable-). + +const + RCL_LOG_ROSOUT_FLAG_SUFFIX* = "rosout-logs" ## The suffix of the ROS flag to enable or disable rosout + ## logging (must be preceded with --enable- or --disable-). + +const + RCL_LOG_EXT_LIB_FLAG_SUFFIX* = "external-lib-logs" ## The suffix of the ROS flag to enable or disable external library + ## logging (must be preceded with --enable- or --disable-). + + +proc rcl_get_zero_initialized_arguments*(): rcl_arguments_t {. + importc: "rcl_get_zero_initialized_arguments", header: "rcl_arguments.h".} + ## Return a rcl_arguments_t struct with members initialized to `NULL`. + +proc rcl_parse_arguments*(argc: cint; argv: cstringArray; allocator: rcl_allocator_t; + args_output: ptr rcl_arguments_t): rcl_ret_t {. + importc: "rcl_parse_arguments", header: "rcl_arguments.h".} + ## Parse command line arguments into a structure usable by code. + ## + ## \sa rcl_get_zero_initialized_arguments() + ## + ## ROS arguments are expected to be scoped by a leading `--ros-args` flag and a trailing double + ## dash token `--` which may be elided if no non-ROS arguments follow after the last `--ros-args`. + ## + ## Remap rule parsing is supported via `-r/--remap` flags e.g. `--remap from:=to` or `-r from:=to`. + ## Successfully parsed remap rules are stored in the order they were given in `argv`. + ## If given arguments `{"__ns:=/foo", "__ns:=/bar"}` then the namespace used by nodes in this + ## process will be `/foo` and not `/bar`. + ## + ## \sa rcl_remap_topic_name() + ## \sa rcl_remap_service_name() + ## \sa rcl_remap_node_name() + ## \sa rcl_remap_node_namespace() + ## + ## Parameter override rule parsing is supported via `-p/--param` flags e.g. `--param name:=value` + ## or `-p name:=value`. + ## + ## The default log level will be parsed as `--log-level level` and logger levels will be parsed as + ## multiple `--log-level name:=level`, where `level` is a name representing one of the log levels + ## in the `RCUTILS_LOG_SEVERITY` enum, e.g. `info`, `debug`, `warn`, not case sensitive. + ## If multiple of these rules are found, the last one parsed will be used. + ## + ## If an argument does not appear to be a valid ROS argument e.g. a `-r/--remap` flag followed by + ## anything but a valid remap rule, parsing will fail immediately. + ## + ## If an argument does not appear to be a known ROS argument, then it is skipped and left unparsed. + ## + ## \sa rcl_arguments_get_count_unparsed_ros() + ## \sa rcl_arguments_get_unparsed_ros() + ## + ## All arguments found outside a `--ros-args ... --` scope are skipped and left unparsed. + ## + ## \sa rcl_arguments_get_count_unparsed() + ## \sa rcl_arguments_get_unparsed() + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | Yes + ## Thread-Safe | Yes + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] argc The number of arguments in argv. + ## \param[in] argv The values of the arguments. + ## \param[in] allocator A valid allocator. + ## \param[out] args_output A structure that will contain the result of parsing. + ## Must be zero initialized before use. + ## \return #RCL_RET_OK if the arguments were parsed successfully, or + ## \return #RCL_RET_INVALID_ROS_ARGS if an invalid ROS argument is found, or + ## \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + ## \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + ## \return #RCL_RET_ERROR if an unspecified error occurs. + ## + +proc rcl_arguments_get_count_unparsed*(args: ptr rcl_arguments_t): cint {. + importc: "rcl_arguments_get_count_unparsed", header: "rcl_arguments.h".} + ## Return the number of arguments that were not ROS specific arguments. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | No + ## Thread-Safe | Yes + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] args An arguments structure that has been parsed. + ## \return number of unparsed arguments, or + ## \return -1 if args is `NULL` or zero initialized. + ## + +proc rcl_arguments_get_unparsed*(args: ptr rcl_arguments_t; + allocator: rcl_allocator_t; + output_unparsed_indices: ptr ptr cint): rcl_ret_t {. + importc: "rcl_arguments_get_unparsed", header: "rcl_arguments.h".} + ## Return a list of indices to non ROS specific arguments. + ## + ## Non ROS specific arguments may have been provided i.e. arguments outside a '--ros-args' scope. + ## This function populates an array of indices to these arguments in the original argv array. + ## Since the first argument is always assumed to be a process name, the list will always contain + ## the index 0. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | Yes + ## Thread-Safe | Yes + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] args An arguments structure that has been parsed. + ## \param[in] allocator A valid allocator. + ## \param[out] output_unparsed_indices An allocated array of indices into the original argv array. + ## This array must be deallocated by the caller using the given allocator. + ## If there are no unparsed args then the output will be set to NULL. + ## \return #RCL_RET_OK if everything goes correctly, or + ## \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + ## \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + ## \return #RCL_RET_ERROR if an unspecified error occurs. + ## + +proc rcl_arguments_get_count_unparsed_ros*(args: ptr rcl_arguments_t): cint {. + importc: "rcl_arguments_get_count_unparsed_ros", header: "rcl_arguments.h".} + ## Return the number of ROS specific arguments that were not successfully parsed. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | No + ## Thread-Safe | Yes + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] args An arguments structure that has been parsed. + ## \return number of unparsed ROS specific arguments, or + ## \return -1 if args is `NULL` or zero initialized. + ## + +proc rcl_arguments_get_unparsed_ros*(args: ptr rcl_arguments_t; + allocator: rcl_allocator_t; + output_unparsed_ros_indices: ptr ptr cint): rcl_ret_t {. + importc: "rcl_arguments_get_unparsed_ros", header: "rcl_arguments.h".} + ## Return a list of indices to unknown ROS specific arguments that were left unparsed. + ## + ## Some ROS specific arguments may not have been recognized, or were not intended to be + ## parsed by rcl. + ## This function populates an array of indices to these arguments in the original argv array. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | Yes + ## Thread-Safe | Yes + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] args An arguments structure that has been parsed. + ## \param[in] allocator A valid allocator. + ## \param[out] output_unparsed_ros_indices An allocated array of indices into the original argv array. + ## This array must be deallocated by the caller using the given allocator. + ## If there are no unparsed ROS specific arguments then the output will be set to NULL. + ## \return #RCL_RET_OK if everything goes correctly, or + ## \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + ## \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + ## \return #RCL_RET_ERROR if an unspecified error occurs. + ## + +proc rcl_arguments_get_param_files_count*(args: ptr rcl_arguments_t): cint {. + importc: "rcl_arguments_get_param_files_count", header: "rcl_arguments.h".} + ## Return the number of parameter yaml files given in the arguments. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | No + ## Thread-Safe | No + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] args An arguments structure that has been parsed. + ## \return number of yaml files, or + ## \return -1 if args is `NULL` or zero initialized. + ## + +proc rcl_arguments_get_param_files*(arguments: ptr rcl_arguments_t; + allocator: rcl_allocator_t; + parameter_files: ptr cstringArray): rcl_ret_t {. + importc: "rcl_arguments_get_param_files", header: "rcl_arguments.h".} + ## Return a list of yaml parameter file paths specified on the command line. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | Yes + ## Thread-Safe | No + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] arguments An arguments structure that has been parsed. + ## \param[in] allocator A valid allocator. + ## \param[out] parameter_files An allocated array of paramter file names. + ## This array must be deallocated by the caller using the given allocator. + ## The output is NULL if there were no paramter files. + ## \return #RCL_RET_OK if everything goes correctly, or + ## \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + ## \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + ## \return #RCL_RET_ERROR if an unspecified error occurs. + ## + +proc rcl_arguments_get_param_overrides*(arguments: ptr rcl_arguments_t; + parameter_overrides: ptr ptr rcl_params_t): rcl_ret_t {. + importc: "rcl_arguments_get_param_overrides", header: "rcl_arguments.h".} + ## Return all parameter overrides parsed from the command line. + ## + ## Parameter overrides are parsed directly from command line arguments and + ## parameter files provided in the command line. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | Yes + ## Thread-Safe | No + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] arguments An arguments structure that has been parsed. + ## \param[out] parameter_overrides Parameter overrides as parsed from command line arguments. + ## This structure must be finalized by the caller. + ## The output is NULL if no parameter overrides were parsed. + ## \return #RCL_RET_OK if everything goes correctly, or + ## \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + ## \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + ## \return #RCL_RET_ERROR if an unspecified error occurs. + ## + +proc rcl_remove_ros_arguments*(argv: cstringArray; args: ptr rcl_arguments_t; + allocator: rcl_allocator_t; nonros_argc: ptr cint; + nonros_argv: ptr cstringArray): rcl_ret_t {. + importc: "rcl_remove_ros_arguments", header: "rcl_arguments.h".} + ## Return a list of arguments with ROS-specific arguments removed. + ## + ## Some arguments may not have been intended as ROS arguments. + ## This function populates an array of the aruments in a new argv array. + ## Since the first argument is always assumed to be a process name, the list + ## will always contain the first value from the argument vector. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | Yes + ## Thread-Safe | Yes + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] argv The argument vector + ## \param[in] args An arguments structure that has been parsed. + ## \param[in] allocator A valid allocator. + ## \param[out] nonros_argc The count of arguments that aren't ROS-specific + ## \param[out] nonros_argv An allocated array of arguments that aren't ROS-specific + ## This array must be deallocated by the caller using the given allocator. + ## If there are no non-ROS args, then the output will be set to NULL. + ## \return #RCL_RET_OK if everything goes correctly, or + ## \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + ## \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + ## \return #RCL_RET_ERROR if an unspecified error occurs. + ## + +proc rcl_arguments_get_log_levels*(arguments: ptr rcl_arguments_t; + log_levels: ptr rcl_log_levels_t): rcl_ret_t {. + importc: "rcl_arguments_get_log_levels", header: "rcl_arguments.h".} + ## Return log levels parsed from the command line. + ## + ## Log levels are parsed directly from command line arguments. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | Yes + ## Thread-Safe | No + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] arguments An arguments structure that has been parsed. + ## \param[out] log_levels Log levels as parsed from command line arguments. + ## The output must be finished by the caller if the function successes. + ## \return #RCL_RET_OK if everything goes correctly, or + ## \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + ## \return #RCL_RET_BAD_ALLOC if allocating memory failed. + ## + +proc rcl_arguments_copy*(args: ptr rcl_arguments_t; args_out: ptr rcl_arguments_t): rcl_ret_t {. + importc: "rcl_arguments_copy", header: "rcl_arguments.h".} + ## Copy one arguments structure into another. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | Yes + ## Thread-Safe | No + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] args The structure to be copied. + ## Its allocator is used to copy memory into the new structure. + ## \param[out] args_out A zero-initialized arguments structure to be copied into. + ## \return #RCL_RET_OK if the structure was copied successfully, or + ## \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + ## \return #RCL_RET_BAD_ALLOC if allocating memory failed, or + ## \return #RCL_RET_ERROR if an unspecified error occurs. + ## + +proc rcl_arguments_fini*(args: ptr rcl_arguments_t): rcl_ret_t {. + importc: "rcl_arguments_fini", header: "rcl_arguments.h".} + ## Reclaim resources held inside rcl_arguments_t structure. + ## + ##
+ ## Attribute | Adherence + ## ------------------ | ------------- + ## Allocates Memory | No + ## Thread-Safe | Yes + ## Uses Atomics | No + ## Lock-Free | Yes + ## + ## \param[in] args The structure to be deallocated. + ## \return #RCL_RET_OK if the memory was successfully freed, or + ## \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or + ## \return #RCL_RET_ERROR if an unspecified error occurs. + ## \ No newline at end of file diff --git a/testsuite/results/smartptrs.nim b/testsuite/results/smartptrs.nim index 496b863..fe4f89a 100644 --- a/testsuite/results/smartptrs.nim +++ b/testsuite/results/smartptrs.nim @@ -23,11 +23,11 @@ import RefCounted -## / Shared pointer template class with intrusive reference counting. +## Shared pointer template class with intrusive reference counting. type - SharedPtr*[T] {.bycopy.} = object ## / Construct a null shared pointer. - ## / Prevent direct assignment from a shared pointer of another type. + SharedPtr*[T] {.bycopy.} = object ## Construct a null shared pointer. + ## Prevent direct assignment from a shared pointer of another type. proc constructSharedPtr*[T](): SharedPtr[T] {.constructor.} @@ -50,22 +50,22 @@ proc Refs*[T](this: SharedPtr[T]): cint {.noSideEffect.} proc WeakRefs*[T](this: SharedPtr[T]): cint {.noSideEffect.} proc RefCountPtr*[T](this: SharedPtr[T]): ptr RefCount {.noSideEffect.} proc ToHash*[T](this: SharedPtr[T]): cuint {.noSideEffect.} -## / Perform a static cast from one shared pointer type to another. +## Perform a static cast from one shared pointer type to another. proc StaticCast*[T; U](`ptr`: SharedPtr[U]): SharedPtr[T] = discard -## / Perform a dynamic cast from one weak pointer type to another. +## Perform a dynamic cast from one weak pointer type to another. proc DynamicCast*[T; U](`ptr`: SharedPtr[U]): SharedPtr[T] = discard -## / Weak pointer template class with intrusive reference counting. Does not keep the object pointed to alive. +## Weak pointer template class with intrusive reference counting. Does not keep the object pointed to alive. type - WeakPtr*[T] {.bycopy.} = object ## / Construct a null weak pointer. - ## / Prevent direct assignment from a weak pointer of different type. - ## / Pointer to the RefCount structure. + WeakPtr*[T] {.bycopy.} = object ## Construct a null weak pointer. + ## Prevent direct assignment from a weak pointer of different type. + ## Pointer to the RefCount structure. proc constructWeakPtr*[T](): WeakPtr[T] {.constructor.} @@ -90,12 +90,12 @@ proc WeakRefs*[T](this: WeakPtr[T]): cint {.noSideEffect.} proc Expired*[T](this: WeakPtr[T]): bool {.noSideEffect.} proc RefCountPtr*[T](this: WeakPtr[T]): ptr RefCount {.noSideEffect.} proc ToHash*[T](this: WeakPtr[T]): cuint {.noSideEffect.} -## / Perform a static cast from one weak pointer type to another. +## Perform a static cast from one weak pointer type to another. proc StaticCast*[T; U](`ptr`: WeakPtr[U]): WeakPtr[T] = discard -## / Perform a dynamic cast from one weak pointer type to another. +## Perform a dynamic cast from one weak pointer type to another. proc DynamicCast*[T; U](`ptr`: WeakPtr[U]): WeakPtr[T] = discard diff --git a/testsuite/tester.nim b/testsuite/tester.nim index 368a94d..c062b53 100644 --- a/testsuite/tester.nim +++ b/testsuite/tester.nim @@ -9,6 +9,7 @@ const cpp2nimCmd = dotslash & "c2nim --cpp $#" cpp2nimCmdKeepBodies = dotslash & "c2nim --cpp --keepBodies $#" hpp2nimCmd = dotslash & "c2nim --cpp --header $#" + c2nimExtrasCmd = dotslash & "c2nim --stdints --strict --header --reordercomments --def:RCL_PUBLIC='__attribute__ ()' --def:RCL_WARN_UNUSED='__attribute__ ()' --def:'RCL_ALIGNAS(N)=__attribute__(align)' --render:extranewlines $#" dir = "testsuite/" usage = """ c2nim test runner @@ -75,5 +76,7 @@ if not exitEarly: for t in walkFiles(dir & "cppkeepbodies/*.cpp"): test(t, cpp2nimCmdKeepBodies, "cppkeepbodies") + for t in walkFiles(dir & "cextras/*.h"): + test(t, c2nimExtrasCmd, "cextras") if failures > 0: quit($failures & " failures occurred.")