c2nim is not part of the compiler anymore

This commit is contained in:
Araq
2014-06-30 10:40:49 +02:00
parent c71d7213e8
commit 5f8ab1653a
20 changed files with 3 additions and 6936 deletions

View File

@@ -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)

View File

@@ -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)

File diff suppressed because it is too large Load Diff

View File

@@ -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)

View File

@@ -1,4 +0,0 @@
# Use the modules of the compiler
path: "$nimrod/compiler"

View File

@@ -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
};

View File

@@ -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__

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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);

View File

@@ -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';
}

View File

@@ -1,3 +0,0 @@
struct foo {
int x,y,z;
};

View File

@@ -1,4 +0,0 @@
# Use the modules of the compiler
path: "$nimrod/compiler"

View File

@@ -1,64 +0,0 @@
#
#
# Pas2nim - Pascal to Nimrod source converter
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
strutils, os, parseopt, llstream, ast, renderer, options, msgs,
paslex, pasparse
const
Version = "0.8"
Usage = """
pas2nim - Pascal to Nimrod source converter
(c) 2012 Andreas Rumpf
Usage: pas2nim [options] inputfile [options]
Options:
-o, --out:FILE set output filename
--ref convert ^typ to ref typ (default: ptr typ)
--boot use special translation rules for the Nimrod compiler
-v, --version write pas2nim's version
-h, --help show this help
"""
proc main(infile, outfile: string, flags: set[TParserFlag]) =
var stream = llStreamOpen(infile, fmRead)
if stream == nil: rawMessage(errCannotOpenFile, infile)
var p: TParser
openParser(p, infile, stream, flags)
var module = parseUnit(p)
closeParser(p)
renderModule(module, outfile)
var
infile = ""
outfile = ""
flags: set[TParserFlag] = {}
for kind, key, val in getopt():
case kind
of cmdArgument: infile = key
of cmdLongOption, cmdShortOption:
case key
of "help", "h":
stdout.write(Usage)
quit(0)
of "version", "v":
stdout.write(Version & "\n")
quit(0)
of "o", "out": outfile = val
of "ref": incl(flags, pfRefs)
of "boot": flags = flags + {pfRefs, pfMoreReplacements, pfImportBlackList}
else: 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, "pas")
main(infile, outfile, flags)

View File

@@ -1,570 +0,0 @@
#
#
# Pas2nim - Pascal 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 a FreePascal scanner. This is an adaption from
# the scanner module.
import
hashes, options, msgs, strutils, platform, idents, 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'}
OpChars*: TCharSet = {'+', '-', '*', '/', '<', '>', '!', '?', '^', '.', '|',
'=', ':', '%', '&', '$', '@', '~', '\x80'..'\xFF'}
# keywords are sorted!
type
TTokKind* = enum
pxInvalid, pxEof,
pxAnd, pxArray, pxAs, pxAsm, pxBegin, pxCase, pxClass, pxConst,
pxConstructor, pxDestructor, pxDiv, pxDo, pxDownto, pxElse, pxEnd, pxExcept,
pxExports, pxFinalization, pxFinally, pxFor, pxFunction, pxGoto, pxIf,
pxImplementation, pxIn, pxInherited, pxInitialization, pxInline,
pxInterface, pxIs, pxLabel, pxLibrary, pxMod, pxNil, pxNot, pxObject, pxOf,
pxOr, pxOut, pxPacked, pxProcedure, pxProgram, pxProperty, pxRaise,
pxRecord, pxRepeat, pxResourcestring, pxSet, pxShl, pxShr, pxThen,
pxThreadvar, pxTo, pxTry, pxType, pxUnit, pxUntil, pxUses, pxVar, pxWhile,
pxWith, pxXor,
pxComment, # ordinary comment
pxCommand, # {@}
pxAmp, # {&}
pxPer, # {%}
pxStrLit, pxSymbol, # a symbol
pxIntLit, pxInt64Lit, # long constant like 0x70fffffff or out of int range
pxFloatLit, pxParLe, pxParRi, pxBracketLe, pxBracketRi, pxComma,
pxSemiColon, pxColon, # operators
pxAsgn, pxEquals, pxDot, pxDotDot, pxHat, pxPlus, pxMinus, pxStar, pxSlash,
pxLe, pxLt, pxGe, pxGt, pxNeq, pxAt, pxStarDirLe, pxStarDirRi, pxCurlyDirLe,
pxCurlyDirRi
TTokKinds* = set[TTokKind]
const
Keywords = ["and", "array", "as", "asm", "begin", "case", "class", "const",
"constructor", "destructor", "div", "do", "downto", "else", "end", "except",
"exports", "finalization", "finally", "for", "function", "goto", "if",
"implementation", "in", "inherited", "initialization", "inline",
"interface", "is", "label", "library", "mod", "nil", "not", "object", "of",
"or", "out", "packed", "procedure", "program", "property", "raise",
"record", "repeat", "resourcestring", "set", "shl", "shr", "then",
"threadvar", "to", "try", "type", "unit", "until", "uses", "var", "while",
"with", "xor"]
firstKeyword = pxAnd
lastKeyword = pxXor
type
TNumericalBase* = enum base10, base2, base8, base16
TToken* = object
xkind*: TTokKind # the type of the token
ident*: PIdent # the parsed identifier
iNumber*: BiggestInt # the parsed integer literal
fNumber*: BiggestFloat # the parsed floating point literal
base*: TNumericalBase # the numerical base; only valid for int
# or float literals
literal*: string # the parsed (string) literal
TLexer* = object of TBaseLexer
filename*: string
proc getTok*(L: var TLexer, tok: var TToken)
proc printTok*(tok: TToken)
proc `$`*(tok: TToken): string
# implementation
var
dummyIdent: PIdent
gLinesCompiled: int
proc fillToken(L: var TToken) =
L.xkind = pxInvalid
L.iNumber = 0
L.literal = ""
L.fNumber = 0.0
L.base = base10
L.ident = dummyIdent # this prevents many bugs!
proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) =
openBaseLexer(lex, inputstream)
lex.filename = filename
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.filename, 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.filename, L.linenumber, pos - L.lineStart)
msgs.globalError(info, msg, arg)
proc tokKindToStr*(k: TTokKind): string =
case k
of pxEof: result = "[EOF]"
of firstKeyword..lastKeyword:
result = Keywords[ord(k)-ord(firstKeyword)]
of pxInvalid, pxComment, pxStrLit: result = "string literal"
of pxCommand: result = "{@"
of pxAmp: result = "{&"
of pxPer: 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 pxAsgn: result = ":="
of pxEquals: result = "="
of pxDot: result = "."
of pxDotDot: result = ".."
of pxHat: result = "^"
of pxPlus: result = "+"
of pxMinus: result = "-"
of pxStar: result = "*"
of pxSlash: result = "/"
of pxLe: result = "<="
of pxLt: result = "<"
of pxGe: result = ">="
of pxGt: result = ">"
of pxNeq: result = "<>"
of pxAt: result = "@"
of pxStarDirLe: result = "(*$"
of pxStarDirRi: result = "*)"
of pxCurlyDirLe: result = "{$"
of pxCurlyDirRi: result = "}"
proc `$`(tok: TToken): string =
case tok.xkind
of pxInvalid, pxComment, pxStrLit: result = tok.literal
of pxSymbol: result = tok.ident.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 setKeyword(L: var TLexer, tok: var TToken) =
var x = binaryStrSearch(keywords, toLower(tok.ident.s))
if x < 0: tok.xkind = pxSymbol
else: tok.xKind = TTokKind(x + ord(firstKeyword))
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.literal, buf[pos])
inc(pos)
else:
break
if buf[pos] == '_':
add(tok.literal, '_')
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 + 1 # skip %
if not (L.buf[pos] in {'0'..'1'}):
# BUGFIX for %date%
tok.xkind = pxInvalid
add(tok.literal, '%')
inc(L.bufpos)
return
tok.base = base2
var xi: BiggestInt = 0
var bits = 0
while true:
case L.buf[pos]
of 'A'..'Z', 'a'..'z', '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 getNumber16(L: var TLexer, tok: var TToken) =
var pos = L.bufpos + 1 # skip $
tok.base = base16
var xi: BiggestInt = 0
var bits = 0
while true:
case L.buf[pos]
of 'G'..'Z', 'g'..'z', '.':
lexMessage(L, errInvalidNumber)
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 getNumber10(L: var TLexer, tok: var TToken) =
tok.base = base10
matchUnderscoreChars(L, tok, {'0'..'9'})
if (L.buf[L.bufpos] == '.') and (L.buf[L.bufpos + 1] in {'0'..'9'}):
add(tok.literal, '.')
inc(L.bufpos)
matchUnderscoreChars(L, tok, {'e', 'E', '+', '-', '0'..'9'})
try:
if isFloatLiteral(tok.literal):
tok.fnumber = parseFloat(tok.literal)
tok.xkind = pxFloatLit
else:
tok.iNumber = parseInt(tok.literal)
if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)):
tok.xkind = pxInt64Lit
else:
tok.xkind = pxIntLit
except EInvalidValue:
lexMessage(L, errInvalidNumber, tok.literal)
except EOverflow:
lexMessage(L, errNumberOutOfRange, tok.literal)
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 getString(L: var TLexer, tok: var TToken) =
var xi: int
var pos = L.bufPos
var buf = L.buf
while true:
if buf[pos] == '\'':
inc(pos)
while true:
case buf[pos]
of CR, LF, nimlexbase.EndOfFile:
lexMessage(L, errClosingQuoteExpected)
break
of '\'':
inc(pos)
if buf[pos] == '\'':
inc(pos)
add(tok.literal, '\'')
else:
break
else:
add(tok.literal, buf[pos])
inc(pos)
elif buf[pos] == '#':
inc(pos)
xi = 0
case buf[pos]
of '$':
inc(pos)
xi = 0
while true:
case buf[pos]
of '0'..'9': xi = (xi shl 4) or (ord(buf[pos]) - ord('0'))
of 'a'..'f': xi = (xi shl 4) or (ord(buf[pos]) - ord('a') + 10)
of 'A'..'F': xi = (xi shl 4) or (ord(buf[pos]) - ord('A') + 10)
else: break
inc(pos)
of '0'..'9':
xi = 0
while buf[pos] in {'0'..'9'}:
xi = (xi * 10) + (ord(buf[pos]) - ord('0'))
inc(pos)
else: lexMessage(L, errInvalidCharacterConstant)
if (xi <= 255): add(tok.literal, chr(xi))
else: lexMessage(L, errInvalidCharacterConstant)
else:
break
tok.xkind = pxStrLit
L.bufpos = pos
proc getSymbol(L: var TLexer, tok: var TToken) =
var h: THash = 0
var pos = L.bufpos
var buf = L.buf
while true:
var c = buf[pos]
case c
of 'a'..'z', '0'..'9', '\x80'..'\xFF':
h = h +% ord(c)
h = h +% h shl 10
h = h xor (h shr 6)
of 'A'..'Z':
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = h +% ord(c)
h = h +% h shl 10
h = h xor (h shr 6)
of '_': discard
else: break
inc(pos)
h = h +% h shl 3
h = h xor (h shr 11)
h = h +% h shl 15
tok.ident = getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
L.bufpos = pos
setKeyword(L, tok)
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 = pxComment
var col = getColNumber(L, pos)
while true:
inc(pos, 2) # skip //
add(tok.literal, '#')
while not (buf[pos] in {CR, LF, nimlexbase.EndOfFile}):
add(tok.literal, 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] == '/'):
tok.literal = tok.literal & "\n"
else:
break
L.bufpos = pos
proc scanCurlyComment(L: var TLexer, tok: var TToken) =
var pos = L.bufpos
var buf = L.buf
tok.literal = "#"
tok.xkind = pxComment
while true:
case buf[pos]
of CR, LF:
pos = handleCRLF(L, pos)
buf = L.buf
add(tok.literal, "\n#")
of '}':
inc(pos)
break
of nimlexbase.EndOfFile: lexMessage(L, errTokenExpected, "}")
else:
add(tok.literal, buf[pos])
inc(pos)
L.bufpos = pos
proc scanStarComment(L: var TLexer, tok: var TToken) =
var pos = L.bufpos
var buf = L.buf
tok.literal = "#"
tok.xkind = pxComment
while true:
case buf[pos]
of CR, LF:
pos = handleCRLF(L, pos)
buf = L.buf
add(tok.literal, "\n#")
of '*':
inc(pos)
if buf[pos] == ')':
inc(pos)
break
else:
add(tok.literal, '*')
of nimlexbase.EndOfFile:
lexMessage(L, errTokenExpected, "*)")
else:
add(tok.literal, 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 ' ', Tabulator:
inc(pos) # newline is special:
of CR, LF:
pos = handleCRLF(L, pos)
buf = L.buf
else:
break # EndOfFile also leaves the loop
L.bufpos = pos
proc getTok(L: var TLexer, tok: var TToken) =
tok.xkind = pxInvalid
fillToken(tok)
skip(L, tok)
var c = L.buf[L.bufpos]
if c in SymStartChars:
getSymbol(L, tok)
elif c in {'0'..'9'}:
getNumber10(L, tok)
else:
case c
of ';':
tok.xkind = pxSemicolon
inc(L.bufpos)
of '/':
if L.buf[L.bufpos + 1] == '/':
scanLineComment(L, tok)
else:
tok.xkind = pxSlash
inc(L.bufpos)
of ',':
tok.xkind = pxComma
inc(L.bufpos)
of '(':
inc(L.bufpos)
if (L.buf[L.bufPos] == '*'):
if (L.buf[L.bufPos + 1] == '$'):
inc(L.bufpos, 2)
skip(L, tok)
getSymbol(L, tok)
tok.xkind = pxStarDirLe
else:
inc(L.bufpos)
scanStarComment(L, tok)
else:
tok.xkind = pxParLe
of '*':
inc(L.bufpos)
if L.buf[L.bufpos] == ')':
inc(L.bufpos)
tok.xkind = pxStarDirRi
else:
tok.xkind = pxStar
of ')':
tok.xkind = pxParRi
inc(L.bufpos)
of '[':
inc(L.bufpos)
tok.xkind = pxBracketLe
of ']':
inc(L.bufpos)
tok.xkind = pxBracketRi
of '.':
inc(L.bufpos)
if L.buf[L.bufpos] == '.':
tok.xkind = pxDotDot
inc(L.bufpos)
else:
tok.xkind = pxDot
of '{':
inc(L.bufpos)
case L.buf[L.bufpos]
of '$':
inc(L.bufpos)
skip(L, tok)
getSymbol(L, tok)
tok.xkind = pxCurlyDirLe
of '&':
inc(L.bufpos)
tok.xkind = pxAmp
of '%':
inc(L.bufpos)
tok.xkind = pxPer
of '@':
inc(L.bufpos)
tok.xkind = pxCommand
else: scanCurlyComment(L, tok)
of '+':
tok.xkind = pxPlus
inc(L.bufpos)
of '-':
tok.xkind = pxMinus
inc(L.bufpos)
of ':':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxAsgn
else:
tok.xkind = pxColon
of '<':
inc(L.bufpos)
if L.buf[L.bufpos] == '>':
inc(L.bufpos)
tok.xkind = pxNeq
elif L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxLe
else:
tok.xkind = pxLt
of '>':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxGe
else:
tok.xkind = pxGt
of '=':
tok.xkind = pxEquals
inc(L.bufpos)
of '@':
tok.xkind = pxAt
inc(L.bufpos)
of '^':
tok.xkind = pxHat
inc(L.bufpos)
of '}':
tok.xkind = pxCurlyDirRi
inc(L.bufpos)
of '\'', '#':
getString(L, tok)
of '$':
getNumber16(L, tok)
of '%':
getNumber2(L, tok)
of nimlexbase.EndOfFile:
tok.xkind = pxEof
else:
tok.literal = c & ""
tok.xkind = pxInvalid
lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
inc(L.bufpos)

File diff suppressed because it is too large Load Diff

View File

@@ -1,295 +0,0 @@
=======================
c2nim User's manual
=======================
:Author: Andreas Rumpf
:Version: |nimrodversion|
.. contents::
Introduction
============
"We all make choices. But in the end our choices make us."
c2nim is a tool to translate Ansi C code to Nimrod. The output is
human-readable Nimrod code that is meant to be tweaked by hand after the
translation process. c2nim is no real compiler!
c2nim is preliminary meant to translate C header files. Because of this, the
preprocessor is part of the parser. For example:
.. code-block:: C
#define abc 123
#define xyz 789
Is translated into:
.. code-block:: Nimrod
const
abc* = 123
xyz* = 789
c2nim is meant to translate fragments of C code and thus does not follow
include files. c2nim cannot parse all of Ansi C and many constructs cannot
be represented in Nimrod: for example `duff's device`:idx: cannot be translated
to Nimrod.
Preprocessor support
====================
Even though the translation process is not perfect, it is often the case that
the translated Nimrod code does not need any tweaking by hand. In other cases
it may be preferable to modify the input file instead of the generated Nimrod
code so that c2nim can parse it properly. c2nim's preprocessor defines the
symbol ``C2NIM`` that can be used to mark code sections:
.. code-block:: C
#ifndef C2NIM
// C2NIM should ignore this prototype:
int fprintf(FILE* f, const char* frmt, ...);
#endif
The ``C2NIM`` symbol is only recognized in ``#ifdef`` and ``#ifndef``
constructs! ``#if defined(C2NIM)`` does **not** work.
c2nim *processes* ``#ifdef C2NIM`` and ``#ifndef C2NIM`` directives, but other
``#if[def]`` directives are *translated* into Nimrod's ``when`` construct:
.. code-block:: C
#ifdef DEBUG
# define OUT(x) printf("%s\n", x)
#else
# define OUT(x)
#endif
Is translated into:
.. code-block:: Nimrod
when defined(debug):
template OUT*(x: expr): expr =
printf("%s\x0A", x)
else:
template OUT*(x: expr): stmt =
discard
As can been seen from the example, C's macros with parameters are mapped
to Nimrod's templates. This mapping is the best one can do, but it is of course
not accurate: Nimrod's templates operate on syntax trees whereas C's
macros work on the token level. c2nim cannot translate any macro that contains
the ``##`` token concatenation operator.
c2nim's preprocessor supports special directives that affect how the output
is generated. They should be put into a ``#ifdef C2NIM`` section so that
ordinary C compilers ignore them.
``#skipinclude`` directive
--------------------------
**Note**: There is also a ``--skipinclude`` command line option that can be
used for the same purpose.
By default, c2nim translates an ``#include`` that is not followed by ``<``
(like in ``#include <stdlib>``) to a Nimrod ``import`` statement. This
directive tells c2nim to just skip any ``#include``.
``#stdcall`` and ``#cdecl`` directives
--------------------------------------
**Note**: There are also ``--stdcall`` and ``--cdecl`` command line options
that can be used for the same purpose.
These directives tell c2nim that it should annotate every proc (or proc type)
with the ``stdcall`` / ``cdecl`` calling convention.
``#dynlib`` directive
---------------------
**Note**: There is also a ``--dynlib`` command line option that can be used for
the same purpose.
This directive tells c2nim that it should annotate every proc that resulted
from a C function prototype with the ``dynlib`` pragma:
.. code-block:: C
#ifdef C2NIM
# dynlib iupdll
# cdecl
# if defined(windows)
# define iupdll "iup.dll"
# elif defined(macosx)
# define iupdll "libiup.dylib"
# else
# define iupdll "libiup.so"
# endif
#endif
int IupConvertXYToPos(PIhandle ih, int x, int y);
Is translated to:
.. code-block:: Nimrod
when defined(windows):
const iupdll* = "iup.dll"
elif defined(macosx):
const iupdll* = "libiup.dylib"
else:
const iupdll* = "libiup.so"
proc IupConvertXYToPos*(ih: PIhandle, x: cint, y: cint): cint {.
importc: "IupConvertXYToPos", cdecl, dynlib: iupdll.}
Note how the example contains extra C code to declare the ``iupdll`` symbol
in the generated Nimrod code.
``#header`` directive
---------------------
**Note**: There is also a ``--header`` command line option that can be used for
the same purpose.
The ``#header`` directive tells c2nim that it should annotate every proc that
resulted from a C function prototype and every exported variable and type with
the ``header`` pragma:
.. code-block:: C
#ifdef C2NIM
# header "iup.h"
#endif
int IupConvertXYToPos(PIhandle ih, int x, int y);
Is translated to:
.. code-block:: Nimrod
proc IupConvertXYToPos*(ih: PIhandle, x: cint, y: cint): cint {.
importc: "IupConvertXYToPos", header: "iup.h".}
The ``#header`` and the ``#dynlib`` directives are mutually exclusive.
A binding that uses ``dynlib`` is much more preferable over one that uses
``header``! The Nimrod compiler might drop support for the ``header`` pragma
in the future as it cannot work for backends that do not generate C code.
``#prefix`` and ``#suffix`` directives
--------------------------------------
**Note**: There are also ``--prefix`` and ``--suffix`` command line options
that can be used for the same purpose.
c2nim does not do any name mangling by default. However the
``#prefix`` and ``#suffix`` directives can be used to strip prefixes and
suffixes from the identifiers in the C code:
.. code-block:: C
#ifdef C2NIM
# prefix Iup
# dynlib dllname
# cdecl
#endif
int IupConvertXYToPos(PIhandle ih, int x, int y);
Is translated to:
.. code-block:: Nimrod
proc ConvertXYToPos*(ih: PIhandle, x: cint, y: cint): cint {.
importc: "IupConvertXYToPos", cdecl, dynlib: dllname.}
``#mangle`` directive
---------------------
Even more sophisticated name mangling can be achieved by the ``#mangle``
directive: It takes a PEG pattern and format string that specify how the
identifier should be converted:
.. code-block:: C
#mangle "'GTK_'{.*}" "TGtk$1"
For convenience the PEG pattern and the replacement can be single identifiers
too, there is no need to quote them:
.. code-block:: C
#mangle ssize_t int
// is short for:
#mangle "'ssize_t'" "int"
``#private`` directive
----------------------
By default c2nim marks every top level identifier (proc name, variable, etc.)
as exported (the export marker is ``*`` in Nimrod). With the ``#private``
directive identifiers can be marked as private so that the resulting Nimrod
module does not export them. The ``#private`` directive takes a PEG pattern:
.. code-block:: C
#private "@('_'!.)" // all identifiers ending in '_' are private
Note: The pattern refers to the original C identifiers, not to the resulting
identifiers after mangling!
``#skipcomments`` directive
---------------------------
**Note**: There is also a ``--skipcomments`` command line option that can be
used for the same purpose.
The ``#skipcomments`` directive can be put into the C code to make c2nim
ignore comments and not copy them into the generated Nimrod file.
``#typeprefixes`` directive
---------------------------
**Note**: There is also a ``--typeprefixes`` command line option that can be
used for the same purpose.
The ``#typeprefixes`` directive can be put into the C code to make c2nim
generate the ``T`` or ``P`` prefix for every defined type.
``#def`` directive
------------------
Often C code contains special macros that affect the declaration of a function
prototype but confuse c2nim's parser:
.. code-block:: C
// does not parse!
EXTERN(int) f(void);
EXTERN(int) g(void);
Instead of removing ``EXTERN()`` from the input source file (which cannot be
done reliably even with a regular expression!), one can tell c2nim
that ``EXPORT`` is a macro that should be expanded by c2nim too:
.. code-block:: C
#ifdef C2NIM
# def EXTERN(x) static x
#endif
// parses now!
EXTERN(int) f(void);
EXTERN(int) g(void);
``#def`` is very similar to C's ``#define``, so in general the macro definition
can be copied and pasted into a ``#def`` directive.
Limitations
===========
* C's ``,`` operator (comma operator) is not supported.
* C's ``union`` are translated to Nimrod's objects and only the first field
is included in the object type. This way there is a high chance that it is
binary compatible to the union.
* The condition in a ``do while(condition)`` statement must be ``0``.
* Lots of other small issues...

View File

@@ -93,10 +93,9 @@ proc buildTool(toolname, args: string) =
copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe)
proc inno(args: string) =
# make sure we have generated the c2nim and niminst executables:
# make sure we have generated the niminst executables:
buildTool("tools/niminst/niminst", args)
buildTool("tools/nimgrep", args)
buildTool("compiler/c2nim/c2nim", args)
exec("tools" / "niminst" / "niminst --var:version=$# inno compiler/nimrod" %
NimrodVersion)

View File

@@ -1,8 +1,6 @@
version 0.9.6
=============
- move pas2nim into its own repository
- tester: .elf
- overloading of '='; general lift mechanism

View File

@@ -37,8 +37,8 @@ UNIX. We don't believe this to be a coincidence. - Jeremy S. Anderson."""
[Documentation]
doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview;filters;trmacros"
doc: "tools;c2nim;niminst;nimgrep;gc;estp;idetools;docgen;koch"
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst;gc"
doc: "tools;niminst;nimgrep;gc;estp;idetools;docgen;koch"
pdf: "manual;lib;tut1;tut2;nimrodc;niminst;gc"
srcdoc2: "system.nim;impure/graphics;wrappers/sdl"
srcdoc2: "core/macros;pure/marshal;core/typeinfo;core/unsigned"
srcdoc2: "impure/re;pure/sockets"