diff options
author | Araq <rumpf_a@web.de> | 2014-07-15 09:37:45 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-07-15 09:37:45 +0200 |
commit | 6d3b632b47d626f6915dc2cbef8745baf04b8d76 (patch) | |
tree | cd2097090977d241065d1415bc9d0845689063f8 /compiler/c2nim | |
parent | 41bb0bf9dcccdfcebdb0f823fea8b2853b89ea4e (diff) | |
parent | 5f8ab1653ad38faf395daf1b8a70249f6954b1ba (diff) | |
download | Nim-6d3b632b47d626f6915dc2cbef8745baf04b8d76.tar.gz |
Merge branch 'new_spawn' into devel
Conflicts: todo.txt web/news.txt web/nimrod.ini
Diffstat (limited to 'compiler/c2nim')
-rw-r--r-- | compiler/c2nim/c2nim.nim | 92 | ||||
-rw-r--r-- | compiler/c2nim/clex.nim | 787 | ||||
-rw-r--r-- | compiler/c2nim/cparse.nim | 2272 | ||||
-rw-r--r-- | compiler/c2nim/cpp.nim | 347 | ||||
-rw-r--r-- | compiler/c2nim/nimrod.cfg | 4 | ||||
-rw-r--r-- | compiler/c2nim/tests/enum.h | 40 | ||||
-rw-r--r-- | compiler/c2nim/tests/matrix.h | 240 | ||||
-rw-r--r-- | compiler/c2nim/tests/struct_anonym.h | 27 | ||||
-rw-r--r-- | compiler/c2nim/tests/systest.c | 622 | ||||
-rw-r--r-- | compiler/c2nim/tests/systest2.c | 17 | ||||
-rw-r--r-- | compiler/c2nim/tests/vincent.c | 33 | ||||
-rw-r--r-- | compiler/c2nim/tests/vincent.h | 3 |
12 files changed, 0 insertions, 4484 deletions
diff --git a/compiler/c2nim/c2nim.nim b/compiler/c2nim/c2nim.nim deleted file mode 100644 index 9b12b9e47..000000000 --- a/compiler/c2nim/c2nim.nim +++ /dev/null @@ -1,92 +0,0 @@ -# -# -# c2nim - C to Nimrod source converter -# (c) Copyright 2013 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -import - strutils, os, times, parseopt, llstream, ast, renderer, options, msgs, - clex, cparse - -const - Version = NimrodVersion - Usage = """ -c2nim - C to Nimrod source converter - (c) 2013 Andreas Rumpf -Usage: c2nim [options] inputfile [options] -Options: - -o, --out:FILE set output filename - --cpp process C++ input file - --dynlib:SYMBOL import from dynlib: SYMBOL will be used for the import - --header:HEADER_FILE import from a HEADER_FILE (discouraged!) - --cdecl annotate procs with ``{.cdecl.}`` - --stdcall annotate procs with ``{.stdcall.}`` - --ref convert typ* to ref typ (default: ptr typ) - --prefix:PREFIX strip prefix for the generated Nimrod identifiers - (multiple --prefix options are supported) - --suffix:SUFFIX strip suffix for the generated Nimrod identifiers - (multiple --suffix options are supported) - --skipinclude do not convert ``#include`` to ``import`` - --typeprefixes generate ``T`` and ``P`` type prefixes - --skipcomments do not copy comments - --ignoreRValueRefs translate C++'s ``T&&`` to ``T`` instead ``of var T`` - --keepBodies keep C++'s method bodies - --spliceHeader parse and emit header before source file - -v, --version write c2nim's version - -h, --help show this help -""" - -proc parse(infile: string, options: PParserOptions): PNode = - var stream = llStreamOpen(infile, fmRead) - if stream == nil: rawMessage(errCannotOpenFile, infile) - var p: TParser - openParser(p, infile, stream, options) - result = parseUnit(p) - closeParser(p) - -proc main(infile, outfile: string, options: PParserOptions, spliceHeader: bool) = - var start = getTime() - if spliceHeader and infile.splitFile.ext == ".c" and existsFile(infile.changeFileExt(".h")): - var header_module = parse(infile.changeFileExt(".h"), options) - var source_module = parse(infile, options) - for n in source_module: - addson(header_module, n) - renderModule(header_module, outfile) - else: - renderModule(parse(infile, options), outfile) - rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start), - formatSize(getTotalMem())]) - -var - infile = "" - outfile = "" - spliceHeader = false - parserOptions = newParserOptions() -for kind, key, val in getopt(): - case kind - of cmdArgument: infile = key - of cmdLongOption, cmdShortOption: - case key.toLower - of "help", "h": - stdout.write(Usage) - quit(0) - of "version", "v": - stdout.write(Version & "\n") - quit(0) - of "o", "out": outfile = val - of "spliceheader": spliceHeader = true - else: - if not parserOptions.setOption(key, val): - stdout.writeln("[Error] unknown option: " & key) - of cmdEnd: assert(false) -if infile.len == 0: - # no filename has been given, so we show the help: - stdout.write(Usage) -else: - if outfile.len == 0: - outfile = changeFileExt(infile, "nim") - infile = addFileExt(infile, "h") - main(infile, outfile, parserOptions, spliceHeader) diff --git a/compiler/c2nim/clex.nim b/compiler/c2nim/clex.nim deleted file mode 100644 index 3934eea63..000000000 --- a/compiler/c2nim/clex.nim +++ /dev/null @@ -1,787 +0,0 @@ -# -# -# c2nim - C to Nimrod source converter -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# This module implements an Ansi C scanner. This is an adaption from -# the scanner module. Keywords are not handled here, but in the parser to make -# it more flexible. - - -import - options, msgs, strutils, platform, nimlexbase, llstream - -const - MaxLineLength* = 80 # lines longer than this lead to a warning - numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'} - SymChars*: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'} - SymStartChars*: TCharSet = {'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF'} - -type - TTokKind* = enum - pxInvalid, pxEof, - pxMacroParam, # fake token: macro parameter (with its index) - pxStarComment, # /* */ comment - pxLineComment, # // comment - pxDirective, # #define, etc. - pxDirectiveParLe, # #define m( with parle (yes, C is that ugly!) - pxDirConc, # ## - pxNewLine, # newline: end of directive - pxAmp, # & - pxAmpAmp, # && - pxAmpAsgn, # &= - pxAmpAmpAsgn, # &&= - pxBar, # | - pxBarBar, # || - pxBarAsgn, # |= - pxBarBarAsgn, # ||= - pxNot, # ! - pxPlusPlus, # ++ - pxMinusMinus, # -- - pxPlus, # + - pxPlusAsgn, # += - pxMinus, # - - pxMinusAsgn, # -= - pxMod, # % - pxModAsgn, # %= - pxSlash, # / - pxSlashAsgn, # /= - pxStar, # * - pxStarAsgn, # *= - pxHat, # ^ - pxHatAsgn, # ^= - pxAsgn, # = - pxEquals, # == - pxDot, # . - pxDotDotDot, # ... - pxLe, # <= - pxLt, # < - pxGe, # >= - pxGt, # > - pxNeq, # != - pxConditional, # ? - pxShl, # << - pxShlAsgn, # <<= - pxShr, # >> - pxShrAsgn, # >>= - pxTilde, # ~ - pxTildeAsgn, # ~= - pxArrow, # -> - pxScope, # :: - - pxStrLit, - pxCharLit, - pxSymbol, # a symbol - pxIntLit, - pxInt64Lit, # long constant like 0x70fffffff or out of int range - pxFloatLit, - pxParLe, pxBracketLe, pxCurlyLe, # this order is important - pxParRi, pxBracketRi, pxCurlyRi, # for macro argument parsing! - pxComma, pxSemiColon, pxColon, - pxAngleRi # '>' but determined to be the end of a - # template's angle bracket - TTokKinds* = set[TTokKind] - -type - TNumericalBase* = enum base10, base2, base8, base16 - TToken* = object - xkind*: TTokKind # the type of the token - s*: string # parsed symbol, char or string literal - iNumber*: BiggestInt # the parsed integer literal; - # if xkind == pxMacroParam: parameter's position - fNumber*: BiggestFloat # the parsed floating point literal - base*: TNumericalBase # the numerical base; only valid for int - # or float literals - next*: ref TToken # for C we need arbitrary look-ahead :-( - - TLexer* = object of TBaseLexer - fileIdx*: int32 - inDirective: bool - -proc getTok*(L: var TLexer, tok: var TToken) -proc printTok*(tok: TToken) -proc `$`*(tok: TToken): string -# implementation - -var - gLinesCompiled*: int - -proc fillToken(L: var TToken) = - L.xkind = pxInvalid - L.iNumber = 0 - L.s = "" - L.fNumber = 0.0 - L.base = base10 - -proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) = - openBaseLexer(lex, inputstream) - lex.fileIdx = filename.fileInfoIdx - -proc closeLexer*(lex: var TLexer) = - inc(gLinesCompiled, lex.LineNumber) - closeBaseLexer(lex) - -proc getColumn*(L: TLexer): int = - result = getColNumber(L, L.bufPos) - -proc getLineInfo*(L: TLexer): TLineInfo = - result = newLineInfo(L.fileIdx, L.linenumber, getColNumber(L, L.bufpos)) - -proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = - msgs.GlobalError(getLineInfo(L), msg, arg) - -proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = - var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart) - msgs.GlobalError(info, msg, arg) - -proc tokKindToStr*(k: TTokKind): string = - case k - of pxEof: result = "[EOF]" - of pxInvalid: result = "[invalid]" - of pxMacroParam: result = "[macro param]" - of pxStarComment, pxLineComment: result = "[comment]" - of pxStrLit: result = "[string literal]" - of pxCharLit: result = "[char literal]" - - of pxDirective, pxDirectiveParLe: result = "#" # #define, etc. - of pxDirConc: result = "##" - of pxNewLine: result = "[NewLine]" - of pxAmp: result = "&" # & - of pxAmpAmp: result = "&&" # && - of pxAmpAsgn: result = "&=" # &= - of pxAmpAmpAsgn: result = "&&=" # &&= - of pxBar: result = "|" # | - of pxBarBar: result = "||" # || - of pxBarAsgn: result = "|=" # |= - of pxBarBarAsgn: result = "||=" # ||= - of pxNot: result = "!" # ! - of pxPlusPlus: result = "++" # ++ - of pxMinusMinus: result = "--" # -- - of pxPlus: result = "+" # + - of pxPlusAsgn: result = "+=" # += - of pxMinus: result = "-" # - - of pxMinusAsgn: result = "-=" # -= - of pxMod: result = "%" # % - of pxModAsgn: result = "%=" # %= - of pxSlash: result = "/" # / - of pxSlashAsgn: result = "/=" # /= - of pxStar: result = "*" # * - of pxStarAsgn: result = "*=" # *= - of pxHat: result = "^" # ^ - of pxHatAsgn: result = "^=" # ^= - of pxAsgn: result = "=" # = - of pxEquals: result = "==" # == - of pxDot: result = "." # . - of pxDotDotDot: result = "..." # ... - of pxLe: result = "<=" # <= - of pxLt: result = "<" # < - of pxGe: result = ">=" # >= - of pxGt: result = ">" # > - of pxNeq: result = "!=" # != - of pxConditional: result = "?" - of pxShl: result = "<<" - of pxShlAsgn: result = "<<=" - of pxShr: result = ">>" - of pxShrAsgn: result = ">>=" - of pxTilde: result = "~" - of pxTildeAsgn: result = "~=" - of pxArrow: result = "->" - of pxScope: result = "::" - - of pxSymbol: result = "[identifier]" - of pxIntLit, pxInt64Lit: result = "[integer literal]" - of pxFloatLit: result = "[floating point literal]" - of pxParLe: result = "(" - of pxParRi: result = ")" - of pxBracketLe: result = "[" - of pxBracketRi: result = "]" - of pxComma: result = "," - of pxSemiColon: result = ";" - of pxColon: result = ":" - of pxCurlyLe: result = "{" - of pxCurlyRi: result = "}" - of pxAngleRi: result = "> [end of template]" - -proc `$`(tok: TToken): string = - case tok.xkind - of pxSymbol, pxInvalid, pxStarComment, pxLineComment, pxStrLit: result = tok.s - of pxIntLit, pxInt64Lit: result = $tok.iNumber - of pxFloatLit: result = $tok.fNumber - else: result = tokKindToStr(tok.xkind) - -proc printTok(tok: TToken) = - writeln(stdout, $tok) - -proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) = - # matches ([chars]_)* - var pos = L.bufpos # use registers for pos, buf - var buf = L.buf - while true: - if buf[pos] in chars: - add(tok.s, buf[pos]) - inc(pos) - else: - break - if buf[pos] == '_': - add(tok.s, '_') - inc(pos) - L.bufPos = pos - -proc isFloatLiteral(s: string): bool = - for i in countup(0, len(s)-1): - if s[i] in {'.', 'e', 'E'}: - return true - -proc getNumber2(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 2 # skip 0b - tok.base = base2 - var xi: BiggestInt = 0 - var bits = 0 - while true: - case L.buf[pos] - of 'A'..'Z', 'a'..'z': - # ignore type suffix: - inc(pos) - of '2'..'9', '.': - lexMessage(L, errInvalidNumber) - inc(pos) - of '_': - inc(pos) - of '0', '1': - xi = `shl`(xi, 1) or (ord(L.buf[pos]) - ord('0')) - inc(pos) - inc(bits) - else: break - tok.iNumber = xi - if (bits > 32): tok.xkind = pxInt64Lit - else: tok.xkind = pxIntLit - L.bufpos = pos - -proc getNumber8(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 1 # skip 0 - tok.base = base8 - var xi: BiggestInt = 0 - var bits = 0 - while true: - case L.buf[pos] - of 'A'..'Z', 'a'..'z': - # ignore type suffix: - inc(pos) - of '8'..'9', '.': - lexMessage(L, errInvalidNumber) - inc(pos) - of '_': - inc(pos) - of '0'..'7': - xi = `shl`(xi, 3) or (ord(L.buf[pos]) - ord('0')) - inc(pos) - inc(bits) - else: break - tok.iNumber = xi - if (bits > 12): tok.xkind = pxInt64Lit - else: tok.xkind = pxIntLit - L.bufpos = pos - -proc getNumber16(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 2 # skip 0x - tok.base = base16 - var xi: BiggestInt = 0 - var bits = 0 - while true: - case L.buf[pos] - of 'G'..'Z', 'g'..'z': - # ignore type suffix: - inc(pos) - of '_': inc(pos) - of '0'..'9': - xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('0')) - inc(pos) - inc(bits, 4) - of 'a'..'f': - xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('a') + 10) - inc(pos) - inc(bits, 4) - of 'A'..'F': - xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('A') + 10) - inc(pos) - inc(bits, 4) - else: break - tok.iNumber = xi - if bits > 32: tok.xkind = pxInt64Lit - else: tok.xkind = pxIntLit - L.bufpos = pos - -proc getFloating(L: var TLexer, tok: var TToken) = - matchUnderscoreChars(L, tok, {'0'..'9'}) - if L.buf[L.bufpos] in {'e', 'E'}: - add(tok.s, L.buf[L.bufpos]) - inc(L.bufpos) - if L.buf[L.bufpos] in {'+', '-'}: - add(tok.s, L.buf[L.bufpos]) - inc(L.bufpos) - matchUnderscoreChars(L, tok, {'0'..'9'}) - -proc getNumber(L: var TLexer, tok: var TToken) = - tok.base = base10 - if L.buf[L.bufpos] == '.': - add(tok.s, "0.") - inc(L.bufpos) - getFloating(L, tok) - else: - matchUnderscoreChars(L, tok, {'0'..'9'}) - if L.buf[L.bufpos] == '.': - add(tok.s, '.') - inc(L.bufpos) - getFloating(L, tok) - try: - if isFloatLiteral(tok.s): - tok.fnumber = parseFloat(tok.s) - tok.xkind = pxFloatLit - else: - tok.iNumber = parseInt(tok.s) - if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)): - tok.xkind = pxInt64Lit - else: - tok.xkind = pxIntLit - except EInvalidValue: - lexMessage(L, errInvalidNumber, tok.s) - except EOverflow: - lexMessage(L, errNumberOutOfRange, tok.s) - # ignore type suffix: - while L.buf[L.bufpos] in {'A'..'Z', 'a'..'z'}: inc(L.bufpos) - -proc handleCRLF(L: var TLexer, pos: int): int = - case L.buf[pos] - of CR: result = nimlexbase.handleCR(L, pos) - of LF: result = nimlexbase.handleLF(L, pos) - else: result = pos - -proc escape(L: var TLexer, tok: var TToken, allowEmpty=false) = - inc(L.bufpos) # skip \ - case L.buf[L.bufpos] - of 'b', 'B': - add(tok.s, '\b') - inc(L.bufpos) - of 't', 'T': - add(tok.s, '\t') - inc(L.bufpos) - of 'n', 'N': - add(tok.s, '\L') - inc(L.bufpos) - of 'f', 'F': - add(tok.s, '\f') - inc(L.bufpos) - of 'r', 'R': - add(tok.s, '\r') - inc(L.bufpos) - of '\'': - add(tok.s, '\'') - inc(L.bufpos) - of '"': - add(tok.s, '"') - inc(L.bufpos) - of '\\': - add(tok.s, '\b') - inc(L.bufpos) - of '0'..'7': - var xi = ord(L.buf[L.bufpos]) - ord('0') - inc(L.bufpos) - if L.buf[L.bufpos] in {'0'..'7'}: - xi = (xi shl 3) or (ord(L.buf[L.bufpos]) - ord('0')) - inc(L.bufpos) - if L.buf[L.bufpos] in {'0'..'7'}: - xi = (xi shl 3) or (ord(L.buf[L.bufpos]) - ord('0')) - inc(L.bufpos) - add(tok.s, chr(xi)) - of 'x': - var xi = 0 - inc(L.bufpos) - while true: - case L.buf[L.bufpos] - of '0'..'9': - xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('0')) - inc(L.bufpos) - of 'a'..'f': - xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('a') + 10) - inc(L.bufpos) - of 'A'..'F': - xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('A') + 10) - inc(L.bufpos) - else: - break - add(tok.s, chr(xi)) - elif not allowEmpty: - lexMessage(L, errInvalidCharacterConstant) - -proc getCharLit(L: var TLexer, tok: var TToken) = - inc(L.bufpos) # skip ' - if L.buf[L.bufpos] == '\\': - escape(L, tok) - else: - add(tok.s, L.buf[L.bufpos]) - inc(L.bufpos) - if L.buf[L.bufpos] == '\'': - inc(L.bufpos) - else: - lexMessage(L, errMissingFinalQuote) - tok.xkind = pxCharLit - -proc getString(L: var TLexer, tok: var TToken) = - var pos = L.bufPos + 1 # skip " - var buf = L.buf # put `buf` in a register - var line = L.linenumber # save linenumber for better error message - while true: - case buf[pos] - of '\"': - inc(pos) - break - of CR: - pos = nimlexbase.HandleCR(L, pos) - buf = L.buf - of LF: - pos = nimlexbase.HandleLF(L, pos) - buf = L.buf - of nimlexbase.EndOfFile: - var line2 = L.linenumber - L.LineNumber = line - lexMessagePos(L, errClosingQuoteExpected, L.lineStart) - L.LineNumber = line2 - break - of '\\': - # we allow an empty \ for line concatenation, but we don't require it - # for line concatenation - L.bufpos = pos - escape(L, tok, allowEmpty=true) - pos = L.bufpos - else: - add(tok.s, buf[pos]) - inc(pos) - L.bufpos = pos - tok.xkind = pxStrLit - -proc getSymbol(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - while true: - var c = buf[pos] - if c notin SymChars: break - add(tok.s, c) - inc(pos) - L.bufpos = pos - tok.xkind = pxSymbol - -proc scanLineComment(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - # a comment ends if the next line does not start with the // on the same - # column after only whitespace - tok.xkind = pxLineComment - var col = getColNumber(L, pos) - while true: - inc(pos, 2) # skip // - add(tok.s, '#') - while not (buf[pos] in {CR, LF, nimlexbase.EndOfFile}): - add(tok.s, buf[pos]) - inc(pos) - pos = handleCRLF(L, pos) - buf = L.buf - var indent = 0 - while buf[pos] == ' ': - inc(pos) - inc(indent) - if (col == indent) and (buf[pos] == '/') and (buf[pos + 1] == '/'): - add(tok.s, "\n") - else: - break - L.bufpos = pos - -proc scanStarComment(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - tok.s = "#" - tok.xkind = pxStarComment - while true: - case buf[pos] - of CR, LF: - pos = handleCRLF(L, pos) - buf = L.buf - add(tok.s, "\n#") - # skip annoying stars as line prefix: (eg. - # /* - # * ugly comment <-- this star - # */ - while buf[pos] in {' ', '\t'}: - add(tok.s, ' ') - inc(pos) - if buf[pos] == '*' and buf[pos+1] != '/': inc(pos) - of '*': - inc(pos) - if buf[pos] == '/': - inc(pos) - break - else: - add(tok.s, '*') - of nimlexbase.EndOfFile: - lexMessage(L, errTokenExpected, "*/") - else: - add(tok.s, buf[pos]) - inc(pos) - L.bufpos = pos - -proc skip(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - while true: - case buf[pos] - of '\\': - # Ignore \ line continuation characters when not inDirective - inc(pos) - if L.inDirective: - while buf[pos] in {' ', '\t'}: inc(pos) - if buf[pos] in {CR, LF}: - pos = handleCRLF(L, pos) - buf = L.buf - of ' ', Tabulator: - inc(pos) # newline is special: - of CR, LF: - pos = handleCRLF(L, pos) - buf = L.buf - if L.inDirective: - tok.xkind = pxNewLine - L.inDirective = false - else: - break # EndOfFile also leaves the loop - L.bufpos = pos - -proc getDirective(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 1 - var buf = L.buf - while buf[pos] in {' ', '\t'}: inc(pos) - while buf[pos] in SymChars: - add(tok.s, buf[pos]) - inc(pos) - # a HACK: we need to distinguish - # #define x (...) - # from: - # #define x(...) - # - L.bufpos = pos - # look ahead: - while buf[pos] in {' ', '\t'}: inc(pos) - while buf[pos] in SymChars: inc(pos) - if buf[pos] == '(': tok.xkind = pxDirectiveParLe - else: tok.xkind = pxDirective - L.inDirective = true - -proc getTok(L: var TLexer, tok: var TToken) = - tok.xkind = pxInvalid - fillToken(tok) - skip(L, tok) - if tok.xkind == pxNewLine: return - var c = L.buf[L.bufpos] - if c in SymStartChars: - getSymbol(L, tok) - elif c == '0': - case L.buf[L.bufpos+1] - of 'x', 'X': getNumber16(L, tok) - of 'b', 'B': getNumber2(L, tok) - of '1'..'7': getNumber8(L, tok) - else: getNumber(L, tok) - elif c in {'1'..'9'} or (c == '.' and L.buf[L.bufpos+1] in {'0'..'9'}): - getNumber(L, tok) - else: - case c - of ';': - tok.xkind = pxSemicolon - inc(L.bufpos) - of '/': - if L.buf[L.bufpos + 1] == '/': - scanLineComment(L, tok) - elif L.buf[L.bufpos+1] == '*': - inc(L.bufpos, 2) - scanStarComment(L, tok) - elif L.buf[L.bufpos+1] == '=': - inc(L.bufpos, 2) - tok.xkind = pxSlashAsgn - else: - tok.xkind = pxSlash - inc(L.bufpos) - of ',': - tok.xkind = pxComma - inc(L.bufpos) - of '(': - inc(L.bufpos) - tok.xkind = pxParLe - of '*': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxStarAsgn - else: - tok.xkind = pxStar - of ')': - inc(L.bufpos) - tok.xkind = pxParRi - of '[': - inc(L.bufpos) - tok.xkind = pxBracketLe - of ']': - inc(L.bufpos) - tok.xkind = pxBracketRi - of '.': - inc(L.bufpos) - if L.buf[L.bufpos] == '.' and L.buf[L.bufpos+1] == '.': - tok.xkind = pxDotDotDot - inc(L.bufpos, 2) - else: - tok.xkind = pxDot - of '{': - inc(L.bufpos) - tok.xkind = pxCurlyLe - of '}': - inc(L.bufpos) - tok.xkind = pxCurlyRi - of '+': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxPlusAsgn - inc(L.bufpos) - elif L.buf[L.bufpos] == '+': - tok.xkind = pxPlusPlus - inc(L.bufpos) - else: - tok.xkind = pxPlus - of '-': - inc(L.bufpos) - case L.buf[L.bufpos] - of '>': - tok.xkind = pxArrow - inc(L.bufpos) - of '=': - tok.xkind = pxMinusAsgn - inc(L.bufpos) - of '-': - tok.xkind = pxMinusMinus - inc(L.bufpos) - else: - tok.xkind = pxMinus - of '?': - inc(L.bufpos) - tok.xkind = pxConditional - of ':': - inc(L.bufpos) - if L.buf[L.bufpos] == ':': - tok.xkind = pxScope - inc(L.bufpos) - else: - tok.xkind = pxColon - of '!': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxNeq - inc(L.bufpos) - else: - tok.xkind = pxNot - of '<': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxLe - elif L.buf[L.bufpos] == '<': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxShlAsgn - else: - tok.xkind = pxShl - else: - tok.xkind = pxLt - of '>': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxGe - elif L.buf[L.bufpos] == '>': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxShrAsgn - else: - tok.xkind = pxShr - else: - tok.xkind = pxGt - of '=': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxEquals - inc(L.bufpos) - else: - tok.xkind = pxAsgn - of '&': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxAmpAsgn - inc(L.bufpos) - elif L.buf[L.bufpos] == '&': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxAmpAmpAsgn - else: - tok.xkind = pxAmpAmp - else: - tok.xkind = pxAmp - of '|': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxBarAsgn - inc(L.bufpos) - elif L.buf[L.bufpos] == '|': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxBarBarAsgn - else: - tok.xkind = pxBarBar - else: - tok.xkind = pxBar - of '^': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxHatAsgn - inc(L.bufpos) - else: - tok.xkind = pxHat - of '%': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxModAsgn - inc(L.bufpos) - else: - tok.xkind = pxMod - of '~': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxTildeAsgn - inc(L.bufpos) - else: - tok.xkind = pxTilde - of '#': - if L.buf[L.bufpos+1] == '#': - inc(L.bufpos, 2) - tok.xkind = pxDirConc - else: - getDirective(L, tok) - of '"': getString(L, tok) - of '\'': getCharLit(L, tok) - of nimlexbase.EndOfFile: - tok.xkind = pxEof - else: - tok.s = $c - tok.xkind = pxInvalid - lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')') - inc(L.bufpos) diff --git a/compiler/c2nim/cparse.nim b/compiler/c2nim/cparse.nim deleted file mode 100644 index 2e31af528..000000000 --- a/compiler/c2nim/cparse.nim +++ /dev/null @@ -1,2272 +0,0 @@ -# -# -# c2nim - C to Nimrod source converter -# (c) Copyright 2013 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This module implements an Ansi C parser. -## It translates a C source file into a Nimrod AST. Then the renderer can be -## used to convert the AST to its text representation. - -# TODO -# - document 'cpp' mode -# - implement handling of '::': function declarations -# - C++'s "operator" still needs some love -# - support '#if' in classes - -import - os, llstream, renderer, clex, idents, strutils, pegs, ast, astalgo, msgs, - options, strtabs, hashes, algorithm - -type - TParserFlag = enum - pfRefs, ## use "ref" instead of "ptr" for C's typ* - pfCDecl, ## annotate procs with cdecl - pfStdCall, ## annotate procs with stdcall - pfSkipInclude, ## skip all ``#include`` - pfTypePrefixes, ## all generated types start with 'T' or 'P' - pfSkipComments, ## do not generate comments - pfCpp, ## process C++ - pfIgnoreRValueRefs, ## transform C++'s 'T&&' to 'T' - pfKeepBodies ## do not skip C++ method bodies - - TMacro = object - name: string - params: int # number of parameters - body: seq[ref TToken] # can contain pxMacroParam tokens - - TParserOptions = object - flags: set[TParserFlag] - prefixes, suffixes: seq[string] - mangleRules: seq[tuple[pattern: TPeg, frmt: string]] - privateRules: seq[TPeg] - dynlibSym, header: string - macros: seq[TMacro] - toMangle: PStringTable - classes: PStringTable - PParserOptions* = ref TParserOptions - - TParser* = object - lex: TLexer - tok: ref TToken # current token - options: PParserOptions - backtrack: seq[ref TToken] - inTypeDef: int - scopeCounter: int - hasDeadCodeElimPragma: bool - currentClass: PNode # type that needs to be added as 'this' parameter - - TReplaceTuple* = array[0..1, string] - - ERetryParsing = object of ESynch - - - -proc addTypeDef(section, name, t: PNode) -proc parseStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode -proc parseStructBody(p: var TParser, stmtList: PNode, isUnion: bool, - kind: TNodeKind = nkRecList): PNode - - - -proc newParserOptions*(): PParserOptions = - new(result) - result.prefixes = @[] - result.suffixes = @[] - result.macros = @[] - result.mangleRules = @[] - result.privateRules = @[] - result.flags = {} - result.dynlibSym = "" - result.header = "" - result.toMangle = newStringTable(modeCaseSensitive) - result.classes = newStringTable(modeCaseSensitive) - -proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool = - result = true - case key.normalize - of "ref": incl(parserOptions.flags, pfRefs) - of "dynlib": parserOptions.dynlibSym = val - of "header": parserOptions.header = val - of "cdecl": incl(parserOptions.flags, pfCdecl) - of "stdcall": incl(parserOptions.flags, pfStdCall) - of "prefix": parserOptions.prefixes.add(val) - of "suffix": parserOptions.suffixes.add(val) - of "skipinclude": incl(parserOptions.flags, pfSkipInclude) - of "typeprefixes": incl(parserOptions.flags, pfTypePrefixes) - of "skipcomments": incl(parserOptions.flags, pfSkipComments) - of "cpp": incl(parserOptions.flags, pfCpp) - of "keepbodies": incl(parserOptions.flags, pfKeepBodies) - of "ignorervaluerefs": incl(parserOptions.flags, pfIgnoreRValueRefs) - of "class": parserOptions.classes[val] = "true" - else: result = false - -proc parseUnit*(p: var TParser): PNode -proc openParser*(p: var TParser, filename: string, inputStream: PLLStream, - options = newParserOptions()) -proc closeParser*(p: var TParser) - -# implementation - -proc openParser(p: var TParser, filename: string, - inputStream: PLLStream, options = newParserOptions()) = - openLexer(p.lex, filename, inputStream) - p.options = options - p.backtrack = @[] - new(p.tok) - -proc parMessage(p: TParser, msg: TMsgKind, arg = "") = - #assert false - lexMessage(p.lex, msg, arg) - -proc closeParser(p: var TParser) = closeLexer(p.lex) -proc saveContext(p: var TParser) = p.backtrack.add(p.tok) -proc closeContext(p: var TParser) = discard p.backtrack.pop() -proc backtrackContext(p: var TParser) = p.tok = p.backtrack.pop() - -proc rawGetTok(p: var TParser) = - if p.tok.next != nil: - p.tok = p.tok.next - elif p.backtrack.len == 0: - p.tok.next = nil - getTok(p.lex, p.tok[]) - else: - # We need the next token and must be able to backtrack. So we need to - # allocate a new token. - var t: ref TToken - new(t) - getTok(p.lex, t[]) - p.tok.next = t - p.tok = t - -proc insertAngleRi(currentToken: ref TToken) = - var t: ref TToken - new(t) - t.xkind = pxAngleRi - t.next = currentToken.next - currentToken.next = t - -proc findMacro(p: TParser): int = - for i in 0..high(p.options.macros): - if p.tok.s == p.options.macros[i].name: return i - return -1 - -proc rawEat(p: var TParser, xkind: TTokKind) = - if p.tok.xkind == xkind: rawGetTok(p) - else: parMessage(p, errTokenExpected, tokKindToStr(xkind)) - -proc parseMacroArguments(p: var TParser): seq[seq[ref TToken]] = - result = @[] - result.add(@[]) - var i: array[pxParLe..pxCurlyLe, int] - var L = 0 - saveContext(p) - while true: - var kind = p.tok.xkind - case kind - of pxEof: rawEat(p, pxParRi) - of pxParLe, pxBracketLe, pxCurlyLe: - inc(i[kind]) - result[L].add(p.tok) - of pxParRi: - # end of arguments? - if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0: break - if i[pxParLe] > 0: dec(i[pxParLe]) - result[L].add(p.tok) - of pxBracketRi, pxCurlyRi: - kind = pred(kind, 3) - if i[kind] > 0: dec(i[kind]) - result[L].add(p.tok) - of pxComma: - if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0: - # next argument: comma is not part of the argument - result.add(@[]) - inc(L) - else: - # comma does not separate different arguments: - result[L].add(p.tok) - else: - result[L].add(p.tok) - rawGetTok(p) - closeContext(p) - -proc expandMacro(p: var TParser, m: TMacro) = - rawGetTok(p) # skip macro name - var arguments: seq[seq[ref TToken]] - if m.params > 0: - rawEat(p, pxParLe) - arguments = parseMacroArguments(p) - if arguments.len != m.params: parMessage(p, errWrongNumberOfArguments) - rawEat(p, pxParRi) - # insert into the token list: - if m.body.len > 0: - var newList: ref TToken - new(newList) - var lastTok = newList - for tok in items(m.body): - if tok.xkind == pxMacroParam: - for t in items(arguments[int(tok.iNumber)]): - #echo "t: ", t^ - lastTok.next = t - lastTok = t - else: - #echo "tok: ", tok^ - lastTok.next = tok - lastTok = tok - lastTok.next = p.tok - p.tok = newList.next - -proc getTok(p: var TParser) = - rawGetTok(p) - if p.tok.xkind == pxSymbol: - var idx = findMacro(p) - if idx >= 0: - expandMacro(p, p.options.macros[idx]) - -proc parLineInfo(p: TParser): TLineInfo = - result = getLineInfo(p.lex) - -proc skipComAux(p: var TParser, n: PNode) = - if n != nil and n.kind != nkEmpty: - if pfSkipComments notin p.options.flags: - if n.comment == nil: n.comment = p.tok.s - else: add(n.comment, "\n" & p.tok.s) - else: - parMessage(p, warnCommentXIgnored, p.tok.s) - getTok(p) - -proc skipCom(p: var TParser, n: PNode) = - while p.tok.xkind in {pxLineComment, pxStarComment}: skipComAux(p, n) - -proc skipStarCom(p: var TParser, n: PNode) = - while p.tok.xkind == pxStarComment: skipComAux(p, n) - -proc getTok(p: var TParser, n: PNode) = - getTok(p) - skipCom(p, n) - -proc expectIdent(p: TParser) = - if p.tok.xkind != pxSymbol: parMessage(p, errIdentifierExpected, $(p.tok[])) - -proc eat(p: var TParser, xkind: TTokKind, n: PNode) = - if p.tok.xkind == xkind: getTok(p, n) - else: parMessage(p, errTokenExpected, tokKindToStr(xkind)) - -proc eat(p: var TParser, xkind: TTokKind) = - if p.tok.xkind == xkind: getTok(p) - else: parMessage(p, errTokenExpected, tokKindToStr(xkind)) - -proc eat(p: var TParser, tok: string, n: PNode) = - if p.tok.s == tok: getTok(p, n) - else: parMessage(p, errTokenExpected, tok) - -proc opt(p: var TParser, xkind: TTokKind, n: PNode) = - if p.tok.xkind == xkind: getTok(p, n) - -proc addSon(father, a, b: PNode) = - addSon(father, a) - addSon(father, b) - -proc addSon(father, a, b, c: PNode) = - addSon(father, a) - addSon(father, b) - addSon(father, c) - -proc newNodeP(kind: TNodeKind, p: TParser): PNode = - result = newNodeI(kind, getLineInfo(p.lex)) - -proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode = - result = newNodeP(kind, p) - result.intVal = intVal - -proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, - p: TParser): PNode = - result = newNodeP(kind, p) - result.floatVal = floatVal - -proc newStrNodeP(kind: TNodeKind, strVal: string, p: TParser): PNode = - result = newNodeP(kind, p) - result.strVal = strVal - -proc newIdentNodeP(ident: PIdent, p: TParser): PNode = - result = newNodeP(nkIdent, p) - result.ident = ident - -proc newIdentNodeP(ident: string, p: TParser): PNode = - result = newIdentNodeP(getIdent(ident), p) - -proc mangleRules(s: string, p: TParser): string = - block mangle: - for pattern, frmt in items(p.options.mangleRules): - if s.match(pattern): - result = s.replacef(pattern, frmt) - break mangle - block prefixes: - for prefix in items(p.options.prefixes): - if s.startsWith(prefix): - result = s.substr(prefix.len) - break prefixes - result = s - block suffixes: - for suffix in items(p.options.suffixes): - if result.endsWith(suffix): - setLen(result, result.len - suffix.len) - break suffixes - -proc mangleName(s: string, p: TParser): string = - if p.options.toMangle.hasKey(s): result = p.options.toMangle[s] - else: result = mangleRules(s, p) - -proc isPrivate(s: string, p: TParser): bool = - for pattern in items(p.options.privateRules): - if s.match(pattern): return true - -proc mangledIdent(ident: string, p: TParser): PNode = - result = newNodeP(nkIdent, p) - result.ident = getIdent(mangleName(ident, p)) - -proc newIdentPair(a, b: string, p: TParser): PNode = - result = newNodeP(nkExprColonExpr, p) - addSon(result, newIdentNodeP(a, p)) - addSon(result, newIdentNodeP(b, p)) - -proc newIdentStrLitPair(a, b: string, p: TParser): PNode = - result = newNodeP(nkExprColonExpr, p) - addSon(result, newIdentNodeP(a, p)) - addSon(result, newStrNodeP(nkStrLit, b, p)) - -proc addImportToPragma(pragmas: PNode, ident: string, p: TParser) = - addSon(pragmas, newIdentStrLitPair("importc", ident, p)) - if p.options.dynlibSym.len > 0: - addSon(pragmas, newIdentPair("dynlib", p.options.dynlibSym, p)) - else: - addSon(pragmas, newIdentStrLitPair("header", p.options.header, p)) - -proc exportSym(p: TParser, i: PNode, origName: string): PNode = - assert i.kind == nkIdent - if p.scopeCounter == 0 and not isPrivate(origName, p): - result = newNodeI(nkPostfix, i.info) - addSon(result, newIdentNode(getIdent("*"), i.info), i) - else: - result = i - -proc varIdent(ident: string, p: TParser): PNode = - result = exportSym(p, mangledIdent(ident, p), ident) - if p.scopeCounter > 0: return - if p.options.dynlibSym.len > 0 or p.options.header.len > 0: - var a = result - result = newNodeP(nkPragmaExpr, p) - var pragmas = newNodeP(nkPragma, p) - addSon(result, a) - addSon(result, pragmas) - addImportToPragma(pragmas, ident, p) - -proc fieldIdent(ident: string, p: TParser): PNode = - result = exportSym(p, mangledIdent(ident, p), ident) - if p.scopeCounter > 0: return - if p.options.header.len > 0: - var a = result - result = newNodeP(nkPragmaExpr, p) - var pragmas = newNodeP(nkPragma, p) - addSon(result, a) - addSon(result, pragmas) - addSon(pragmas, newIdentStrLitPair("importc", ident, p)) - -proc doImport(ident: string, pragmas: PNode, p: TParser) = - if p.options.dynlibSym.len > 0 or p.options.header.len > 0: - addImportToPragma(pragmas, ident, p) - -proc doImportCpp(ident: string, pragmas: PNode, p: TParser) = - if p.options.dynlibSym.len > 0 or p.options.header.len > 0: - addSon(pragmas, newIdentStrLitPair("importcpp", ident, p)) - if p.options.dynlibSym.len > 0: - addSon(pragmas, newIdentPair("dynlib", p.options.dynlibSym, p)) - else: - addSon(pragmas, newIdentStrLitPair("header", p.options.header, p)) - -proc newBinary(opr: string, a, b: PNode, p: TParser): PNode = - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP(getIdent(opr), p)) - addSon(result, a) - addSon(result, b) - -proc skipIdent(p: var TParser): PNode = - expectIdent(p) - result = mangledIdent(p.tok.s, p) - getTok(p, result) - -proc skipIdentExport(p: var TParser): PNode = - expectIdent(p) - result = exportSym(p, mangledIdent(p.tok.s, p), p.tok.s) - getTok(p, result) - -proc skipTypeIdentExport(p: var TParser, prefix='T'): PNode = - expectIdent(p) - var n = prefix & mangleName(p.tok.s, p) - p.options.toMangle[p.tok.s] = n - var i = newNodeP(nkIdent, p) - i.ident = getIdent(n) - result = exportSym(p, i, p.tok.s) - getTok(p, result) - -proc markTypeIdent(p: var TParser, typ: PNode) = - if pfTypePrefixes in p.options.flags: - var prefix = "" - if typ == nil or typ.kind == nkEmpty: - prefix = "T" - else: - var t = typ - while t != nil and t.kind in {nkVarTy, nkPtrTy, nkRefTy}: - prefix.add('P') - t = t.sons[0] - if prefix.len == 0: prefix.add('T') - expectIdent(p) - p.options.toMangle[p.tok.s] = prefix & mangleRules(p.tok.s, p) - -# --------------- parser ----------------------------------------------------- -# We use this parsing rule: If it looks like a declaration, it is one. This -# avoids to build a symbol table, which can't be done reliably anyway for our -# purposes. - -proc expression(p: var TParser, rbp: int = 0): PNode -proc constantExpression(p: var TParser): PNode = expression(p, 40) -proc assignmentExpression(p: var TParser): PNode = expression(p, 30) -proc compoundStatement(p: var TParser): PNode -proc statement(p: var TParser): PNode - -proc declKeyword(p: TParser, s: string): bool = - # returns true if it is a keyword that introduces a declaration - case s - of "extern", "static", "auto", "register", "const", "volatile", "restrict", - "inline", "__inline", "__cdecl", "__stdcall", "__syscall", "__fastcall", - "__safecall", "void", "struct", "union", "enum", "typedef", - "short", "int", "long", "float", "double", "signed", "unsigned", "char": - result = true - of "class": - result = p.options.flags.contains(pfCpp) - -proc stmtKeyword(s: string): bool = - case s - of "if", "for", "while", "do", "switch", "break", "continue", "return", - "goto": - result = true - -# ------------------- type desc ----------------------------------------------- - -proc isIntType(s: string): bool = - case s - of "short", "int", "long", "float", "double", "signed", "unsigned": - result = true - -proc skipConst(p: var TParser) = - while p.tok.xkind == pxSymbol and - (p.tok.s == "const" or p.tok.s == "volatile" or p.tok.s == "restrict"): - getTok(p, nil) - -proc isTemplateAngleBracket(p: var TParser): bool = - if pfCpp notin p.options.flags: return false - saveContext(p) - getTok(p, nil) # skip "<" - var i: array[pxParLe..pxCurlyLe, int] - var angles = 0 - while true: - let kind = p.tok.xkind - case kind - of pxEof: break - of pxParLe, pxBracketLe, pxCurlyLe: inc(i[kind]) - of pxGt, pxAngleRi: - # end of arguments? - if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0 and - angles == 0: - # mark as end token: - p.tok.xkind = pxAngleRi - result = true; - break - if angles > 0: dec(angles) - of pxShr: - # >> can end a template too: - if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0 and - angles == 1: - p.tok.xkind = pxAngleRi - insertAngleRi(p.tok) - result = true - break - if angles > 1: dec(angles, 2) - of pxLt: inc(angles) - of pxParRi, pxBracketRi, pxCurlyRi: - let kind = pred(kind, 3) - if i[kind] > 0: dec(i[kind]) - else: break - of pxSemicolon: break - else: discard - getTok(p, nil) - backtrackContext(p) - -proc optAngle(p: var TParser, n: PNode): PNode = - if p.tok.xkind == pxLt and isTemplateAngleBracket(p): - getTok(p) - result = newNodeP(nkBracketExpr, p) - result.add(n) - while true: - let a = assignmentExpression(p) - if not a.isNil: result.add(a) - if p.tok.xkind != pxComma: break - getTok(p) - eat(p, pxAngleRi) - else: - result = n - -proc optScope(p: var TParser, n: PNode): PNode = - result = n - if pfCpp in p.options.flags: - while p.tok.xkind == pxScope: - let a = result - result = newNodeP(nkDotExpr, p) - result.add(a) - getTok(p, result) - expectIdent(p) - result.add(mangledIdent(p.tok.s, p)) - getTok(p, result) - -proc typeAtom(p: var TParser): PNode = - skipConst(p) - expectIdent(p) - case p.tok.s - of "void": - result = newNodeP(nkNilLit, p) # little hack - getTok(p, nil) - of "struct", "union", "enum": - getTok(p, nil) - result = skipIdent(p) - elif isIntType(p.tok.s): - var x = "" - #getTok(p, nil) - var isUnsigned = false - while p.tok.xkind == pxSymbol and (isIntType(p.tok.s) or p.tok.s == "char"): - if p.tok.s == "unsigned": - isUnsigned = true - elif p.tok.s == "signed" or p.tok.s == "int": - discard - else: - add(x, p.tok.s) - getTok(p, nil) - if x.len == 0: x = "int" - let xx = if isUnsigned: "cu" & x else: "c" & x - result = mangledIdent(xx, p) - else: - result = mangledIdent(p.tok.s, p) - getTok(p, result) - result = optScope(p, result) - result = optAngle(p, result) - -proc newPointerTy(p: TParser, typ: PNode): PNode = - if pfRefs in p.options.flags: - result = newNodeP(nkRefTy, p) - else: - result = newNodeP(nkPtrTy, p) - result.addSon(typ) - -proc pointer(p: var TParser, a: PNode): PNode = - result = a - var i = 0 - skipConst(p) - while true: - if p.tok.xkind == pxStar: - inc(i) - getTok(p, result) - skipConst(p) - result = newPointerTy(p, result) - elif p.tok.xkind == pxAmp and pfCpp in p.options.flags: - getTok(p, result) - skipConst(p) - let b = result - result = newNodeP(nkVarTy, p) - result.add(b) - elif p.tok.xkind == pxAmpAmp and pfCpp in p.options.flags: - getTok(p, result) - skipConst(p) - if pfIgnoreRvalueRefs notin p.options.flags: - let b = result - result = newNodeP(nkVarTy, p) - result.add(b) - else: break - if a.kind == nkIdent and a.ident.s == "char": - if i >= 2: - result = newIdentNodeP("cstringArray", p) - for j in 1..i-2: result = newPointerTy(p, result) - elif i == 1: result = newIdentNodeP("cstring", p) - elif a.kind == nkNilLit and i > 0: - result = newIdentNodeP("pointer", p) - for j in 1..i-1: result = newPointerTy(p, result) - -proc newProcPragmas(p: TParser): PNode = - result = newNodeP(nkPragma, p) - if pfCDecl in p.options.flags: - addSon(result, newIdentNodeP("cdecl", p)) - elif pfStdCall in p.options.flags: - addSon(result, newIdentNodeP("stdcall", p)) - -proc addPragmas(father, pragmas: PNode) = - if sonsLen(pragmas) > 0: addSon(father, pragmas) - else: addSon(father, ast.emptyNode) - -proc addReturnType(params, rettyp: PNode) = - if rettyp == nil: addSon(params, ast.emptyNode) - elif rettyp.kind != nkNilLit: addSon(params, rettyp) - else: addSon(params, ast.emptyNode) - -proc parseFormalParams(p: var TParser, params, pragmas: PNode) - -proc parseTypeSuffix(p: var TParser, typ: PNode): PNode = - result = typ - while true: - case p.tok.xkind - of pxBracketLe: - getTok(p, result) - skipConst(p) # POSIX contains: ``int [restrict]`` - if p.tok.xkind != pxBracketRi: - var tmp = result - var index = expression(p) - # array type: - result = newNodeP(nkBracketExpr, p) - addSon(result, newIdentNodeP("array", p)) - #var r = newNodeP(nkRange, p) - #addSon(r, newIntNodeP(nkIntLit, 0, p)) - #addSon(r, newBinary("-", index, newIntNodeP(nkIntLit, 1, p), p)) - #addSon(result, r) - addSon(result, index) - addSon(result, tmp) - else: - # pointer type: - var tmp = result - if pfRefs in p.options.flags: - result = newNodeP(nkRefTy, p) - else: - result = newNodeP(nkPtrTy, p) - result.addSon(tmp) - eat(p, pxBracketRi, result) - of pxParLe: - # function pointer: - var procType = newNodeP(nkProcTy, p) - var pragmas = newProcPragmas(p) - var params = newNodeP(nkFormalParams, p) - addReturnType(params, result) - parseFormalParams(p, params, pragmas) - addSon(procType, params) - addPragmas(procType, pragmas) - result = procType - else: break - -proc typeDesc(p: var TParser): PNode = - result = pointer(p, typeAtom(p)) - -proc abstractDeclarator(p: var TParser, a: PNode): PNode - -proc directAbstractDeclarator(p: var TParser, a: PNode): PNode = - if p.tok.xkind == pxParLe: - getTok(p, a) - if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp}: - result = abstractDeclarator(p, a) - eat(p, pxParRi, result) - return parseTypeSuffix(p, a) - -proc abstractDeclarator(p: var TParser, a: PNode): PNode = - return directAbstractDeclarator(p, pointer(p, a)) - -proc typeName(p: var TParser): PNode = - return abstractDeclarator(p, typeAtom(p)) - -proc parseField(p: var TParser, kind: TNodeKind): PNode = - if p.tok.xkind == pxParLe: - getTok(p, nil) - while p.tok.xkind == pxStar: getTok(p, nil) - result = parseField(p, kind) - eat(p, pxParRi, result) - else: - expectIdent(p) - if kind == nkRecList: result = fieldIdent(p.tok.s, p) - else: result = mangledIdent(p.tok.s, p) - getTok(p, result) - -proc structPragmas(p: TParser, name: PNode, origName: string): PNode = - assert name.kind == nkIdent - result = newNodeP(nkPragmaExpr, p) - addSon(result, exportSym(p, name, origName)) - var pragmas = newNodeP(nkPragma, p) - #addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p)) - if p.options.header.len > 0: - addSon(pragmas, newIdentStrLitPair("importc", origName, p), - newIdentStrLitPair("header", p.options.header, p)) - if pragmas.len > 0: addSon(result, pragmas) - else: addSon(result, ast.emptyNode) - -proc hashPosition(p: TParser): string = - let lineInfo = parLineInfo(p) - let fileInfo = fileInfos[lineInfo.fileIndex] - result = $hash(fileInfo.shortName & "_" & $lineInfo.line & "_" & $lineInfo.col).uint - -proc parseInnerStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode = - getTok(p, nil) - if p.tok.xkind != pxCurlyLe: - parMessage(p, errUser, "Expected '{' but found '" & $(p.tok[]) & "'") - - let structName = if isUnion: "INNER_C_UNION_" & p.hashPosition - else: "INNER_C_STRUCT_" & p.hashPosition - let typeSection = newNodeP(nkTypeSection, p) - let newStruct = newNodeP(nkObjectTy, p) - var pragmas = ast.emptyNode - if isUnion: - pragmas = newNodeP(nkPragma, p) - addSon(pragmas, newIdentNodeP("union", p)) - addSon(newStruct, pragmas, ast.emptyNode) # no inheritance - result = newNodeP(nkIdent, p) - result.ident = getIdent(structName) - let struct = parseStructBody(p, stmtList, isUnion) - let defName = newNodeP(nkIdent, p) - defName.ident = getIdent(structName) - addSon(newStruct, struct) - addTypeDef(typeSection, structPragmas(p, defName, "no_name"), newStruct) - addSon(stmtList, typeSection) - -proc parseStructBody(p: var TParser, stmtList: PNode, isUnion: bool, - kind: TNodeKind = nkRecList): PNode = - result = newNodeP(kind, p) - eat(p, pxCurlyLe, result) - while p.tok.xkind notin {pxEof, pxCurlyRi}: - skipConst(p) - var baseTyp: PNode - if p.tok.xkind == pxSymbol and (p.tok.s == "struct" or p.tok.s == "union"): - let gotUnion = if p.tok.s == "union": true else: false - saveContext(p) - getTok(p, nil) - if p.tok.xkind == pxSymbol: - backtrackContext(p) - baseTyp = typeAtom(p) - else: - backtrackContext(p) - baseTyp = parseInnerStruct(p, stmtList, gotUnion) - if p.tok.xkind == pxSemiColon: - let def = newNodeP(nkIdentDefs, p) - var t = pointer(p, baseTyp) - let i = fieldIdent("ano_" & p.hashPosition, p) - t = parseTypeSuffix(p, t) - addSon(def, i, t, ast.emptyNode) - addSon(result, def) - getTok(p, nil) - continue - else: - baseTyp = typeAtom(p) - - while true: - var def = newNodeP(nkIdentDefs, p) - var t = pointer(p, baseTyp) - var i = parseField(p, kind) - t = parseTypeSuffix(p, t) - addSon(def, i, t, ast.emptyNode) - addSon(result, def) - if p.tok.xkind != pxComma: break - getTok(p, def) - eat(p, pxSemicolon, lastSon(result)) - eat(p, pxCurlyRi, result) - -proc enumPragmas(p: TParser, name: PNode): PNode = - result = newNodeP(nkPragmaExpr, p) - addSon(result, name) - var pragmas = newNodeP(nkPragma, p) - var e = newNodeP(nkExprColonExpr, p) - # HACK: sizeof(cint) should be constructed as AST - addSon(e, newIdentNodeP("size", p), newIdentNodeP("sizeof(cint)", p)) - addSon(pragmas, e) - addSon(result, pragmas) - -proc parseStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode = - result = newNodeP(nkObjectTy, p) - var pragmas = ast.emptyNode - if isUnion: - pragmas = newNodeP(nkPragma, p) - addSon(pragmas, newIdentNodeP("union", p)) - addSon(result, pragmas, ast.emptyNode) # no inheritance - if p.tok.xkind == pxCurlyLe: - addSon(result, parseStructBody(p, stmtList, isUnion)) - else: - addSon(result, newNodeP(nkRecList, p)) - -proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode - -proc directDeclarator(p: var TParser, a: PNode, ident: ptr PNode): PNode = - case p.tok.xkind - of pxSymbol: - ident[] = skipIdent(p) - of pxParLe: - getTok(p, a) - if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp, pxSymbol}: - result = declarator(p, a, ident) - eat(p, pxParRi, result) - else: - discard - return parseTypeSuffix(p, a) - -proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode = - return directDeclarator(p, pointer(p, a), ident) - -# parameter-declaration -# declaration-specifiers declarator -# declaration-specifiers asbtract-declarator(opt) -proc parseParam(p: var TParser, params: PNode) = - var typ = typeDesc(p) - # support for ``(void)`` parameter list: - if typ.kind == nkNilLit and p.tok.xkind == pxParRi: return - var name: PNode - typ = declarator(p, typ, addr name) - if name == nil: - var idx = sonsLen(params)+1 - name = newIdentNodeP("a" & $idx, p) - var x = newNodeP(nkIdentDefs, p) - addSon(x, name, typ) - if p.tok.xkind == pxAsgn: - # we support default parameters for C++: - getTok(p, x) - addSon(x, assignmentExpression(p)) - else: - addSon(x, ast.emptyNode) - addSon(params, x) - -proc parseFormalParams(p: var TParser, params, pragmas: PNode) = - eat(p, pxParLe, params) - while p.tok.xkind notin {pxEof, pxParRi}: - if p.tok.xkind == pxDotDotDot: - addSon(pragmas, newIdentNodeP("varargs", p)) - getTok(p, pragmas) - break - parseParam(p, params) - if p.tok.xkind != pxComma: break - getTok(p, params) - eat(p, pxParRi, params) - -proc parseCallConv(p: var TParser, pragmas: PNode) = - while p.tok.xkind == pxSymbol: - case p.tok.s - of "inline", "__inline": addSon(pragmas, newIdentNodeP("inline", p)) - of "__cdecl": addSon(pragmas, newIdentNodeP("cdecl", p)) - of "__stdcall": addSon(pragmas, newIdentNodeP("stdcall", p)) - of "__syscall": addSon(pragmas, newIdentNodeP("syscall", p)) - of "__fastcall": addSon(pragmas, newIdentNodeP("fastcall", p)) - of "__safecall": addSon(pragmas, newIdentNodeP("safecall", p)) - else: break - getTok(p, nil) - -proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode = - var procType = newNodeP(nkProcTy, p) - var pragmas = newProcPragmas(p) - var params = newNodeP(nkFormalParams, p) - eat(p, pxParLe, params) - addReturnType(params, rettyp) - parseCallConv(p, pragmas) - if p.tok.xkind == pxStar: getTok(p, params) - else: parMessage(p, errTokenExpected, "*") - if p.inTypeDef > 0: markTypeIdent(p, nil) - var name = skipIdentExport(p) - eat(p, pxParRi, name) - parseFormalParams(p, params, pragmas) - addSon(procType, params) - addPragmas(procType, pragmas) - - if p.inTypeDef == 0: - result = newNodeP(nkVarSection, p) - var def = newNodeP(nkIdentDefs, p) - addSon(def, name, procType, ast.emptyNode) - addSon(result, def) - else: - result = newNodeP(nkTypeDef, p) - addSon(result, name, ast.emptyNode, procType) - assert result != nil - -proc addTypeDef(section, name, t: PNode) = - var def = newNodeI(nkTypeDef, name.info) - addSon(def, name, ast.emptyNode, t) - addSon(section, def) - -proc otherTypeDef(p: var TParser, section, typ: PNode) = - var name: PNode - var t = typ - if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp}: - t = pointer(p, t) - if p.tok.xkind == pxParLe: - # function pointer: typedef typ (*name)(); - var x = parseFunctionPointerDecl(p, t) - name = x[0] - t = x[2] - else: - # typedef typ name; - markTypeIdent(p, t) - name = skipIdentExport(p) - t = parseTypeSuffix(p, t) - addTypeDef(section, name, t) - -proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) = - while p.tok.xkind == pxComma: - getTok(p, nil) - var newTyp = pointer(p, typ) - markTypeIdent(p, newTyp) - var newName = skipIdentExport(p) - newTyp = parseTypeSuffix(p, newTyp) - addTypeDef(section, newName, newTyp) - -proc createConst(name, typ, val: PNode, p: TParser): PNode = - result = newNodeP(nkConstDef, p) - addSon(result, name, typ, val) - -proc exprToNumber(n: PNode not nil): tuple[succ: bool, val: BiggestInt] = - result = (false, 0.BiggestInt) - case n.kind: - of nkPrefix: - # Check for negative/positive numbers -3 or +6 - if n.sons.len == 2 and n.sons[0].kind == nkIdent and n.sons[1].kind == nkIntLit: - let pre = n.sons[0] - let num = n.sons[1] - if pre.ident.s == "-": result = (true, - num.intVal) - elif pre.ident.s == "+": result = (true, num.intVal) - else: discard - -proc enumFields(p: var TParser, constList: PNode): PNode = - result = newNodeP(nkEnumTy, p) - addSon(result, ast.emptyNode) # enum does not inherit from anything - var i: BiggestInt = 0 - var field: tuple[id: BiggestInt, isNumber: bool, node: PNode] - var fields = newSeq[type(field)]() - while true: - var e = skipIdent(p) - if p.tok.xkind == pxAsgn: - getTok(p, e) - var c = constantExpression(p) - var a = e - e = newNodeP(nkEnumFieldDef, p) - addSon(e, a, c) - skipCom(p, e) - if c.kind == nkIntLit: - i = c.intVal - field.isNumber = true - else: - var (success, number) = exprToNumber(c) - if success: - i = number - field.isNumber = true - else: - field.isNumber = false - else: - inc(i) - field.isNumber = true - field.id = i - field.node = e - fields.add(field) - if p.tok.xkind != pxComma: break - getTok(p, e) - # allow trailing comma: - if p.tok.xkind == pxCurlyRi: break - fields.sort do (x, y: type(field)) -> int: - cmp(x.id, y.id) - var lastId: BiggestInt - var lastIdent: PNode - for count, f in fields: - if not f.isNumber: - addSon(result, f.node) - elif f.id == lastId and count > 0: - var currentIdent: PNode - case f.node.kind: - of nkEnumFieldDef: - if f.node.sons.len > 0 and f.node.sons[0].kind == nkIdent: - currentIdent = f.node.sons[0] - else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") - of nkIdent: currentIdent = f.node - else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") - var constant = createConst( currentIdent, ast.emptyNode, lastIdent, p) - constList.addSon(constant) - else: - addSon(result, f.node) - lastId = f.id - case f.node.kind: - of nkEnumFieldDef: - if f.node.sons.len > 0 and f.node.sons[0].kind == nkIdent: - lastIdent = f.node.sons[0] - else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") - of nkIdent: lastIdent = f.node - else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") - -proc parseTypedefStruct(p: var TParser, result: PNode, stmtList: PNode, isUnion: bool) = - getTok(p, result) - if p.tok.xkind == pxCurlyLe: - var t = parseStruct(p, stmtList, isUnion) - var origName = p.tok.s - markTypeIdent(p, nil) - var name = skipIdent(p) - addTypeDef(result, structPragmas(p, name, origName), t) - parseTrailingDefinedTypes(p, result, name) - elif p.tok.xkind == pxSymbol: - # name to be defined or type "struct a", we don't know yet: - markTypeIdent(p, nil) - var origName = p.tok.s - var nameOrType = skipIdent(p) - case p.tok.xkind - of pxCurlyLe: - var t = parseStruct(p, stmtList, isUnion) - if p.tok.xkind == pxSymbol: - # typedef struct tagABC {} abc, *pabc; - # --> abc is a better type name than tagABC! - markTypeIdent(p, nil) - var origName = p.tok.s - var name = skipIdent(p) - addTypeDef(result, structPragmas(p, name, origName), t) - parseTrailingDefinedTypes(p, result, name) - else: - addTypeDef(result, structPragmas(p, nameOrType, origName), t) - of pxSymbol: - # typedef struct a a? - if mangleName(p.tok.s, p) == nameOrType.ident.s: - # ignore the declaration: - getTok(p, nil) - else: - # typedef struct a b; or typedef struct a b[45]; - otherTypeDef(p, result, nameOrType) - else: - otherTypeDef(p, result, nameOrType) - else: - expectIdent(p) - -proc parseTypedefEnum(p: var TParser, result, constSection: PNode) = - getTok(p, result) - if p.tok.xkind == pxCurlyLe: - getTok(p, result) - var t = enumFields(p, constSection) - eat(p, pxCurlyRi, t) - var origName = p.tok.s - markTypeIdent(p, nil) - var name = skipIdent(p) - addTypeDef(result, enumPragmas(p, exportSym(p, name, origName)), t) - parseTrailingDefinedTypes(p, result, name) - elif p.tok.xkind == pxSymbol: - # name to be defined or type "enum a", we don't know yet: - markTypeIdent(p, nil) - var origName = p.tok.s - var nameOrType = skipIdent(p) - case p.tok.xkind - of pxCurlyLe: - getTok(p, result) - var t = enumFields(p, constSection) - eat(p, pxCurlyRi, t) - if p.tok.xkind == pxSymbol: - # typedef enum tagABC {} abc, *pabc; - # --> abc is a better type name than tagABC! - markTypeIdent(p, nil) - var origName = p.tok.s - var name = skipIdent(p) - addTypeDef(result, enumPragmas(p, exportSym(p, name, origName)), t) - parseTrailingDefinedTypes(p, result, name) - else: - addTypeDef(result, - enumPragmas(p, exportSym(p, nameOrType, origName)), t) - of pxSymbol: - # typedef enum a a? - if mangleName(p.tok.s, p) == nameOrType.ident.s: - # ignore the declaration: - getTok(p, nil) - else: - # typedef enum a b; or typedef enum a b[45]; - otherTypeDef(p, result, nameOrType) - else: - otherTypeDef(p, result, nameOrType) - else: - expectIdent(p) - -proc parseTypeDef(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - var typeSection = newNodeP(nkTypeSection, p) - var afterStatements = newNodeP(nkStmtList, p) - while p.tok.xkind == pxSymbol and p.tok.s == "typedef": - getTok(p, typeSection) - inc(p.inTypeDef) - expectIdent(p) - case p.tok.s - of "struct": parseTypedefStruct(p, typeSection, result, isUnion=false) - of "union": parseTypedefStruct(p, typeSection, result, isUnion=true) - of "enum": - var constSection = newNodeP(nkConstSection, p) - parseTypedefEnum(p, typeSection, constSection) - addSon(afterStatements, constSection) - of "class": - if pfCpp in p.options.flags: - parseTypedefStruct(p, typeSection, result, isUnion=false) - else: - var t = typeAtom(p) - otherTypeDef(p, typeSection, t) - else: - var t = typeAtom(p) - otherTypeDef(p, typeSection, t) - eat(p, pxSemicolon) - dec(p.inTypeDef) - - addSon(result, typeSection) - for s in afterStatements: - addSon(result, s) - -proc skipDeclarationSpecifiers(p: var TParser) = - while p.tok.xkind == pxSymbol: - case p.tok.s - of "extern", "static", "auto", "register", "const", "volatile": - getTok(p, nil) - else: break - -proc parseInitializer(p: var TParser): PNode = - if p.tok.xkind == pxCurlyLe: - result = newNodeP(nkBracket, p) - getTok(p, result) - while p.tok.xkind notin {pxEof, pxCurlyRi}: - addSon(result, parseInitializer(p)) - opt(p, pxComma, nil) - eat(p, pxCurlyRi, result) - else: - result = assignmentExpression(p) - -proc addInitializer(p: var TParser, def: PNode) = - if p.tok.xkind == pxAsgn: - getTok(p, def) - addSon(def, parseInitializer(p)) - else: - addSon(def, ast.emptyNode) - -proc parseVarDecl(p: var TParser, baseTyp, typ: PNode, - origName: string): PNode = - result = newNodeP(nkVarSection, p) - var def = newNodeP(nkIdentDefs, p) - addSon(def, varIdent(origName, p)) - addSon(def, parseTypeSuffix(p, typ)) - addInitializer(p, def) - addSon(result, def) - - while p.tok.xkind == pxComma: - getTok(p, def) - var t = pointer(p, baseTyp) - expectIdent(p) - def = newNodeP(nkIdentDefs, p) - addSon(def, varIdent(p.tok.s, p)) - getTok(p, def) - addSon(def, parseTypeSuffix(p, t)) - addInitializer(p, def) - addSon(result, def) - eat(p, pxSemicolon) - -proc declarationName(p: var TParser): string = - expectIdent(p) - result = p.tok.s - getTok(p) # skip identifier - while p.tok.xkind == pxScope and pfCpp in p.options.flags: - getTok(p) # skip "::" - expectIdent(p) - result.add("::") - result.add(p.tok.s) - getTok(p) - -proc declaration(p: var TParser): PNode = - result = newNodeP(nkProcDef, p) - var pragmas = newNodeP(nkPragma, p) - - skipDeclarationSpecifiers(p) - parseCallConv(p, pragmas) - skipDeclarationSpecifiers(p) - expectIdent(p) - var baseTyp = typeAtom(p) - var rettyp = pointer(p, baseTyp) - skipDeclarationSpecifiers(p) - parseCallConv(p, pragmas) - skipDeclarationSpecifiers(p) - - if p.tok.xkind == pxParLe: - # Function pointer declaration: This is of course only a heuristic, but the - # best we can do here. - result = parseFunctionPointerDecl(p, rettyp) - eat(p, pxSemicolon) - return - var origName = declarationName(p) - case p.tok.xkind - of pxParLe: - # really a function! - var name = mangledIdent(origName, p) - var params = newNodeP(nkFormalParams, p) - addReturnType(params, rettyp) - parseFormalParams(p, params, pragmas) - if pfCpp in p.options.flags and p.tok.xkind == pxSymbol and - p.tok.s == "const": - addSon(pragmas, newIdentNodeP("noSideEffect", p)) - getTok(p) - if pfCDecl in p.options.flags: - addSon(pragmas, newIdentNodeP("cdecl", p)) - elif pfStdcall in p.options.flags: - addSon(pragmas, newIdentNodeP("stdcall", p)) - # no pattern, no exceptions: - addSon(result, exportSym(p, name, origName), ast.emptyNode, ast.emptyNode) - addSon(result, params, pragmas, ast.emptyNode) # no exceptions - case p.tok.xkind - of pxSemicolon: - getTok(p) - addSon(result, ast.emptyNode) # nobody - if p.scopeCounter == 0: doImport(origName, pragmas, p) - of pxCurlyLe: - addSon(result, compoundStatement(p)) - else: - parMessage(p, errTokenExpected, ";") - if sonsLen(result.sons[pragmasPos]) == 0: - result.sons[pragmasPos] = ast.emptyNode - else: - result = parseVarDecl(p, baseTyp, rettyp, origName) - assert result != nil - -proc enumSpecifier(p: var TParser): PNode = - saveContext(p) - getTok(p, nil) # skip "enum" - case p.tok.xkind - of pxCurlyLe: - closeContext(p) - # make a const section out of it: - result = newNodeP(nkConstSection, p) - getTok(p, result) - var i = 0 - var hasUnknown = false - while true: - var name = skipIdentExport(p) - var val: PNode - if p.tok.xkind == pxAsgn: - getTok(p, name) - val = constantExpression(p) - if val.kind == nkIntLit: - i = int(val.intVal)+1 - hasUnknown = false - else: - hasUnknown = true - else: - if hasUnknown: - parMessage(p, warnUser, "computed const value may be wrong: " & - name.renderTree) - val = newIntNodeP(nkIntLit, i, p) - inc(i) - var c = createConst(name, ast.emptyNode, val, p) - addSon(result, c) - if p.tok.xkind != pxComma: break - getTok(p, c) - # allow trailing comma: - if p.tok.xkind == pxCurlyRi: break - eat(p, pxCurlyRi, result) - eat(p, pxSemicolon) - of pxSymbol: - var origName = p.tok.s - markTypeIdent(p, nil) - result = skipIdent(p) - case p.tok.xkind - of pxCurlyLe: - closeContext(p) - var name = result - # create a type section containing the enum - result = newNodeP(nkStmtList, p) - var tSection = newNodeP(nkTypeSection, p) - var t = newNodeP(nkTypeDef, p) - getTok(p, t) - var constSection = newNodeP(nkConstSection, p) - var e = enumFields(p, constSection) - addSon(t, exportSym(p, name, origName), ast.emptyNode, e) - addSon(tSection, t) - addSon(result, tSection) - addSon(result, constSection) - eat(p, pxCurlyRi, result) - eat(p, pxSemicolon) - of pxSemicolon: - # just ignore ``enum X;`` for now. - closeContext(p) - getTok(p, nil) - else: - backtrackContext(p) - result = declaration(p) - else: - closeContext(p) - parMessage(p, errTokenExpected, "{") - result = ast.emptyNode - -# Expressions - -proc setBaseFlags(n: PNode, base: TNumericalBase) = - case base - of base10: discard - of base2: incl(n.flags, nfBase2) - of base8: incl(n.flags, nfBase8) - of base16: incl(n.flags, nfBase16) - -proc startExpression(p : var TParser, tok : TToken) : PNode = - #echo "nud ", $tok - case tok.xkind: - of pxSymbol: - if tok.s == "NULL": - result = newNodeP(nkNilLit, p) - elif tok.s == "sizeof": - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("sizeof", p)) - saveContext(p) - try: - addSon(result, expression(p, 139)) - closeContext(p) - except ERetryParsing: - backtrackContext(p) - eat(p, pxParLe) - addSon(result, typeName(p)) - eat(p, pxParRi) - elif (tok.s == "new" or tok.s == "delete") and pfCpp in p.options.flags: - var opr = tok.s - result = newNodeP(nkCall, p) - if p.tok.xkind == pxBracketLe: - getTok(p) - eat(p, pxBracketRi) - opr.add("Array") - addSon(result, newIdentNodeP(opr, p)) - if p.tok.xkind == pxParLe: - getTok(p, result) - addSon(result, typeDesc(p)) - eat(p, pxParRi, result) - else: - addSon(result, expression(p, 139)) - else: - result = mangledIdent(tok.s, p) - result = optScope(p, result) - result = optAngle(p, result) - of pxIntLit: - result = newIntNodeP(nkIntLit, tok.iNumber, p) - setBaseFlags(result, tok.base) - of pxInt64Lit: - result = newIntNodeP(nkInt64Lit, tok.iNumber, p) - setBaseFlags(result, tok.base) - of pxFloatLit: - result = newFloatNodeP(nkFloatLit, tok.fNumber, p) - setBaseFlags(result, tok.base) - of pxStrLit: - result = newStrNodeP(nkStrLit, tok.s, p) - while p.tok.xkind == pxStrLit: - add(result.strVal, p.tok.s) - getTok(p, result) - of pxCharLit: - result = newIntNodeP(nkCharLit, ord(tok.s[0]), p) - of pxParLe: - try: - saveContext(p) - result = newNodeP(nkPar, p) - addSon(result, expression(p, 0)) - if p.tok.xkind != pxParRi: - raise newException(ERetryParsing, "expected a ')'") - getTok(p, result) - if p.tok.xkind in {pxSymbol, pxIntLit, pxFloatLit, pxStrLit, pxCharLit}: - raise newException(ERetryParsing, "expected a non literal token") - closeContext(p) - except ERetryParsing: - backtrackContext(p) - result = newNodeP(nkCast, p) - addSon(result, typeName(p)) - eat(p, pxParRi, result) - addSon(result, expression(p, 139)) - of pxPlusPlus: - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("inc", p)) - addSon(result, expression(p, 139)) - of pxMinusMinus: - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("dec", p)) - addSon(result, expression(p, 139)) - of pxAmp: - result = newNodeP(nkAddr, p) - addSon(result, expression(p, 139)) - of pxStar: - result = newNodeP(nkBracketExpr, p) - addSon(result, expression(p, 139)) - of pxPlus: - result = newNodeP(nkPrefix, p) - addSon(result, newIdentNodeP("+", p)) - addSon(result, expression(p, 139)) - of pxMinus: - result = newNodeP(nkPrefix, p) - addSon(result, newIdentNodeP("-", p)) - addSon(result, expression(p, 139)) - of pxTilde: - result = newNodeP(nkPrefix, p) - addSon(result, newIdentNodeP("not", p)) - addSon(result, expression(p, 139)) - of pxNot: - result = newNodeP(nkPrefix, p) - addSon(result, newIdentNodeP("not", p)) - addSon(result, expression(p, 139)) - else: - # probably from a failed sub expression attempt, try a type cast - raise newException(ERetryParsing, "did not expect " & $tok) - -proc leftBindingPower(p : var TParser, tok : ref TToken) : int = - #echo "lbp ", $tok[] - case tok.xkind: - of pxComma: - return 10 - # throw == 20 - of pxAsgn, pxPlusAsgn, pxMinusAsgn, pxStarAsgn, pxSlashAsgn, pxModAsgn, - pxShlAsgn, pxShrAsgn, pxAmpAsgn, pxHatAsgn, pxBarAsgn: - return 30 - of pxConditional: - return 40 - of pxBarBar: - return 50 - of pxAmpAmp: - return 60 - of pxBar: - return 70 - of pxHat: - return 80 - of pxAmp: - return 90 - of pxEquals, pxNeq: - return 100 - of pxLt, pxLe, pxGt, pxGe: - return 110 - of pxShl, pxShr: - return 120 - of pxPlus, pxMinus: - return 130 - of pxStar, pxSlash, pxMod: - return 140 - # .* ->* == 150 - of pxPlusPlus, pxMinusMinus, pxParLe, pxDot, pxArrow, pxBracketLe: - return 160 - # :: == 170 - else: - return 0 - -proc buildStmtList(a: PNode): PNode - -proc leftExpression(p : var TParser, tok : TToken, left : PNode) : PNode = - #echo "led ", $tok - case tok.xkind: - of pxComma: # 10 - # not supported as an expression, turns into a statement list - result = buildStmtList(left) - addSon(result, expression(p, 0)) - # throw == 20 - of pxAsgn: # 30 - result = newNodeP(nkAsgn, p) - addSon(result, left, expression(p, 29)) - of pxPlusAsgn: # 30 - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP(getIdent("inc"), p), left, expression(p, 29)) - of pxMinusAsgn: # 30 - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP(getIdent("dec"), p), left, expression(p, 29)) - of pxStarAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("*", copyTree(left), right, p)) - of pxSlashAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("/", copyTree(left), right, p)) - of pxModAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("mod", copyTree(left), right, p)) - of pxShlAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("shl", copyTree(left), right, p)) - of pxShrAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("shr", copyTree(left), right, p)) - of pxAmpAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("and", copyTree(left), right, p)) - of pxHatAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("xor", copyTree(left), right, p)) - of pxBarAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("or", copyTree(left), right, p)) - of pxConditional: # 40 - var a = expression(p, 0) - eat(p, pxColon, a) - var b = expression(p, 39) - result = newNodeP(nkIfExpr, p) - var branch = newNodeP(nkElifExpr, p) - addSon(branch, left, a) - addSon(result, branch) - branch = newNodeP(nkElseExpr, p) - addSon(branch, b) - addSon(result, branch) - of pxBarBar: # 50 - result = newBinary("or", left, expression(p, 50), p) - of pxAmpAmp: # 60 - result = newBinary("and", left, expression(p, 60), p) - of pxBar: # 70 - result = newBinary("or", left, expression(p, 70), p) - of pxHat: # 80 - result = newBinary("^", left, expression(p, 80), p) - of pxAmp: # 90 - result = newBinary("and", left, expression(p, 90), p) - of pxEquals: # 100 - result = newBinary("==", left, expression(p, 100), p) - of pxNeq: # 100 - result = newBinary("!=", left, expression(p, 100), p) - of pxLt: # 110 - result = newBinary("<", left, expression(p, 110), p) - of pxLe: # 110 - result = newBinary("<=", left, expression(p, 110), p) - of pxGt: # 110 - result = newBinary(">", left, expression(p, 110), p) - of pxGe: # 110 - result = newBinary(">=", left, expression(p, 110), p) - of pxShl: # 120 - result = newBinary("shl", left, expression(p, 120), p) - of pxShr: # 120 - result = newBinary("shr", left, expression(p, 120), p) - of pxPlus: # 130 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("+", p), left) - addSon(result, expression(p, 130)) - of pxMinus: # 130 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("+", p), left) - addSon(result, expression(p, 130)) - of pxStar: # 140 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("*", p), left) - addSon(result, expression(p, 140)) - of pxSlash: # 140 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("div", p), left) - addSon(result, expression(p, 140)) - of pxMod: # 140 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("mod", p), left) - addSon(result, expression(p, 140)) - # .* ->* == 150 - of pxPlusPlus: # 160 - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("inc", p), left) - of pxMinusMinus: # 160 - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("dec", p), left) - of pxParLe: # 160 - result = newNodeP(nkCall, p) - addSon(result, left) - while p.tok.xkind != pxParRi: - var a = expression(p, 29) - addSon(result, a) - while p.tok.xkind == pxComma: - getTok(p, a) - a = expression(p, 29) - addSon(result, a) - eat(p, pxParRi, result) - of pxDot: # 160 - result = newNodeP(nkDotExpr, p) - addSon(result, left) - addSon(result, skipIdent(p)) - of pxArrow: # 160 - result = newNodeP(nkDotExpr, p) - addSon(result, left) - addSon(result, skipIdent(p)) - of pxBracketLe: # 160 - result = newNodeP(nkBracketExpr, p) - addSon(result, left, expression(p)) - eat(p, pxBracketRi, result) - # :: == 170 - else: - result = left - -proc expression*(p : var TParser, rbp : int = 0) : PNode = - var tok : TToken - - tok = p.tok[] - getTok(p, result) - - result = startExpression(p, tok) - - while rbp < leftBindingPower(p, p.tok): - tok = p.tok[] - getTok(p, result) - result = leftExpression(p, tok, result) - -# Statements - -proc buildStmtList(a: PNode): PNode = - if a.kind == nkStmtList: result = a - else: - result = newNodeI(nkStmtList, a.info) - addSon(result, a) - -proc nestedStatement(p: var TParser): PNode = - # careful: We need to translate: - # if (x) if (y) stmt; - # into: - # if x: - # if x: - # stmt - # - # Nimrod requires complex statements to be nested in whitespace! - const - complexStmt = {nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, - nkTemplateDef, nkIteratorDef, nkIfStmt, - nkWhenStmt, nkForStmt, nkWhileStmt, nkCaseStmt, nkVarSection, - nkConstSection, nkTypeSection, nkTryStmt, nkBlockStmt, nkStmtList, - nkCommentStmt, nkStmtListExpr, nkBlockExpr, nkStmtListType, nkBlockType} - result = statement(p) - if result.kind in complexStmt: - result = buildStmtList(result) - -proc expressionStatement(p: var TParser): PNode = - # do not skip the comment after a semicolon to make a new nkCommentStmt - if p.tok.xkind == pxSemicolon: - getTok(p) - result = ast.emptyNode - else: - result = expression(p) - if p.tok.xkind == pxSemicolon: getTok(p) - else: parMessage(p, errTokenExpected, ";") - assert result != nil - -proc parseIf(p: var TParser): PNode = - # we parse additional "else if"s too here for better Nimrod code - result = newNodeP(nkIfStmt, p) - while true: - getTok(p) # skip ``if`` - var branch = newNodeP(nkElifBranch, p) - eat(p, pxParLe, branch) - addSon(branch, expression(p)) - eat(p, pxParRi, branch) - addSon(branch, nestedStatement(p)) - addSon(result, branch) - skipCom(p, branch) - if p.tok.s == "else": - getTok(p, result) - if p.tok.s != "if": - # ordinary else part: - branch = newNodeP(nkElse, p) - addSon(branch, nestedStatement(p)) - addSon(result, branch) - break - else: - break - -proc parseWhile(p: var TParser): PNode = - result = newNodeP(nkWhileStmt, p) - getTok(p, result) - eat(p, pxParLe, result) - addSon(result, expression(p)) - eat(p, pxParRi, result) - addSon(result, nestedStatement(p)) - -proc embedStmts(sl, a: PNode) - -proc parseDoWhile(p: var TParser): PNode = - # parsing - result = newNodeP(nkWhileStmt, p) - getTok(p, result) - var stm = nestedStatement(p) - eat(p, "while", result) - eat(p, pxParLe, result) - var exp = expression(p) - eat(p, pxParRi, result) - if p.tok.xkind == pxSemicolon: getTok(p) - - # while true: - # stmt - # if not expr: - # break - addSon(result, newIdentNodeP("true", p)) - - stm = buildStmtList(stm) - - # get the last exp if it is a stmtlist - var cleanedExp = exp - if exp.kind == nkStmtList: - cleanedExp = exp.sons[exp.len-1] - exp.sons = exp.sons[0..exp.len-2] - embedStmts(stm, exp) - - var notExp = newNodeP(nkPrefix, p) - addSon(notExp, newIdentNodeP("not", p)) - addSon(notExp, cleanedExp) - - var brkStm = newNodeP(nkBreakStmt, p) - addSon(brkStm, ast.emptyNode) - - var ifStm = newNodeP(nkIfStmt, p) - var ifBranch = newNodeP(nkElifBranch, p) - addSon(ifBranch, notExp) - addSon(ifBranch, brkStm) - addSon(ifStm, ifBranch) - - embedStmts(stm, ifStm) - - addSon(result, stm) - -proc declarationOrStatement(p: var TParser): PNode = - if p.tok.xkind != pxSymbol: - result = expressionStatement(p) - elif declKeyword(p, p.tok.s): - result = declaration(p) - else: - # ordinary identifier: - saveContext(p) - getTok(p) # skip identifier to look ahead - case p.tok.xkind - of pxSymbol, pxStar, pxLt, pxAmp, pxAmpAmp: - # we parse - # a b - # a * b - # always as declarations! This is of course not correct, but good - # enough for most real world C code out there. - backtrackContext(p) - result = declaration(p) - of pxColon: - # it is only a label: - closeContext(p) - getTok(p) - result = statement(p) - else: - backtrackContext(p) - result = expressionStatement(p) - assert result != nil - -proc parseTuple(p: var TParser, statements: PNode, isUnion: bool): PNode = - parseStructBody(p, statements, isUnion, nkTupleTy) - -proc parseTrailingDefinedIdents(p: var TParser, result, baseTyp: PNode) = - var varSection = newNodeP(nkVarSection, p) - while p.tok.xkind notin {pxEof, pxSemicolon}: - var t = pointer(p, baseTyp) - expectIdent(p) - var def = newNodeP(nkIdentDefs, p) - addSon(def, varIdent(p.tok.s, p)) - getTok(p, def) - addSon(def, parseTypeSuffix(p, t)) - addInitializer(p, def) - addSon(varSection, def) - if p.tok.xkind != pxComma: break - getTok(p, def) - eat(p, pxSemicolon) - if sonsLen(varSection) > 0: - addSon(result, varSection) - -proc parseStandaloneStruct(p: var TParser, isUnion: bool): PNode = - result = newNodeP(nkStmtList, p) - saveContext(p) - getTok(p, result) # skip "struct" or "union" - var origName = "" - if p.tok.xkind == pxSymbol: - markTypeIdent(p, nil) - origName = p.tok.s - getTok(p, result) - if p.tok.xkind in {pxCurlyLe, pxSemiColon}: - if origName.len > 0: - var name = mangledIdent(origName, p) - var t = parseStruct(p, result, isUnion) - var typeSection = newNodeP(nkTypeSection, p) - addTypeDef(typeSection, structPragmas(p, name, origName), t) - addSon(result, typeSection) - parseTrailingDefinedIdents(p, result, name) - else: - var t = parseTuple(p, result, isUnion) - parseTrailingDefinedIdents(p, result, t) - else: - backtrackContext(p) - result = declaration(p) - -proc parseFor(p: var TParser, result: PNode) = - # 'for' '(' expression_statement expression_statement expression? ')' - # statement - getTok(p, result) - eat(p, pxParLe, result) - var initStmt = declarationOrStatement(p) - if initStmt.kind != nkEmpty: - embedStmts(result, initStmt) - var w = newNodeP(nkWhileStmt, p) - var condition = expressionStatement(p) - if condition.kind == nkEmpty: condition = newIdentNodeP("true", p) - addSon(w, condition) - var step = if p.tok.xkind != pxParRi: expression(p) else: ast.emptyNode - eat(p, pxParRi, step) - var loopBody = nestedStatement(p) - if step.kind != nkEmpty: - loopBody = buildStmtList(loopBody) - embedStmts(loopBody, step) - addSon(w, loopBody) - addSon(result, w) - -proc switchStatement(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - while true: - if p.tok.xkind in {pxEof, pxCurlyRi}: break - case p.tok.s - of "break": - getTok(p, result) - eat(p, pxSemicolon, result) - break - of "return", "continue", "goto": - addSon(result, statement(p)) - break - of "case", "default": - break - else: discard - addSon(result, statement(p)) - if sonsLen(result) == 0: - # translate empty statement list to Nimrod's ``nil`` statement - result = newNodeP(nkNilLit, p) - -proc rangeExpression(p: var TParser): PNode = - # We support GCC's extension: ``case expr...expr:`` - result = constantExpression(p) - if p.tok.xkind == pxDotDotDot: - getTok(p, result) - var a = result - var b = constantExpression(p) - result = newNodeP(nkRange, p) - addSon(result, a) - addSon(result, b) - -proc parseSwitch(p: var TParser): PNode = - # We cannot support Duff's device or C's crazy switch syntax. We just support - # sane usages of switch. ;-) - result = newNodeP(nkCaseStmt, p) - getTok(p, result) - eat(p, pxParLe, result) - addSon(result, expression(p)) - eat(p, pxParRi, result) - eat(p, pxCurlyLe, result) - var b: PNode - while (p.tok.xkind != pxCurlyRi) and (p.tok.xkind != pxEof): - case p.tok.s - of "default": - b = newNodeP(nkElse, p) - getTok(p, b) - eat(p, pxColon, b) - of "case": - b = newNodeP(nkOfBranch, p) - while p.tok.xkind == pxSymbol and p.tok.s == "case": - getTok(p, b) - addSon(b, rangeExpression(p)) - eat(p, pxColon, b) - else: - parMessage(p, errXExpected, "case") - addSon(b, switchStatement(p)) - addSon(result, b) - if b.kind == nkElse: break - eat(p, pxCurlyRi) - -proc addStmt(sl, a: PNode) = - # merge type sections if possible: - if a.kind != nkTypeSection or sonsLen(sl) == 0 or - lastSon(sl).kind != nkTypeSection: - addSon(sl, a) - else: - var ts = lastSon(sl) - for i in 0..sonsLen(a)-1: addSon(ts, a.sons[i]) - -proc embedStmts(sl, a: PNode) = - if a.kind != nkStmtList: - addStmt(sl, a) - else: - for i in 0..sonsLen(a)-1: - if a[i].kind != nkEmpty: addStmt(sl, a[i]) - -proc compoundStatement(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - eat(p, pxCurlyLe) - inc(p.scopeCounter) - while p.tok.xkind notin {pxEof, pxCurlyRi}: - var a = statement(p) - if a.kind == nkEmpty: break - embedStmts(result, a) - if sonsLen(result) == 0: - # translate ``{}`` to Nimrod's ``discard`` statement - result = newNodeP(nkDiscardStmt, p) - result.add(ast.emptyNode) - dec(p.scopeCounter) - eat(p, pxCurlyRi) - -proc skipInheritKeyw(p: var TParser) = - if p.tok.xkind == pxSymbol and (p.tok.s == "private" or - p.tok.s == "protected" or - p.tok.s == "public"): - getTok(p) - -proc parseConstructor(p: var TParser, pragmas: PNode, - isDestructor=false): PNode = - var origName = p.tok.s - getTok(p) - - result = newNodeP(nkProcDef, p) - var rettyp = if isDestructor: newNodeP(nkNilLit, p) - else: mangledIdent(origName, p) - - let oname = if isDestructor: "destroy" & origName - else: "construct" & origName - var name = mangledIdent(oname, p) - var params = newNodeP(nkFormalParams, p) - addReturnType(params, rettyp) - if p.tok.xkind == pxParLe: - parseFormalParams(p, params, pragmas) - if p.tok.xkind == pxSymbol and p.tok.s == "const": - addSon(pragmas, newIdentNodeP("noSideEffect", p)) - if pfCDecl in p.options.flags: - addSon(pragmas, newIdentNodeP("cdecl", p)) - elif pfStdcall in p.options.flags: - addSon(pragmas, newIdentNodeP("stdcall", p)) - if p.tok.xkind == pxColon: - # skip initializer list: - while true: - getTok(p) - discard expression(p) - if p.tok.xkind != pxComma: break - # no pattern, no exceptions: - addSon(result, exportSym(p, name, origName), ast.emptyNode, ast.emptyNode) - addSon(result, params, pragmas, ast.emptyNode) # no exceptions - addSon(result, ast.emptyNode) # no body - case p.tok.xkind - of pxSemicolon: getTok(p) - of pxCurlyLe: - let body = compoundStatement(p) - if pfKeepBodies in p.options.flags: - result.sons[bodyPos] = body - else: - parMessage(p, errTokenExpected, ";") - if result.sons[bodyPos].kind == nkEmpty: - doImport((if isDestructor: "~" else: "") & origName, pragmas, p) - elif isDestructor: - addSon(pragmas, newIdentNodeP("destructor", p)) - if sonsLen(result.sons[pragmasPos]) == 0: - result.sons[pragmasPos] = ast.emptyNode - -proc parseMethod(p: var TParser, origName: string, rettyp, pragmas: PNode, - isStatic: bool): PNode = - result = newNodeP(nkProcDef, p) - var params = newNodeP(nkFormalParams, p) - addReturnType(params, rettyp) - var thisDef = newNodeP(nkIdentDefs, p) - if not isStatic: - # declare 'this': - var t = newNodeP(nkVarTy, p) - t.add(p.currentClass) - addSon(thisDef, newIdentNodeP("this", p), t, ast.emptyNode) - params.add(thisDef) - parseFormalParams(p, params, pragmas) - if p.tok.xkind == pxSymbol and p.tok.s == "const": - addSon(pragmas, newIdentNodeP("noSideEffect", p)) - getTok(p, result) - if not isStatic: - # fix the type of the 'this' parameter: - thisDef.sons[1] = thisDef.sons[1].sons[0] - if pfCDecl in p.options.flags: - addSon(pragmas, newIdentNodeP("cdecl", p)) - elif pfStdcall in p.options.flags: - addSon(pragmas, newIdentNodeP("stdcall", p)) - # no pattern, no exceptions: - let methodName = newIdentNodeP(origName, p) - addSon(result, exportSym(p, methodName, origName), - ast.emptyNode, ast.emptyNode) - addSon(result, params, pragmas, ast.emptyNode) # no exceptions - addSon(result, ast.emptyNode) # no body - case p.tok.xkind - of pxSemicolon: getTok(p) - of pxCurlyLe: - let body = compoundStatement(p) - if pfKeepBodies in p.options.flags: - result.sons[bodyPos] = body - else: - parMessage(p, errTokenExpected, ";") - if result.sons[bodyPos].kind == nkEmpty: - if isStatic: doImport(origName, pragmas, p) - else: doImportCpp(origName, pragmas, p) - if sonsLen(result.sons[pragmasPos]) == 0: - result.sons[pragmasPos] = ast.emptyNode - -proc parseStandaloneClass(p: var TParser, isStruct: bool): PNode - -proc followedByParLe(p: var TParser): bool = - saveContext(p) - getTok(p) # skip Identifier - result = p.tok.xkind == pxParLe - backtrackContext(p) - -proc parseOperator(p: var TParser, origName: var string): bool = - getTok(p) # skip 'operator' keyword - case p.tok.xkind - of pxAmp..pxArrow: - # ordinary operator symbol: - origName.add(tokKindToStr(p.tok.xkind)) - getTok(p) - of pxSymbol: - if p.tok.s == "new" or p.tok.s == "delete": - origName.add(p.tok.s) - getTok(p) - if p.tok.xkind == pxBracketLe: - getTok(p) - eat(p, pxBracketRi) - origName.add("[]") - else: - # type converter - let x = typeAtom(p) - if x.kind == nkIdent: - origName.add(x.ident.s) - else: - parMessage(p, errGenerated, "operator symbol expected") - result = true - of pxParLe: - getTok(p) - eat(p, pxParRi) - origName.add("()") - of pxBracketLe: - getTok(p) - eat(p, pxBracketRi) - origName.add("[]") - else: - parMessage(p, errGenerated, "operator symbol expected") - -proc parseClass(p: var TParser; isStruct: bool; stmtList: PNode): PNode = - result = newNodeP(nkObjectTy, p) - addSon(result, ast.emptyNode, ast.emptyNode) # no pragmas, no inheritance - - var recList = newNodeP(nkRecList, p) - addSon(result, recList) - if p.tok.xkind == pxColon: - getTok(p, result) - skipInheritKeyw(p) - var baseTyp = typeAtom(p) - var inh = newNodeP(nkOfInherit, p) - inh.add(baseTyp) - if p.tok.xkind == pxComma: - parMessage(p, errGenerated, "multiple inheritance is not supported") - while p.tok.xkind == pxComma: - getTok(p) - skipInheritKeyw(p) - discard typeAtom(p) - result.sons[0] = inh - - eat(p, pxCurlyLe, result) - var private = not isStruct - var pragmas = newNodeP(nkPragma, p) - while p.tok.xkind notin {pxEof, pxCurlyRi}: - skipCom(p, stmtList) - if p.tok.xkind == pxSymbol and (p.tok.s == "private" or - p.tok.s == "protected"): - getTok(p, result) - eat(p, pxColon, result) - private = true - elif p.tok.xkind == pxSymbol and p.tok.s == "public": - getTok(p, result) - eat(p, pxColon, result) - private = false - if p.tok.xkind == pxSymbol and (p.tok.s == "friend" or p.tok.s == "using"): - # we skip friend declarations: - while p.tok.xkind notin {pxEof, pxSemicolon}: getTok(p) - eat(p, pxSemicolon) - elif p.tok.xkind == pxSymbol and p.tok.s == "enum": - let x = enumSpecifier(p) - if not private or pfKeepBodies in p.options.flags: stmtList.add(x) - elif p.tok.xkind == pxSymbol and p.tok.s == "typedef": - let x = parseTypeDef(p) - if not private or pfKeepBodies in p.options.flags: stmtList.add(x) - elif p.tok.xkind == pxSymbol and(p.tok.s == "struct" or p.tok.s == "class"): - let x = parseStandaloneClass(p, isStruct=p.tok.s == "struct") - if not private or pfKeepBodies in p.options.flags: stmtList.add(x) - elif p.tok.xkind == pxSymbol and p.tok.s == "union": - let x = parseStandaloneStruct(p, isUnion=true) - if not private or pfKeepBodies in p.options.flags: stmtList.add(x) - else: - if pragmas.len != 0: pragmas = newNodeP(nkPragma, p) - parseCallConv(p, pragmas) - var isStatic = false - if p.tok.xkind == pxSymbol and p.tok.s == "virtual": - getTok(p, stmtList) - if p.tok.xkind == pxSymbol and p.tok.s == "explicit": - getTok(p, stmtList) - if p.tok.xkind == pxSymbol and p.tok.s == "static": - getTok(p, stmtList) - isStatic = true - parseCallConv(p, pragmas) - if p.tok.xkind == pxSymbol and p.tok.s == p.currentClass.ident.s and - followedByParLe(p): - # constructor - let cons = parseConstructor(p, pragmas) - if not private or pfKeepBodies in p.options.flags: stmtList.add(cons) - elif p.tok.xkind == pxTilde: - # destructor - getTok(p, stmtList) - if p.tok.xkind == pxSymbol and p.tok.s == p.currentClass.ident.s: - let des = parseConstructor(p, pragmas, isDestructor=true) - if not private or pfKeepBodies in p.options.flags: stmtList.add(des) - else: - parMessage(p, errGenerated, "invalid destructor") - else: - # field declaration or method: - var baseTyp = typeAtom(p) - while true: - var def = newNodeP(nkIdentDefs, p) - var t = pointer(p, baseTyp) - let canBeMethod = p.tok.xkind != pxParLe - var origName: string - if p.tok.xkind == pxSymbol: - origName = p.tok.s - if p.tok.s == "operator": - var isConverter = parseOperator(p, origName) - let meth = parseMethod(p, origName, t, pragmas, isStatic) - if not private or pfKeepBodies in p.options.flags: - if isConverter: meth.kind = nkConverterDef - stmtList.add(meth) - break - var i = parseField(p, nkRecList) - if canBeMethod and p.tok.xkind == pxParLe: - let meth = parseMethod(p, origName, t, pragmas, isStatic) - if not private or pfKeepBodies in p.options.flags: - stmtList.add(meth) - else: - t = parseTypeSuffix(p, t) - addSon(def, i, t, ast.emptyNode) - if not isStatic: addSon(recList, def) - if p.tok.xkind != pxComma: break - getTok(p, def) - if p.tok.xkind == pxSemicolon: - getTok(p, lastSon(recList)) - eat(p, pxCurlyRi, result) - -proc parseStandaloneClass(p: var TParser, isStruct: bool): PNode = - result = newNodeP(nkStmtList, p) - saveContext(p) - getTok(p, result) # skip "class" or "struct" - var origName = "" - let oldClass = p.currentClass - if p.tok.xkind == pxSymbol: - markTypeIdent(p, nil) - origName = p.tok.s - getTok(p, result) - p.currentClass = mangledIdent(origName, p) - else: - p.currentClass = nil - if p.tok.xkind in {pxCurlyLe, pxSemiColon, pxColon}: - if origName.len > 0: - p.options.classes[origName] = "true" - - var typeSection = newNodeP(nkTypeSection, p) - addSon(result, typeSection) - - var name = mangledIdent(origName, p) - var t = parseClass(p, isStruct, result) - addTypeDef(typeSection, structPragmas(p, name, origName), t) - parseTrailingDefinedIdents(p, result, name) - else: - var t = parseTuple(p, result, isUnion=false) - parseTrailingDefinedIdents(p, result, t) - else: - backtrackContext(p) - result = declaration(p) - p.currentClass = oldClass - -proc unwrap(a: PNode): PNode = - if a.kind == nkPar: - return a.sons[0] - return a - -include cpp - -proc statement(p: var TParser): PNode = - case p.tok.xkind - of pxSymbol: - case p.tok.s - of "if": result = parseIf(p) - of "switch": result = parseSwitch(p) - of "while": result = parseWhile(p) - of "do": result = parseDoWhile(p) - of "for": - result = newNodeP(nkStmtList, p) - parseFor(p, result) - of "goto": - # we cannot support "goto"; in hand-written C, "goto" is most often used - # to break a block, so we convert it to a break statement with label. - result = newNodeP(nkBreakStmt, p) - getTok(p) - addSon(result, skipIdent(p)) - eat(p, pxSemicolon) - of "continue": - result = newNodeP(nkContinueStmt, p) - getTok(p) - eat(p, pxSemicolon) - addSon(result, ast.emptyNode) - of "break": - result = newNodeP(nkBreakStmt, p) - getTok(p) - eat(p, pxSemicolon) - addSon(result, ast.emptyNode) - of "return": - result = newNodeP(nkReturnStmt, p) - getTok(p) - if p.tok.xkind == pxSemicolon: - addSon(result, ast.emptyNode) - else: - addSon(result, unwrap(expression(p))) - eat(p, pxSemicolon) - of "enum": result = enumSpecifier(p) - of "typedef": result = parseTypeDef(p) - of "union": result = parseStandaloneStruct(p, isUnion=true) - of "struct": - if pfCpp in p.options.flags: - result = parseStandaloneClass(p, isStruct=true) - else: - result = parseStandaloneStruct(p, isUnion=false) - of "class": - if pfCpp in p.options.flags: - result = parseStandaloneClass(p, isStruct=false) - else: - result = declarationOrStatement(p) - of "namespace": - if pfCpp in p.options.flags: - while p.tok.xkind notin {pxEof, pxCurlyLe}: getTok(p) - result = compoundStatement(p) - else: - result = declarationOrStatement(p) - of "using": - if pfCpp in p.options.flags: - while p.tok.xkind notin {pxEof, pxSemicolon}: getTok(p) - eat(p, pxSemicolon) - result = newNodeP(nkNilLit, p) - else: - result = declarationOrStatement(p) - else: result = declarationOrStatement(p) - of pxCurlyLe: - result = compoundStatement(p) - of pxDirective, pxDirectiveParLe: - result = parseDir(p) - of pxLineComment, pxStarComment: - result = newNodeP(nkCommentStmt, p) - skipCom(p, result) - of pxSemicolon: - # empty statement: - getTok(p) - if p.tok.xkind in {pxLineComment, pxStarComment}: - result = newNodeP(nkCommentStmt, p) - skipCom(p, result) - else: - result = newNodeP(nkNilLit, p) - else: - result = expressionStatement(p) - assert result != nil - -proc parseUnit(p: var TParser): PNode = - try: - result = newNodeP(nkStmtList, p) - getTok(p) # read first token - while p.tok.xkind != pxEof: - var s = statement(p) - if s.kind != nkEmpty: embedStmts(result, s) - except ERetryParsing: - parMessage(p, errGenerated, "Uncaught parsing exception raised") - diff --git a/compiler/c2nim/cpp.nim b/compiler/c2nim/cpp.nim deleted file mode 100644 index 84b4c4dfb..000000000 --- a/compiler/c2nim/cpp.nim +++ /dev/null @@ -1,347 +0,0 @@ -# -# -# c2nim - C to Nimrod source converter -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# Preprocessor support - -const - c2nimSymbol = "C2NIM" - -proc eatNewLine(p: var TParser, n: PNode) = - if p.tok.xkind == pxLineComment: - skipCom(p, n) - if p.tok.xkind == pxNewLine: getTok(p) - elif p.tok.xkind == pxNewLine: - eat(p, pxNewLine) - -proc skipLine(p: var TParser) = - while p.tok.xkind notin {pxEof, pxNewLine, pxLineComment}: getTok(p) - eatNewLine(p, nil) - -proc parseDefineBody(p: var TParser, tmplDef: PNode): string = - if p.tok.xkind == pxCurlyLe or - (p.tok.xkind == pxSymbol and ( - declKeyword(p, p.tok.s) or stmtKeyword(p.tok.s))): - addSon(tmplDef, statement(p)) - result = "stmt" - elif p.tok.xkind in {pxLineComment, pxNewLine}: - addSon(tmplDef, buildStmtList(newNodeP(nkNilLit, p))) - result = "stmt" - else: - addSon(tmplDef, buildStmtList(expression(p))) - result = "expr" - -proc parseDefine(p: var TParser): PNode = - if p.tok.xkind == pxDirectiveParLe: - # a macro with parameters: - result = newNodeP(nkTemplateDef, p) - getTok(p) - addSon(result, skipIdentExport(p)) - addSon(result, ast.emptyNode) - eat(p, pxParLe) - var params = newNodeP(nkFormalParams, p) - # return type; not known yet: - addSon(params, ast.emptyNode) - if p.tok.xkind != pxParRi: - var identDefs = newNodeP(nkIdentDefs, p) - while p.tok.xkind != pxParRi: - addSon(identDefs, skipIdent(p)) - skipStarCom(p, nil) - if p.tok.xkind != pxComma: break - getTok(p) - addSon(identDefs, newIdentNodeP("expr", p)) - addSon(identDefs, ast.emptyNode) - addSon(params, identDefs) - eat(p, pxParRi) - - addSon(result, ast.emptyNode) # no generic parameters - addSon(result, params) - addSon(result, ast.emptyNode) # no pragmas - addSon(result, ast.emptyNode) - var kind = parseDefineBody(p, result) - params.sons[0] = newIdentNodeP(kind, p) - eatNewLine(p, result) - else: - # a macro without parameters: - result = newNodeP(nkConstSection, p) - while p.tok.xkind == pxDirective and p.tok.s == "define": - getTok(p) # skip #define - var c = newNodeP(nkConstDef, p) - addSon(c, skipIdentExport(p)) - addSon(c, ast.emptyNode) - skipStarCom(p, c) - if p.tok.xkind in {pxLineComment, pxNewLine, pxEof}: - addSon(c, newIdentNodeP("true", p)) - else: - addSon(c, expression(p)) - addSon(result, c) - eatNewLine(p, c) - assert result != nil - -proc parseDefBody(p: var TParser, m: var TMacro, params: seq[string]) = - m.body = @[] - # A little hack: We safe the context, so that every following token will be - # put into a newly allocated TToken object. Thus we can just save a - # reference to the token in the macro's body. - saveContext(p) - while p.tok.xkind notin {pxEof, pxNewLine, pxLineComment}: - case p.tok.xkind - of pxSymbol: - # is it a parameter reference? - var tok = p.tok - for i in 0..high(params): - if params[i] == p.tok.s: - new(tok) - tok.xkind = pxMacroParam - tok.iNumber = i - break - m.body.add(tok) - of pxDirConc: - # just ignore this token: this implements token merging correctly - discard - else: - m.body.add(p.tok) - # we do not want macro expansion here: - rawGetTok(p) - eatNewLine(p, nil) - closeContext(p) - # newline token might be overwritten, but this is not - # part of the macro body, so it is safe. - -proc parseDef(p: var TParser, m: var TMacro) = - var hasParams = p.tok.xkind == pxDirectiveParLe - getTok(p) - expectIdent(p) - m.name = p.tok.s - getTok(p) - var params: seq[string] = @[] - # parse parameters: - if hasParams: - eat(p, pxParLe) - while p.tok.xkind != pxParRi: - expectIdent(p) - params.add(p.tok.s) - getTok(p) - skipStarCom(p, nil) - if p.tok.xkind != pxComma: break - getTok(p) - eat(p, pxParRi) - m.params = params.len - parseDefBody(p, m, params) - -proc isDir(p: TParser, dir: string): bool = - result = p.tok.xkind in {pxDirectiveParLe, pxDirective} and p.tok.s == dir - -proc parseInclude(p: var TParser): PNode = - result = newNodeP(nkImportStmt, p) - while isDir(p, "include"): - getTok(p) # skip "include" - if p.tok.xkind == pxStrLit and pfSkipInclude notin p.options.flags: - var file = newStrNodeP(nkStrLit, changeFileExt(p.tok.s, ""), p) - addSon(result, file) - getTok(p) - skipStarCom(p, file) - eatNewLine(p, nil) - else: - skipLine(p) - if sonsLen(result) == 0: - # we only parsed includes that we chose to ignore: - result = ast.emptyNode - -proc definedExprAux(p: var TParser): PNode = - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("defined", p)) - addSon(result, skipIdent(p)) - -proc parseStmtList(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - while true: - case p.tok.xkind - of pxEof: break - of pxDirectiveParLe, pxDirective: - case p.tok.s - of "else", "endif", "elif": break - else: discard - addSon(result, statement(p)) - -proc eatEndif(p: var TParser) = - if isDir(p, "endif"): - skipLine(p) - else: - parMessage(p, errXExpected, "#endif") - -proc parseIfDirAux(p: var TParser, result: PNode) = - addSon(result.sons[0], parseStmtList(p)) - while isDir(p, "elif"): - var b = newNodeP(nkElifBranch, p) - getTok(p) - addSon(b, expression(p)) - eatNewLine(p, nil) - addSon(b, parseStmtList(p)) - addSon(result, b) - if isDir(p, "else"): - var s = newNodeP(nkElse, p) - skipLine(p) - addSon(s, parseStmtList(p)) - addSon(result, s) - eatEndif(p) - -proc skipUntilEndif(p: var TParser) = - var nested = 1 - while p.tok.xkind != pxEof: - if isDir(p, "ifdef") or isDir(p, "ifndef") or isDir(p, "if"): - inc(nested) - elif isDir(p, "endif"): - dec(nested) - if nested <= 0: - skipLine(p) - return - getTok(p) - parMessage(p, errXExpected, "#endif") - -type - TEndifMarker = enum - emElif, emElse, emEndif - -proc skipUntilElifElseEndif(p: var TParser): TEndifMarker = - var nested = 1 - while p.tok.xkind != pxEof: - if isDir(p, "ifdef") or isDir(p, "ifndef") or isDir(p, "if"): - inc(nested) - elif isDir(p, "elif") and nested <= 1: - return emElif - elif isDir(p, "else") and nested <= 1: - return emElse - elif isDir(p, "endif"): - dec(nested) - if nested <= 0: - return emEndif - getTok(p) - parMessage(p, errXExpected, "#endif") - -proc parseIfdef(p: var TParser): PNode = - getTok(p) # skip #ifdef - expectIdent(p) - case p.tok.s - of "__cplusplus": - skipUntilEndif(p) - result = ast.emptyNode - of c2nimSymbol: - skipLine(p) - result = parseStmtList(p) - skipUntilEndif(p) - else: - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - addSon(result.sons[0], definedExprAux(p)) - eatNewLine(p, nil) - parseIfDirAux(p, result) - -proc parseIfndef(p: var TParser): PNode = - result = ast.emptyNode - getTok(p) # skip #ifndef - expectIdent(p) - if p.tok.s == c2nimSymbol: - skipLine(p) - case skipUntilElifElseEndif(p) - of emElif: - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - addSon(result.sons[0], expression(p)) - eatNewLine(p, nil) - parseIfDirAux(p, result) - of emElse: - skipLine(p) - result = parseStmtList(p) - eatEndif(p) - of emEndif: skipLine(p) - else: - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - var e = newNodeP(nkCall, p) - addSon(e, newIdentNodeP("not", p)) - addSon(e, definedExprAux(p)) - eatNewLine(p, nil) - addSon(result.sons[0], e) - parseIfDirAux(p, result) - -proc parseIfDir(p: var TParser): PNode = - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - addSon(result.sons[0], expression(p)) - eatNewLine(p, nil) - parseIfDirAux(p, result) - -proc parsePegLit(p: var TParser): TPeg = - var col = getColumn(p.lex) + 2 - getTok(p) - if p.tok.xkind != pxStrLit: expectIdent(p) - try: - result = parsePeg( - pattern = if p.tok.xkind == pxStrLit: p.tok.s else: escapePeg(p.tok.s), - filename = p.lex.fileIdx.toFilename, - line = p.lex.linenumber, - col = col) - getTok(p) - except EInvalidPeg: - parMessage(p, errUser, getCurrentExceptionMsg()) - -proc parseMangleDir(p: var TParser) = - var pattern = parsePegLit(p) - if p.tok.xkind != pxStrLit: expectIdent(p) - p.options.mangleRules.add((pattern, p.tok.s)) - getTok(p) - eatNewLine(p, nil) - -proc modulePragmas(p: var TParser): PNode = - if p.options.dynlibSym.len > 0 and not p.hasDeadCodeElimPragma: - p.hasDeadCodeElimPragma = true - result = newNodeP(nkPragma, p) - var e = newNodeP(nkExprColonExpr, p) - addSon(e, newIdentNodeP("deadCodeElim", p), newIdentNodeP("on", p)) - addSon(result, e) - else: - result = ast.emptyNode - -proc parseDir(p: var TParser): PNode = - result = ast.emptyNode - assert(p.tok.xkind in {pxDirective, pxDirectiveParLe}) - case p.tok.s - of "define": result = parseDefine(p) - of "include": result = parseInclude(p) - of "ifdef": result = parseIfdef(p) - of "ifndef": result = parseIfndef(p) - of "if": result = parseIfDir(p) - of "cdecl", "stdcall", "ref", "skipinclude", "typeprefixes", "skipcomments": - discard setOption(p.options, p.tok.s) - getTok(p) - eatNewLine(p, nil) - of "dynlib", "header", "prefix", "suffix", "class": - var key = p.tok.s - getTok(p) - if p.tok.xkind != pxStrLit: expectIdent(p) - discard setOption(p.options, key, p.tok.s) - getTok(p) - eatNewLine(p, nil) - result = modulePragmas(p) - of "mangle": - parseMangleDir(p) - of "def": - var L = p.options.macros.len - setLen(p.options.macros, L+1) - parseDef(p, p.options.macros[L]) - of "private": - var pattern = parsePegLit(p) - p.options.privateRules.add(pattern) - eatNewLine(p, nil) - else: - # ignore unimportant/unknown directive ("undef", "pragma", "error") - skipLine(p) - diff --git a/compiler/c2nim/nimrod.cfg b/compiler/c2nim/nimrod.cfg deleted file mode 100644 index cfeda63ed..000000000 --- a/compiler/c2nim/nimrod.cfg +++ /dev/null @@ -1,4 +0,0 @@ -# Use the modules of the compiler - -path: "$nimrod/compiler" - diff --git a/compiler/c2nim/tests/enum.h b/compiler/c2nim/tests/enum.h deleted file mode 100644 index 16bc59058..000000000 --- a/compiler/c2nim/tests/enum.h +++ /dev/null @@ -1,40 +0,0 @@ - -enum vehicles -{ - car = 0x10, - truck, - boat = 0x01, - ship = 1, - speedboat = 1, - bicycle = 4, - bobycar -}; - -enum -{ - red = 4, - green = 2, - blue -}; - -typedef enum food -{ - bread = 4, - toast = 4, - bun = 0x04, - cucumber = 2, - chocolate = 6 -}; - -typedef enum numbers -{ - one = 1, - two, - nten = - 10, - nnine, - four = 4, - three = + 3, - positivenine = + 9, - nfour = - 4, - negativeten = -10 -}; \ No newline at end of file diff --git a/compiler/c2nim/tests/matrix.h b/compiler/c2nim/tests/matrix.h deleted file mode 100644 index 715e9e43b..000000000 --- a/compiler/c2nim/tests/matrix.h +++ /dev/null @@ -1,240 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: wx/matrix.h -// Purpose: wxTransformMatrix class. NOT YET USED -// Author: Chris Breeze, Julian Smart -// Modified by: Klaas Holwerda -// Created: 01/02/97 -// RCS-ID: $Id$ -// Copyright: (c) Julian Smart, Chris Breeze -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_MATRIXH__ -#define _WX_MATRIXH__ - -//! headerfiles="matrix.h wx/object.h" -#include "wx/object.h" -#include "wx/math.h" - -//! codefiles="matrix.cpp" - -// A simple 3x3 matrix. This may be replaced by a more general matrix -// class some day. -// -// Note: this is intended to be used in wxDC at some point to replace -// the current system of scaling/translation. It is not yet used. - -#def WXDLLIMPEXP_CORE -#header "wxmatrix.h" - -//:definition -// A 3x3 matrix to do 2D transformations. -// It can be used to map data to window coordinates, -// and also for manipulating your own data. -// For example drawing a picture (composed of several primitives) -// at a certain coordinate and angle within another parent picture. -// At all times m_isIdentity is set if the matrix itself is an Identity matrix. -// It is used where possible to optimize calculations. -class WXDLLIMPEXP_CORE wxTransformMatrix: public wxObject<string, string<ubyte>> -{ -public: - wxTransformMatrix(void); - wxTransformMatrix(const wxTransformMatrix& mat); - - ~wxTransformMatrix(void); - - //get the value in the matrix at col,row - //rows are horizontal (second index of m_matrix member) - //columns are vertical (first index of m_matrix member) - double GetValue(int col, int row) const; - - //set the value in the matrix at col,row - //rows are horizontal (second index of m_matrix member) - //columns are vertical (first index of m_matrix member) - void SetValue(int col, int row, double value); - - void operator = (const wxTransformMatrix& mat); - bool operator == (const wxTransformMatrix& mat) const; - bool operator != (const module::gah::wxTransformMatrix& mat) const; - - //multiply every element by t - wxTransformMatrix& operator*=(const double& t); - //divide every element by t - wxTransformMatrix& operator/=(const double& t); - //add matrix m to this t - wxTransformMatrix& operator+=(const wxTransformMatrix& m); - //subtract matrix m from this - wxTransformMatrix& operator-=(const wxTransformMatrix& m); - //multiply matrix m with this - wxTransformMatrix& operator*=(const wxTransformMatrix& m); - - // constant operators - - //multiply every element by t and return result - wxTransformMatrix operator*(const double& t) const; - //divide this matrix by t and return result - wxTransformMatrix operator/(const double& t) const; - //add matrix m to this and return result - wxTransformMatrix operator+(const wxTransformMatrix& m) const; - //subtract matrix m from this and return result - wxTransformMatrix operator-(const wxTransformMatrix& m) const; - //multiply this by matrix m and return result - wxTransformMatrix operator*(const wxTransformMatrix& m) const; - wxTransformMatrix operator-() const; - - //rows are horizontal (second index of m_matrix member) - //columns are vertical (first index of m_matrix member) - double& operator()(int col, int row); - - //rows are horizontal (second index of m_matrix member) - //columns are vertical (first index of m_matrix member) - double operator()(int col, int row) const; - - // Invert matrix - bool Invert(void); - - // Make into identity matrix - bool Identity(void); - - // Is the matrix the identity matrix? - // Only returns a flag, which is set whenever an operation - // is done. - inline bool IsIdentity(void) const { return m_isIdentity; } - - // This does an actual check. - inline bool IsIdentity1(void) const ; - - //Scale by scale (isotropic scaling i.e. the same in x and y): - //!ex: - //!code: | scale 0 0 | - //!code: matrix' = | 0 scale 0 | x matrix - //!code: | 0 0 scale | - bool Scale(double scale); - - //Scale with center point and x/y scale - // - //!ex: - //!code: | xs 0 xc(1-xs) | - //!code: matrix' = | 0 ys yc(1-ys) | x matrix - //!code: | 0 0 1 | - wxTransformMatrix& Scale(const double &xs, const double &ys,const double &xc, const double &yc); - - // mirror a matrix in x, y - //!ex: - //!code: | -1 0 0 | - //!code: matrix' = | 0 -1 0 | x matrix - //!code: | 0 0 1 | - wxTransformMatrix<float>& Mirror(bool x=true, bool y=false); - // Translate by dx, dy: - //!ex: - //!code: | 1 0 dx | - //!code: matrix' = | 0 1 dy | x matrix - //!code: | 0 0 1 | - bool Translate(double x, double y); - - // Rotate clockwise by the given number of degrees: - //!ex: - //!code: | cos sin 0 | - //!code: matrix' = | -sin cos 0 | x matrix - //!code: | 0 0 1 | - bool Rotate(double angle); - - //Rotate counter clockwise with point of rotation - // - //!ex: - //!code: | cos(r) -sin(r) x(1-cos(r))+y(sin(r)| - //!code: matrix' = | sin(r) cos(r) y(1-cos(r))-x(sin(r)| x matrix - //!code: | 0 0 1 | - wxTransformMatrix& Rotate(const double &r, const double &x, const double &y); - - // Transform X value from logical to device - inline double TransformX(double x) const; - - // Transform Y value from logical to device - inline double TransformY(double y) const; - - // Transform a point from logical to device coordinates - bool TransformPoint(double x, double y, double& tx, double& ty) const; - - // Transform a point from device to logical coordinates. - // Example of use: - // wxTransformMatrix mat = dc.GetTransformation(); - // mat.Invert(); - // mat.InverseTransformPoint(x, y, x1, y1); - // OR (shorthand:) - // dc.LogicalToDevice(x, y, x1, y1); - // The latter is slightly less efficient if we're doing several - // conversions, since the matrix is inverted several times. - // N.B. 'this' matrix is the inverse at this point - bool InverseTransformPoint(double x, double y, double& tx, double& ty) const; - - double Get_scaleX(); - double Get_scaleY(); - double GetRotation(); - void SetRotation(double rotation); - - -public: - double m_matrix[3][3]; - bool m_isIdentity; -}; - - -/* -Chris Breeze reported, that -some functions of wxTransformMatrix cannot work because it is not -known if he matrix has been inverted. Be careful when using it. -*/ - -// Transform X value from logical to device -// warning: this function can only be used for this purpose -// because no rotation is involved when mapping logical to device coordinates -// mirror and scaling for x and y will be part of the matrix -// if you have a matrix that is rotated, eg a shape containing a matrix to place -// it in the logical coordinate system, use TransformPoint -inline double wxTransformMatrix::TransformX(double x) const -{ - //normally like this, but since no rotation is involved (only mirror and scale) - //we can do without Y -> m_matrix[1]{0] is -sin(rotation angle) and therefore zero - //(x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0])) - return (m_isIdentity ? x : (x * m_matrix[0][0] + m_matrix[2][0])); -} - -// Transform Y value from logical to device -// warning: this function can only be used for this purpose -// because no rotation is involved when mapping logical to device coordinates -// mirror and scaling for x and y will be part of the matrix -// if you have a matrix that is rotated, eg a shape containing a matrix to place -// it in the logical coordinate system, use TransformPoint -inline double wxTransformMatrix::TransformY(double y) const -{ - //normally like this, but since no rotation is involved (only mirror and scale) - //we can do without X -> m_matrix[0]{1] is sin(rotation angle) and therefore zero - //(x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1])) - return (m_isIdentity ? y : (y * m_matrix[1][1] + m_matrix[2][1])); -} - - -// Is the matrix the identity matrix? -// Each operation checks whether the result is still the identity matrix and sets a flag. -inline bool wxTransformMatrix::IsIdentity1(void) const -{ - return - ( wxIsSameDouble(m_matrix[0][0], 1.0) && - wxIsSameDouble(m_matrix[1][1], 1.0) && - wxIsSameDouble(m_matrix[2][2], 1.0) && - wxIsSameDouble(m_matrix[1][0], 0.0) && - wxIsSameDouble(m_matrix[2][0], 0.0) && - wxIsSameDouble(m_matrix[0][1], 0.0) && - wxIsSameDouble(m_matrix[2][1], 0.0) && - wxIsSameDouble(m_matrix[0][2], 0.0) && - wxIsSameDouble(m_matrix[1][2], 0.0) ); -} - -// Calculates the determinant of a 2 x 2 matrix -inline double wxCalculateDet(double a11, double a21, double a12, double a22) -{ - return a11 * a22 - a12 * a21; -} - -#endif // _WX_MATRIXH__ diff --git a/compiler/c2nim/tests/struct_anonym.h b/compiler/c2nim/tests/struct_anonym.h deleted file mode 100644 index 859bfc206..000000000 --- a/compiler/c2nim/tests/struct_anonym.h +++ /dev/null @@ -1,27 +0,0 @@ - -struct normal{ - int a; - int b; -}; - -typedef struct outerStruct { - struct normal a_nomal_one; - - int a; - - struct { - union { - int b; - } a_union_in_the_struct; - - int c; - }; - - union { - int d; - - struct { - int e; - } a_struct_in_the_union; - } a_union; -}; \ No newline at end of file diff --git a/compiler/c2nim/tests/systest.c b/compiler/c2nim/tests/systest.c deleted file mode 100644 index 51509e253..000000000 --- a/compiler/c2nim/tests/systest.c +++ /dev/null @@ -1,622 +0,0 @@ -/* This file has been written by Blablub. - * - * Another comment line. - */ - -#ifdef __cplusplus -# ifdef __SOME_OTHER_CRAP -extern "C" { -# endif -#endif - -#define interrupts() sei() - -enum -{ -/* 8bit, color or not */ - CV_LOAD_IMAGE_UNCHANGED =-1, -/* 8bit, gray */ - CV_LOAD_IMAGE_GRAYSCALE =0, -/* ?, color */ - CV_LOAD_IMAGE_COLOR =1, -/* any depth, ? */ - CV_LOAD_IMAGE_ANYDEPTH =2, -/* ?, any color */ - CV_LOAD_IMAGE_ANYCOLOR =4 -}; - -typedef void (*callback_t) (int rc); -typedef const char* (*callback2)(int rc, long L, const char* buffer); - -int aw_callback_set (AW_CALLBACK c, callback_t callback ); -int aw_instance_callback_set (AW_CALLBACK c, callback_t callback); - -unsigned long int wawa; - -#define MAX(x, y) ((x) < (y)? (y) : (x)) - -#define AW_BUILD 85 // AW 5.0 -// Limits -#define AW_MAX_AVCHANGE_PER_SECOND 10 - -#private expatDll - -#if !defined(expatDll) -# if defined(windows) -# define expatDll "expat.dll" -# elif defined(macosx) -# define expatDll "libexpat.dynlib" -# else -# define expatDll "libexpat.so(.1|)" -# endif -#endif - -#mangle "'XML_'{.*}" "$1" -#private "'XML_ParserStruct'" - -#mangle cuint cint - -unsigned int uiVar; - -#private "@('_'!.)" -unsigned int myPrivateVar__; - - -struct XML_ParserStruct; - -#def XMLCALL __cdecl - -typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData, - const XML_Char *name, - XML_Content *model); - - -void* x; -void* fn(void); -void (*fn)(void); -void* (*fn)(void); -void* (*fn)(void*); - -/* - * Very ugly real world code ahead: - */ - -#def JMETHOD(rettype, name, params) rettype (*name) params - -typedef struct cjpeg_source_struct * cjpeg_source_ptr; - -struct cjpeg_source_struct { - JMETHOD(void, start_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(void, finish_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - - FILE *input_file; - - JSAMPARRAY buffer; - JDIMENSION buffer_height; -}; - -// Test standalone structs: - -union myunion { - char x, y, *z; - myint a, b; -} u; - -struct mystruct { - char x, y, *z; - myint a, b; -}; - -struct mystruct fn(i32 x, i64 y); - -struct mystruct { - char x, y, *z; - myint a, b; -} *myvar = NULL, **myvar2 = NULL; - -// anonymous struct: - -struct { - char x, y, *z; - myint a, b; -} varX, **varY; - -// empty anonymous struct: - -struct { - -} varX, **varY; - -// Test C2NIM skipping: - -#define MASK(x) ((x) & 0xff) -#define CAST1(x) ((int) &x) -#define CAST2(x) (typ*) &x -#define CAST3(x) ((const unsigned char**) &x) - -#ifndef C2NIM - #if someNestedCond - This is an invalid text that should generate a parser error, if not - #endif - skipped correctly. -#endif - -#ifndef C2NIM - #if someNestedCond - This is an invalid text that should generate a parser error, if not - #endif - skipped correctly. -#else -typedef char gchar; -typedef unsigned int gunsignedint; -typedef unsigned char guchar; -#endif - -#ifdef C2NIM -# mangle "'those'" "these" -int those; -#elif abc - #if someNestedCond - This is an invalid text that should generate a parser error, if not - #else - skipped correctly. - #endif -#else - Another crappy input line. -#endif - -point* newPoint(void) { - for (int i = 0; i < 89; ++i) echo("test" " string " "concatenation"); - for (; j < 54; j++) {} - for (;; j--) ; - for (;;) {} - mytype * x = y * z; - - if (**p == ' ') { - --p; - } else if (**p == '\t') { - p += 3; - } else { - p = 45 + (mytype*)45; - p = 45 + ((mytype*)45); - p = 45 + ((mytype)45); - // BUG: This does not parse: - // p = 45 + (mytype)45; - } - - while (x >= 6 && x <= 20) - --x; - - switch (*p) { - case 'A'...'Z': - case 'a'...'z': - ++p; - break; - case '0': - ++p; - break; - default: - return NULL; - } -} - -enum { - a1, a2 = 4, a3 -}; - -typedef enum crazyTAG { - x1, x2, x3 = 8, x4, x5 -} myEnum, *pMyEnum; - -typedef enum { - x1, x2, x3 = 8, x4, x5 -} myEnum, *pMyEnum; - -// Test multi-line macro: - -#define MUILTILINE "abc" \ - "xyz" \ - "def" - -#define MULTILINE(x, y) do { \ - ++y; ++x; \ -} while (0) - -#ifdef C2NIM -# dynlib iupdll -# cdecl -# mangle "'GTK_'{.*}" "TGtk$1" -# mangle "'PGTK_'{.*}" "PGtk$1" -# if defined(windows) -# define iupdll "iup.dll" -# elif defined(macosx) -# define iupdll "libiup.dynlib" -# else -# define iupdll "libiup.so" -# endif -#endif - -typedef struct stupidTAG { - mytype a, b; -} GTK_MyStruct, *PGTK_MyStruct; - -typedef struct { - mytype a, b; -} GTK_MyStruct, *PGTK_MyStruct; - -int IupConvertXYToPos(PIhandle ih, int x, int y); - -#ifdef DEBUG -# define OUT(x) printf("%s\n", x) -#else -# define OUT(x) -#endif - - - #ifdef C2NIM - # def EXTERN(x) static x - # def TWO_ARGS(x, y) x* y - #endif - // parses now! - EXTERN(int) f(void); - EXTERN(int) g(void); - - - #def EXPORT - // does parse now! - EXPORT int f(void); - EXPORT int g(void); - - static TWO_ARGS(int, x) = TWO_ARGS(56, 45); - - -# define abc 34 -# define xyz 42 - -# define wuseldusel "my string\nconstant" - -#undef ignoreThis - -char* x; - -typedef struct { - char x, y, *z; -} point; - -char* __stdcall printf(char* frmt, const char* const** ptrToStrArray, - const int* const dummy, ...); - -inline char* myinlineProc(char* frmt, const char* const* strArray, - const int* const dummy, ...); - -// Test void parameter list: -void myVoidProc(void); - -void emptyReturn(void) { return; } - -// POSIX stuff: - -#ifdef C2NIM -#prefix posix_ -int c2nimBranch; -#elif defined(MACOSX) -int* x, y, z; -#else -int dummy; -#endif - -#ifndef C2NIM -int dontTranslateThis; -#elif defined(Windows) -int WindowsTrue = true; -#endif - -int posix_spawn(pid_t *restrict, const char *restrict, - const posix_spawn_file_actions_t *, - const posix_spawnattr_t *restrict, char *const [restrict], - char *const [restrict]); -int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, - int); -int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, - int, int); -int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict, - int, const char *restrict, int, mode_t); -int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *); -int posix_spawn_file_actions_init(posix_spawn_file_actions_t *); -int posix_spawnattr_destroy(posix_spawnattr_t *); -int posix_spawnattr_getsigdefault(const posix_spawnattr_t *restrict, - sigset_t *restrict); -int posix_spawnattr_getflags(const posix_spawnattr_t *restrict, - short *restrict); -int posix_spawnattr_getpgroup(const posix_spawnattr_t *restrict, - pid_t *restrict); -int posix_spawnattr_getschedparam(const posix_spawnattr_t *restrict, - struct sched_param *restrict); -int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *restrict, - int *restrict); -int posix_spawnattr_getsigmask(const posix_spawnattr_t *restrict, - sigset_t *restrict); -int posix_spawnattr_init(posix_spawnattr_t *); -int posix_spawnattr_setsigdefault(posix_spawnattr_t *restrict, - const sigset_t *restrict); -int posix_spawnattr_setflags(posix_spawnattr_t *, short); -int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t); - - -int posix_spawnattr_setschedparam(posix_spawnattr_t *restrict, - const struct sched_param *restrict); -int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int); -int posix_spawnattr_setsigmask(posix_spawnattr_t *restrict, - const sigset_t *restrict); -int posix_spawnp(pid_t *restrict, const char *restrict, - const posix_spawn_file_actions_t *, - const posix_spawnattr_t *restrict, - char *const [restrict], char *const [restrict]); - -typedef struct -{ - float R, G, B; -} -RGBType; -typedef struct -{ - float H, W, B; -} -HWBType; - -static HWBType * -RGB_to_HWB (RGBType RGB, HWBType * HWB) -{ - HWBType* myArray[20]; - /* - * RGB are each on [0, 1]. W and B are returned on [0, 1] and H is - * returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B. - */ - - float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f; - int i; - - w = MIN3 (R, G, B); - v = MAX3 (R, G, B); - b &= 1 - v; - if (v == w) - RETURN_HWB (HWB_UNDEFINED, w, b); - f = (R == w) ? G - B : ((G == w) ? B - R : R - G); - i = (R == w) ? 3 : ((G == w) ? 5 : 1); - RETURN_HWB (i - f / (v - w), w, b); - -} - -static int -clip_1d (int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim) -{ - double m; // gradient of line - if (*x0 < mindim) - { // start of line is left of window - if (*x1 < mindim) // as is the end, so the line never cuts the window - return 0; - m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line - // adjust x0 to be on the left boundary (ie to be zero), and y0 to match - *y0 -= m * (*x0 - mindim); - *x0 = mindim; - // now, perhaps, adjust the far end of the line as well - if (*x1 > maxdim) - { - *y1 += m * (maxdim - *x1); - *x1 = maxdim; - } - return 1; - } - if (*x0 > maxdim) - { // start of line is right of window - complement of above - if (*x1 > maxdim) // as is the end, so the line misses the window - return 0; - m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line - *y0 += m * (maxdim - *x0); // adjust so point is on the right - // boundary - *x0 = maxdim; - // now, perhaps, adjust the end of the line - if (*x1 < mindim) - { - *y1 -= m * (*x1 - mindim); - *x1 = mindim; - } - return 1; - } - // the final case - the start of the line is inside the window - if (*x1 > maxdim) - { // other end is outside to the right - m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line - *y1 += m * (maxdim - *x1); - *x1 = maxdim; - return 1; - } - if (*x1 < mindim) - { // other end is outside to the left - m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of line - *y1 -= m * (*x1 - mindim); - *x1 = mindim; - return 1; - } - // only get here if both points are inside the window - return 1; -} - -// end of line clipping code - -static void -gdImageBrushApply (gdImagePtr im, int x, int y) -{ - int lx, ly; - int hy; - int hx; - int x1, y1, x2, y2; - int srcx, srcy; - if (!im->brush) - { - return; - } - hy = gdImageSY (im->brush) / 2; - y1 = y - hy; - y2 = y1 + gdImageSY (im->brush); - hx = gdImageSX (im->brush) / 2; - x1 = x - hx; - x2 = x1 + gdImageSX (im->brush); - srcy = 0; - if (im->trueColor) - { - if (im->brush->trueColor) - { - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p; - p = gdImageGetTrueColorPixel (im->brush, srcx, srcy); - // 2.0.9, Thomas Winzig: apply simple full transparency - if (p != gdImageGetTransparent (im->brush)) - { - gdImageSetPixel (im, lx, ly, p); - } - srcx++; - } - srcy++; - } - } - else - { - // 2.0.12: Brush palette, image truecolor (thanks to Thorben Kundinger - // for pointing out the issue) - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p, tc; - p = gdImageGetPixel (im->brush, srcx, srcy); - tc = gdImageGetTrueColorPixel (im->brush, srcx, srcy); - // 2.0.9, Thomas Winzig: apply simple full transparency - if (p != gdImageGetTransparent (im->brush)) - { - gdImageSetPixel (im, lx, ly, tc); - } - srcx++; - } - srcy++; - } - } - } - else - { - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p; - p = gdImageGetPixel (im->brush, srcx, srcy); - // Allow for non-square brushes! - if (p != gdImageGetTransparent (im->brush)) - { - // Truecolor brush. Very slow - // on a palette destination. - if (im->brush->trueColor) - { - gdImageSetPixel (im, lx, ly, - gdImageColorResolveAlpha(im, - gdTrueColorGetRed(p), - gdTrueColorGetGreen(p), - gdTrueColorGetBlue(p), - gdTrueColorGetAlpha(p))); - } - else - { - gdImageSetPixel (im, lx, ly, im->brushColorMap[p]); - } - } - srcx++; - } - srcy++; - } - } -} - - -void gdImageSetPixel (gdImagePtr im, int x, int y, int color) -{ - int p; - switch (color) - { - case gdStyled: - if (!im->style) - { - // Refuse to draw if no style is set. - return; - } - else - { - p = im->style[im->stylePos++]; - } - if (p != (gdTransparent)) - { - gdImageSetPixel (im, x, y, p); - } - im->stylePos = im->stylePos % im->styleLength; - break; - case gdStyledBrushed: - if (!im->style) - { - // Refuse to draw if no style is set. - return; - } - p = im->style[im->stylePos++]; - if ((p != gdTransparent) && (p != 0)) - { - gdImageSetPixel (im, x, y, gdBrushed); - } - im->stylePos = im->stylePos % im->styleLength; - break; - case gdBrushed: - gdImageBrushApply (im, x, y); - break; - case gdTiled: - gdImageTileApply (im, x, y); - break; - case gdAntiAliased: - // This shouldn't happen (2.0.26) because we just call - // gdImageAALine now, but do something sane. - gdImageSetPixel(im, x, y, im->AA_color); - break; - default: - if (gdImageBoundsSafeMacro (im, x, y)) - { - if (im->trueColor) - { - if (im->alphaBlendingFlag) - { - im->tpixels[y][x] = gdAlphaBlend (im->tpixels[y][x], color); - } - else - { - im->tpixels[y][x] = color; - } - } - else - { - im->pixels[y][x] = color; - } - } - break; - } -} - -#ifdef __cplusplus -} -#endif - - diff --git a/compiler/c2nim/tests/systest2.c b/compiler/c2nim/tests/systest2.c deleted file mode 100644 index bf3027cfc..000000000 --- a/compiler/c2nim/tests/systest2.c +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef C2NIM -# header "iup.h" -# cdecl -# mangle "'GTK_'{.*}" "TGtk$1" -# mangle "'PGTK_'{.*}" "PGtk$1" -#endif - -typedef struct stupidTAG { - mytype a, b; -} GTK_MyStruct, *PGTK_MyStruct; - -typedef struct { - mytype a, b; -} GTK_MyStruct, *PGTK_MyStruct; - -int IupConvertXYToPos(PIhandle ih, int x, int y); - diff --git a/compiler/c2nim/tests/vincent.c b/compiler/c2nim/tests/vincent.c deleted file mode 100644 index 24c6d6425..000000000 --- a/compiler/c2nim/tests/vincent.c +++ /dev/null @@ -1,33 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> - -int rand(void); - -int id2(void) { - return (int *)1; -} - -int id(void (*f)(void)) { - f(); - ((void (*)(int))f)(10); - return 10; - return (20+1); - return (int *)id; -} - -int main() { - float f = .2, - g = 2., - h = 1.0+rand(), - i = 1.0e+3; - int j, a; - for(j = 0, a = 10; j < 0; j++, a++) ; - do { - printf("howdy"); - } while(--i, 0); - if(1) - printf("1"); // error from this comment - else - printf("2"); - return '\x00'; -} diff --git a/compiler/c2nim/tests/vincent.h b/compiler/c2nim/tests/vincent.h deleted file mode 100644 index b4e761ee1..000000000 --- a/compiler/c2nim/tests/vincent.h +++ /dev/null @@ -1,3 +0,0 @@ -struct foo { - int x,y,z; -}; |