diff --git a/bin/empty.txt b/bin/empty.txt index 6661420738..20f9a91e35 100644 --- a/bin/empty.txt +++ b/bin/empty.txt @@ -1 +1 @@ -This file keeps several tools from deleting this subdirectory. +This file keeps several tools from deleting this subdirectory. diff --git a/compiler/ast.nim b/compiler/ast.nim index 516954b887..0c828a6d9b 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this @@ -263,7 +263,7 @@ type sfNamedParamCall, # symbol needs named parameter call syntax in target # language; for interfacing with Objective C sfDiscardable, # returned value may be discarded implicitly - sfDestructor, # proc is destructor + sfOverriden, # proc is overriden sfGenSym # symbol is 'gensym'ed; do not add to symbol table TSymFlags* = set[TSymFlag] @@ -291,6 +291,8 @@ const sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't # require RC ops + sfCompileToCpp* = sfInfixCall # compile the module as C++ code + sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code const # getting ready for the future expr/stmt merge @@ -417,6 +419,7 @@ type # efficiency nfTransf, # node has been transformed nfSem # node has been checked for semantics + nfLL # node has gone through lambda lifting nfDotField # the call can use a dot operator nfDotSetter # the call can use a setter dot operarator nfExplicitCall # x.y() was used instead of x.y @@ -475,7 +478,7 @@ type # and first phase symbol lookup in generics skConditional, # symbol for the preprocessor (may become obsolete) skDynLib, # symbol represents a dynamic library; this is used - # internally; it does not exist in Nimrod code + # internally; it does not exist in Nim code skParam, # a parameter skGenericParam, # a generic parameter; eq in ``proc x[eq=`==`]()`` skTemp, # a temporary variable (introduced by compiler) @@ -500,7 +503,8 @@ type skStub, # symbol is a stub and not yet loaded from the ROD # file (it is loaded on demand, which may # mean: never) - skPackage # symbol is a package (used for canonicalization) + skPackage, # symbol is a package (used for canonicalization) + skAlias # an alias (needs to be resolved immediately) TSymKinds* = set[TSymKind] const @@ -552,7 +556,7 @@ type mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, mIsPartOf, mAstToStr, mParallel, mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, - mNewString, mNewStringOfCap, + mNewString, mNewStringOfCap, mParseBiggestFloat, mReset, mArray, mOpenArray, mRange, mSet, mSeq, mVarargs, mOrdinal, @@ -677,7 +681,7 @@ type heapRoot*: PRope # keeps track of the enclosing heap object that # owns this location (required by GC algorithms # employing heap snapshots or sliding views) - a*: int # location's "address", i.e. slot for temporaries + a*: int # ---------------- end of backend information ------------------------------ @@ -730,8 +734,9 @@ type # check for the owner when touching 'usedGenerics'. usedGenerics*: seq[PInstantiation] tab*: TStrTable # interface table for modules + of skLet, skVar, skField: + guard*: PSym else: nil - magic*: TMagic typ*: PType name*: PIdent @@ -784,12 +789,13 @@ type # the body of the user-defined type class # formal param list # else: unused - destructor*: PSym # destructor. warning: nil here may not necessary - # mean that there is no destructor. - # see instantiateDestructor in types.nim owner*: PSym # the 'owner' of the type sym*: PSym # types have the sym associated with them # it is used for converting types to strings + destructor*: PSym # destructor. warning: nil here may not necessary + # mean that there is no destructor. + # see instantiateDestructor in semdestruct.nim + deepCopy*: PSym # overriden 'deepCopy' operation size*: BiggestInt # the size of the type in bytes # -1 means that the size is unkwown align*: int # the type's alignment requirements @@ -870,7 +876,7 @@ const tyProc, tyString, tyError} ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator, skClosureIterator, - skMacro, skTemplate, skConverter, skEnumField, skLet, skStub} + skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias} PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfDotSetter, nfDotField, nfIsRef} @@ -1160,7 +1166,6 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode, result.sons = @[name, pattern, genericParams, params, pragmas, exceptions, body] - proc newType(kind: TTypeKind, owner: PSym): PType = new(result) result.kind = kind @@ -1170,8 +1175,8 @@ proc newType(kind: TTypeKind, owner: PSym): PType = result.id = getID() when debugIds: registerId(result) - #if result.id < 2000 then - # MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id)) + #if result.id < 2000: + # messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id)) proc mergeLoc(a: var TLoc, b: TLoc) = if a.k == low(a.k): a.k = b.k @@ -1189,6 +1194,7 @@ proc assignType(dest, src: PType) = dest.size = src.size dest.align = src.align dest.destructor = src.destructor + dest.deepCopy = src.deepCopy # this fixes 'type TLock = TSysLock': if src.sym != nil: if dest.sym != nil: @@ -1226,6 +1232,8 @@ proc copySym(s: PSym, keepId: bool = false): PSym = result.position = s.position result.loc = s.loc result.annex = s.annex # BUGFIX + if result.kind in {skVar, skLet, skField}: + result.guard = s.guard proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym = result = newSym(s.kind, newIdent, s.owner, info) @@ -1310,6 +1318,10 @@ proc newSons(father: PNode, length: int) = setLen(father.sons, length) proc skipTypes*(t: PType, kinds: TTypeKinds): PType = + ## Used throughout the compiler code to test whether a type tree contains or + ## doesn't contain a specific type/types - it is often the case that only the + ## last child nodes of a type tree need to be searched. This is a really hot + ## path within the compiler! result = t while result.kind in kinds: result = lastSon(result) @@ -1505,7 +1517,7 @@ proc isGenericRoutine*(s: PSym): bool = proc skipGenericOwner*(s: PSym): PSym = internalAssert s.kind in skProcKinds ## Generic instantiations are owned by their originating generic - ## symbol. This proc skips such owners and goes straigh to the owner + ## symbol. This proc skips such owners and goes straight to the owner ## of the generic itself (the module or the enclosing proc). result = if sfFromGeneric in s.flags: s.owner.owner else: s.owner diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index dbf13f7640..eb7ffc63e7 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -116,17 +116,16 @@ proc iiTablePut*(t: var TIITable, key, val: int) # implementation -proc skipConv*(n: PNode): PNode = - case n.kind - of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: - result = n.sons[0] - of nkHiddenStdConv, nkHiddenSubConv, nkConv: - result = n.sons[1] - else: result = n - -proc skipConvTakeType*(n: PNode): PNode = - result = n.skipConv - result.typ = n.typ +proc skipConvAndClosure*(n: PNode): PNode = + result = n + while true: + case result.kind + of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64, + nkClosure: + result = result.sons[0] + of nkHiddenStdConv, nkHiddenSubConv, nkConv: + result = result.sons[1] + else: break proc sameValue*(a, b: PNode): bool = result = false @@ -379,29 +378,30 @@ proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope = var marker = initIntSet() result = symToYamlAux(n, marker, indent, maxRecDepth) -proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope -proc debugType(n: PType): PRope = +proc debugTree(n: PNode, indent: int, maxRecDepth: int; renderType=false): PRope +proc debugType(n: PType, maxRecDepth=100): PRope = if n == nil: result = toRope("null") - else: + else: result = toRope($n.kind) if n.sym != nil: app(result, " ") app(result, n.sym.name.s) - if (n.kind != tyString) and (sonsLen(n) > 0): + if (n.kind != tyString) and (sonsLen(n) > 0) and maxRecDepth != 0: app(result, "(") - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): if i > 0: app(result, ", ") - if n.sons[i] == nil: + if n.sons[i] == nil: app(result, "null") - else: - app(result, debugType(n.sons[i])) - if n.kind == tyObject and n.n != nil: + else: + app(result, debugType(n.sons[i], maxRecDepth-1)) + if n.kind == tyObject and n.n != nil: app(result, ", node: ") - app(result, debugTree(n.n, 2, 100)) + app(result, debugTree(n.n, 2, maxRecDepth-1, renderType=true)) app(result, ")") -proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = +proc debugTree(n: PNode, indent: int, maxRecDepth: int; + renderType=false): PRope = if n == nil: result = toRope("null") else: @@ -425,6 +425,8 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = [istr, toRope(n.sym.name.s), toRope(n.sym.id)]) # [istr, symToYaml(n.sym, indent, maxRecDepth), # toRope(n.sym.id)]) + if renderType and n.sym.typ != nil: + appf(result, ",$N$1\"typ\": $2", [istr, debugType(n.sym.typ, 2)]) of nkIdent: if n.ident != nil: appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) @@ -436,7 +438,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = for i in countup(0, sonsLen(n) - 1): if i > 0: app(result, ",") appf(result, "$N$1$2", [spaces(indent + 4), debugTree(n.sons[i], - indent + 4, maxRecDepth - 1)]) + indent + 4, maxRecDepth - 1, renderType)]) appf(result, "$N$1]", [istr]) appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)]) appf(result, "$N$1}", [spaces(indent)]) diff --git a/compiler/c2nim/c2nim.nim b/compiler/c2nim/c2nim.nim deleted file mode 100644 index 9b12b9e47f..0000000000 --- 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 3934eea63d..0000000000 --- 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 2e31af5285..0000000000 --- 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 84b4c4dfb6..0000000000 --- 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 cfeda63ed6..0000000000 --- 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 16bc59058f..0000000000 --- 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 715e9e43b2..0000000000 --- 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> -{ -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& 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 859bfc206f..0000000000 --- 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 51509e253b..0000000000 --- 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 bf3027cfcf..0000000000 --- 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 24c6d6425f..0000000000 --- a/compiler/c2nim/tests/vincent.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include - -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 b4e761ee14..0000000000 --- a/compiler/c2nim/tests/vincent.h +++ /dev/null @@ -1,3 +0,0 @@ -struct foo { - int x,y,z; -}; diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 71e23aa1dd..adcc95e846 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -29,7 +29,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, # beware of 'result = p(result)'. We may need to allocate a temporary: if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri): # Great, we can use 'd': - if d.k == locNone: getTemp(p, typ.sons[0], d) + if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true) elif d.k notin {locExpr, locTemp} and not hasNoInit(ri): # reset before pass as 'result' var: resetLoc(p, d) @@ -38,7 +38,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, line(p, cpsStmts, pl) else: var tmp: TLoc - getTemp(p, typ.sons[0], tmp) + getTemp(p, typ.sons[0], tmp, needsInit=true) app(pl, addrLoc(tmp)) app(pl, ~");$n") line(p, cpsStmts, pl) @@ -195,7 +195,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = # beware of 'result = p(result)'. We may need to allocate a temporary: if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri): # Great, we can use 'd': - if d.k == locNone: getTemp(p, typ.sons[0], d) + if d.k == locNone: + getTemp(p, typ.sons[0], d, needsInit=true) elif d.k notin {locExpr, locTemp} and not hasNoInit(ri): # reset before pass as 'result' var: resetLoc(p, d) @@ -203,7 +204,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = genCallPattern() else: var tmp: TLoc - getTemp(p, typ.sons[0], tmp) + getTemp(p, typ.sons[0], tmp, needsInit=true) app(pl, addrLoc(tmp)) genCallPattern() genAssignment(p, d, tmp, {}) # no need for deep copying @@ -278,14 +279,14 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = # beware of 'result = p(result)'. We always allocate a temporary: if d.k in {locTemp, locNone}: # We already got a temp. Great, special case it: - if d.k == locNone: getTemp(p, typ.sons[0], d) + if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true) app(pl, ~"Result: ") app(pl, addrLoc(d)) app(pl, ~"];$n") line(p, cpsStmts, pl) else: var tmp: TLoc - getTemp(p, typ.sons[0], tmp) + getTemp(p, typ.sons[0], tmp, needsInit=true) app(pl, addrLoc(tmp)) app(pl, ~"];$n") line(p, cpsStmts, pl) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 4698082f1a..b5817de05a 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -359,6 +359,32 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) else: internalError("genAssignment: " & $ty.kind) +proc genDeepCopy(p: BProc; dest, src: TLoc) = + var ty = skipTypes(dest.t, abstractVarRange) + case ty.kind + of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr: + # XXX optimize this + linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n", + addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)) + of tySequence, tyString: + linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n", + addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)) + of tyOpenArray, tyVarargs: + linefmt(p, cpsStmts, + "#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n", + addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)) + of tySet: + if mapType(ty) == ctArray: + useStringh(p.module) + linefmt(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n", + rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))) + else: + linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + of tyPointer, tyChar, tyBool, tyEnum, tyCString, + tyInt..tyUInt64, tyRange, tyVar: + linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + else: internalError("genDeepCopy: " & $ty.kind) + proc getDestLoc(p: BProc, d: var TLoc, typ: PType) = if d.k == locNone: getTemp(p, typ, d) @@ -1191,7 +1217,6 @@ proc genOf(p: BProc, n: PNode, d: var TLoc) = genOf(p, n.sons[1], n.sons[2].typ, d) proc genRepr(p: BProc, e: PNode, d: var TLoc) = - # XXX we don't generate keep alive info for now here var a: TLoc initLocExpr(p, e.sons[1], a) var t = skipTypes(e.sons[1].typ, abstractVarRange) @@ -1260,6 +1285,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)") else: unaryExpr(p, e, d, "$1Len0") of tyCString: + useStringh(p.module) if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)") else: unaryExpr(p, e, d, "strlen($1)") of tyString, tySequence: @@ -1578,25 +1604,25 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mGetTypeInfo: genGetTypeInfo(p, e, d) of mSwap: genSwap(p, e, d) of mUnaryLt: - if not (optOverflowCheck in p.options): unaryExpr(p, e, d, "$1 - 1") + if optOverflowCheck notin p.options: unaryExpr(p, e, d, "($1 - 1)") else: unaryExpr(p, e, d, "#subInt($1, 1)") of mPred: # XXX: range checking? - if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "$1 - $2") + if optOverflowCheck notin p.options: binaryExpr(p, e, d, "($1 - $2)") else: binaryExpr(p, e, d, "#subInt($1, $2)") of mSucc: # XXX: range checking? - if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "$1 + $2") + if optOverflowCheck notin p.options: binaryExpr(p, e, d, "($1 + $2)") else: binaryExpr(p, e, d, "#addInt($1, $2)") of mInc: - if not (optOverflowCheck in p.options): + if optOverflowCheck notin p.options: binaryStmt(p, e, d, "$1 += $2;$n") elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64: binaryStmt(p, e, d, "$1 = #addInt64($1, $2);$n") else: binaryStmt(p, e, d, "$1 = #addInt($1, $2);$n") of ast.mDec: - if not (optOverflowCheck in p.options): + if optOverflowCheck notin p.options: binaryStmt(p, e, d, "$1 -= $2;$n") elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64: binaryStmt(p, e, d, "$1 = #subInt64($1, $2);$n") @@ -1640,7 +1666,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet, mInSet: genSetOp(p, e, d, op) - of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit: + of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit, + mParseBiggestFloat: var opr = e.sons[0].sym if lfNoDecl notin opr.loc.flags: discard cgsym(p.module, opr.loc.r.ropeToStr) @@ -1658,6 +1685,12 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mParallel: let n = semparallel.liftParallel(p.module.module, e) expr(p, n, d) + of mDeepCopy: + var a, b: TLoc + let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1] + initLocExpr(p, x, a) + initLocExpr(p, e.sons[2], b) + genDeepCopy(p, a, b) else: internalError(e.info, "genMagicExpr: " & $op) proc genConstExpr(p: BProc, n: PNode): PRope @@ -1877,7 +1910,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of skVar, skForVar, skResult, skLet: if sfGlobal in sym.flags: genVarPrototype(p.module, sym) if sym.loc.r == nil or sym.loc.t == nil: - internalError(n.info, "expr: var not init " & sym.name.s) + #echo "FAILED FOR PRCO ", p.prc.name.s + internalError n.info, "expr: var not init " & sym.name.s & "_" & $sym.id if sfThread in sym.flags: accessThreadLocalVar(p, sym) if emulatedThreadVars(): @@ -1888,11 +1922,14 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = putLocIntoDest(p, d, sym.loc) of skTemp: if sym.loc.r == nil or sym.loc.t == nil: - internalError(n.info, "expr: temp not init " & sym.name.s) + #echo "FAILED FOR PRCO ", p.prc.name.s + #echo renderTree(p.prc.ast, {renderIds}) + internalError(n.info, "expr: temp not init " & sym.name.s & "_" & $sym.id) putLocIntoDest(p, d, sym.loc) of skParam: if sym.loc.r == nil or sym.loc.t == nil: - internalError(n.info, "expr: param not init " & sym.name.s) + #echo "FAILED FOR PRCO ", p.prc.name.s + internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id) putLocIntoDest(p, d, sym.loc) else: internalError(n.info, "expr(" & $sym.kind & "); unknown symbol") of nkNilLit: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index a8cfa57e46..8b0a8e9bb5 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2013 Andreas Rumpf +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -24,10 +24,29 @@ proc registerGcRoot(p: BProc, v: PSym) = linefmt(p.module.initProc, cpsStmts, "#nimRegisterGlobalMarker($1);$n", prc) +proc isAssignedImmediately(n: PNode): bool {.inline.} = + if n.kind == nkEmpty: return false + if isInvalidReturnType(n.typ): + # var v = f() + # is transformed into: var v; f(addr v) + # where 'f' **does not** initialize the result! + return false + result = true + proc genVarTuple(p: BProc, n: PNode) = var tup, field: TLoc if n.kind != nkVarTuple: internalError(n.info, "genVarTuple") var L = sonsLen(n) + + # if we have a something that's been captured, use the lowering instead: + var useLowering = false + for i in countup(0, L-3): + if n[i].kind != nkSym: + useLowering = true; break + if useLowering: + genStmts(p, lowerTupleUnpacking(n, p.prc)) + return + genLineDir(p, n) initLocExpr(p, n.sons[L-1], tup) var t = tup.t @@ -40,7 +59,7 @@ proc genVarTuple(p: BProc, n: PNode) = registerGcRoot(p, v) else: assignLocalVar(p, v) - initLocalVar(p, v, immediateAsgn=true) + initLocalVar(p, v, immediateAsgn=isAssignedImmediately(n[L-1])) initLoc(field, locExpr, t.sons[i], tup.s) if t.kind == tyTuple: field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)]) @@ -146,12 +165,16 @@ proc genBreakState(p: BProc, n: PNode) = # lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)]) proc genVarPrototypeAux(m: BModule, sym: PSym) + proc genSingleVar(p: BProc, a: PNode) = var v = a.sons[0].sym if sfCompileTime in v.flags: return var targetProc = p - var immediateAsgn = a.sons[2].kind != nkEmpty if sfGlobal in v.flags: + if v.flags * {sfImportc, sfExportc} == {sfImportc} and + a.sons[2].kind == nkEmpty and + v.loc.flags * {lfHeader, lfNoDecl} != {}: + return if sfPure in v.flags: # v.owner.kind != skModule: targetProc = p.module.preInitProc @@ -170,9 +193,9 @@ proc genSingleVar(p: BProc, a: PNode) = registerGcRoot(p, v) else: assignLocalVar(p, v) - initLocalVar(p, v, immediateAsgn) + initLocalVar(p, v, isAssignedImmediately(a.sons[2])) - if immediateAsgn: + if a.sons[2].kind != nkEmpty: genLineDir(targetProc, a) loadInto(targetProc, a.sons[0], a.sons[2], v.loc) @@ -809,7 +832,14 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = discard cgsym(p.module, "E_Base") linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint) linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint) - linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) + if isDefined("nimStdSetjmp"): + linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) + elif isDefined("nimSigSetjmp"): + linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint) + elif isDefined("nimRawSetjmp"): + linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint) + else: + linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) startBlock(p, "if ($1.status == 0) {$n", [safePoint]) var length = sonsLen(t) add(p.nestedTryStmts, t) diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index 26f4746598..a5bf9e7a74 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -19,7 +19,7 @@ type proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) proc genCaseRange(p: BProc, branch: PNode) -proc getTemp(p: BProc, t: PType, result: var TLoc) +proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) = if n == nil: return diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 8e762ce279..fc6febc6ff 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -122,6 +122,7 @@ proc mapSetType(typ: PType): TCTypeKind = else: result = ctArray proc mapType(typ: PType): TCTypeKind = + ## Maps a nimrod type to a C type case typ.kind of tyNone, tyStmt: result = ctVoid of tyBool: result = ctBool @@ -453,7 +454,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope, appf(result, " {$n", [name]) var desc = getRecordFields(m, typ, check) - if (desc == nil) and not hasField: + if desc == nil and not hasField: appf(result, "char dummy;$n", []) else: app(result, desc) @@ -722,7 +723,7 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope = if objtype.sym == nil: internalError(d.info, "anonymous obj with discriminator") result = ropef("NimDT_$1_$2", [ - toRope(objtype.sym.name.s.mangle), toRope(d.name.s.mangle)]) + toRope(objtype.id), toRope(d.name.s.mangle)]) proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope = discard cgsym(m, "TNimNode") @@ -895,11 +896,20 @@ type include ccgtrav -proc genTypeInfo(m: BModule, t: PType): PRope = +proc genDeepCopyProc(m: BModule; s: PSym; result: PRope) = + genProc(m, s) + appf(m.s[cfsTypeInit3], "$1.deepcopy = (N_NIMCALL_PTR(void*, void*)) $2;$n", + [result, s.loc.r]) + +proc genTypeInfo(m: BModule, t: PType): PRope = + let origType = t var t = getUniqueType(t) result = ropef("NTI$1", [toRope(t.id)]) if containsOrIncl(m.typeInfoMarker, t.id): return con("(&".toRope, result, ")".toRope) + + # getUniqueType doesn't skip tyDistinct when that has an overriden operation: + while t.kind == tyDistinct: t = t.lastSon let owner = t.skipTypes(typedescPtrs).owner.getModule if owner != m.module: # make sure the type info is created in the owner module @@ -936,6 +946,10 @@ proc genTypeInfo(m: BModule, t: PType): PRope = # results are not deterministic! genTupleInfo(m, t, result) else: internalError("genTypeInfo(" & $t.kind & ')') + if t.deepCopy != nil: + genDeepCopyProc(m, t.deepCopy, result) + elif origType.deepCopy != nil: + genDeepCopyProc(m, origType.deepCopy, result) result = con("(&".toRope, result, ")".toRope) proc genTypeSection(m: BModule, n: PNode) = diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 04983d6a4f..65957584a1 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -89,9 +89,15 @@ proc getUniqueType*(key: PType): PType = of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr, tyFieldAccessor: internalError("GetUniqueType") - of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, - tyConst, tyIter, tyStatic: + of tyDistinct: + if key.deepCopy != nil: result = key + else: result = getUniqueType(lastSon(key)) + of tyGenericInst, tyOrdinal, tyMutable, tyConst, tyIter, tyStatic: result = getUniqueType(lastSon(key)) + #let obj = lastSon(key) + #if obj.sym != nil and obj.sym.name.s == "TOption": + # echo "for ", typeToString(key), " I returned " + # debug result of tyArrayConstr, tyGenericInvokation, tyGenericBody, tyOpenArray, tyArray, tySet, tyRange, tyTuple, tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar: @@ -124,7 +130,7 @@ proc getUniqueType*(key: PType): PType = if t != nil and sameType(t, key): return t idTablePut(gTypeTable[k], key, key) - result = key + result = key of tyEnum: result = PType(idTableGet(gTypeTable[k], key)) if result == nil: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index e2f3b5ab0a..359fa33098 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -13,7 +13,7 @@ import ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, intsets, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, - times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, + times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings, semparallel @@ -295,6 +295,7 @@ proc postStmtActions(p: BProc) {.inline.} = proc accessThreadLocalVar(p: BProc, s: PSym) proc emulatedThreadVars(): bool {.inline.} +proc genProc(m: BModule, prc: PSym) include "ccgtypes.nim" @@ -398,7 +399,7 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = if not immediateAsgn: constructLoc(p, v.loc) -proc getTemp(p: BProc, t: PType, result: var TLoc) = +proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = inc(p.labels) if gCmd == cmdCompileToLLVM: result.r = con("%LOC", toRope(p.labels)) @@ -410,7 +411,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc) = result.t = getUniqueType(t) result.s = OnStack result.flags = {} - constructLoc(p, result, isTemp=true) + constructLoc(p, result, not needsInit) proc keepAlive(p: BProc, toKeepAlive: TLoc) = when false: @@ -574,7 +575,6 @@ proc fixLabel(p: BProc, labl: TLabel) = proc genVarPrototype(m: BModule, sym: PSym) proc requestConstImpl(p: BProc, sym: PSym) -proc genProc(m: BModule, prc: PSym) proc genStmts(p: BProc, t: PNode) proc expr(p: BProc, n: PNode, d: var TLoc) proc genProcPrototype(m: BModule, sym: PSym) @@ -949,13 +949,23 @@ proc genFilenames(m: BModule): PRope = proc genMainProc(m: BModule) = const + # The use of a volatile function pointer to call Pre/NimMainInner + # prevents inlining of the NimMainInner function and dependent + # functions, which might otherwise merge their stack frames. PreMainBody = - "\tsystemDatInit();$N" & + "void PreMainInner() {$N" & "\tsystemInit();$N" & "$1" & "$2" & "$3" & - "$4" + "}$N$N" & + "void PreMain() {$N" & + "\tvoid (*volatile inner)();$N" & + "\tsystemDatInit();$N" & + "\tinner = PreMainInner;$N" & + "$4" & + "\t(*inner)();$N" & + "}$N$N" MainProcs = "\tNimMain();$N" @@ -964,9 +974,15 @@ proc genMainProc(m: BModule) = MainProcs & "\treturn nim_program_result;$N" NimMainBody = - "N_CDECL(void, NimMain)(void) {$N" & - "\tPreMain();$N" & + "N_CDECL(void, NimMainInner)(void) {$N" & "$1" & + "}$N$N" & + "N_CDECL(void, NimMain)(void) {$N" & + "\tvoid (*volatile inner)();$N" & + "\tPreMain();$N" & + "\tinner = NimMainInner;$N" & + "$2" & + "\t(*inner)();$N" & "}$N$N" PosixNimMain = @@ -1034,14 +1050,15 @@ proc genMainProc(m: BModule) = if optEndb in gOptions: gBreakpoints.app(m.genFilenames) - let initStackBottomCall = if emulatedThreadVars() or - platform.targetOS == osStandalone: "".toRope - else: ropecg(m, "\t#initStackBottom();$N") + let initStackBottomCall = + if emulatedThreadVars() or + platform.targetOS == osStandalone: "".toRope + else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N") inc(m.labels) - appcg(m, m.s[cfsProcs], "void PreMain() {$N" & PreMainBody & "}$N$N", [ - mainDatInit, initStackBottomCall, gBreakpoints, otherModsInit]) + appcg(m, m.s[cfsProcs], PreMainBody, [ + mainDatInit, gBreakpoints, otherModsInit, initStackBottomCall]) - appcg(m, m.s[cfsProcs], nimMain, [mainModInit, toRope(m.labels)]) + appcg(m, m.s[cfsProcs], nimMain, [mainModInit, initStackBottomCall, toRope(m.labels)]) if optNoMain notin gGlobalOptions: appcg(m, m.s[cfsProcs], otherMain, []) diff --git a/compiler/commands.nim b/compiler/commands.nim index 38c8dd2949..87e94d9c9d 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -80,9 +80,9 @@ proc writeVersionInfo(pass: TCmdLinePass) = platform.OS[platform.hostOS].name, CPU[platform.hostCPU].name])) - const gitHash = gorge("git log -n 1 --format=%H") + discard """const gitHash = gorge("git log -n 1 --format=%H") if gitHash.strip.len == 40: - msgWriteln("git hash: " & gitHash) + msgWriteln("git hash: " & gitHash)""" msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine & usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas & @@ -291,8 +291,12 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = of "excludepath": expectArg(switch, arg, pass, info) let path = processPath(arg) - lists.excludeStr(options.searchPaths, path) - lists.excludeStr(options.lazyPaths, path) + lists.excludePath(options.searchPaths, path) + lists.excludePath(options.lazyPaths, path) + if (len(path) > 0) and (path[len(path) - 1] == DirSep): + let strippedPath = path[0 .. (len(path) - 2)] + lists.excludePath(options.searchPaths, strippedPath) + lists.excludePath(options.lazyPaths, strippedPath) of "nimcache": expectArg(switch, arg, pass, info) options.nimcacheDir = processPath(arg) @@ -311,6 +315,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = of "undef", "u": expectArg(switch, arg, pass, info) undefSymbol(arg) + of "symbol": + expectArg(switch, arg, pass, info) + declareSymbol(arg) of "compile": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: processCompile(arg) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 17bb5db55a..6d144ad96e 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -19,6 +19,9 @@ var gSymbols: PStringTable proc defineSymbol*(symbol: string) = gSymbols[symbol] = "true" +proc declareSymbol*(symbol: string) = + gSymbols[symbol] = "unknown" + proc undefSymbol*(symbol: string) = gSymbols[symbol] = "false" @@ -27,6 +30,7 @@ proc isDefined*(symbol: string): bool = result = gSymbols[symbol] == "true" proc isDefined*(symbol: PIdent): bool = isDefined(symbol.s) +proc isDeclared*(symbol: PIdent): bool = gSymbols.hasKey(symbol.s) iterator definedSymbolNames*: string = for key, val in pairs(gSymbols): @@ -37,6 +41,38 @@ proc countDefinedSymbols*(): int = for key, val in pairs(gSymbols): if val == "true": inc(result) +# For ease of bootstrapping, we keep there here and not in the global config +# file for now: +const + additionalSymbols = """ + x86 itanium x8664 + msdos mswindows win32 unix posix sunos bsd macintosh RISCOS doslike hpux + mac + + hppa hp9000 hp9000s300 hp9000s700 hp9000s800 hp9000s820 ELATE sparcv9 + + ecmascript js nimrodvm nimffi nimdoc cpp objc + gcc llvmgcc clang lcc bcc dmc wcc vcc tcc pcc ucc icl + boehmgc gcmarkandsweep gcgenerational nogc gcUseBitvectors + endb profiler + executable guiapp consoleapp library dll staticlib + + quick + release debug + useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler + nodejs kwin nimfix + + usesysassert usegcassert tinyC useFFI + useStdoutAsStdmsg createNimRtl + booting fulldebug corruption nimsuperops noSignalHandler useGnuReadline + noCaas noDocGen noBusyWaiting nativeStackTrace useNodeIds selftest + reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize + debugExecProcesses pcreDll useLipzipSrc + preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime + + nimStdSetjmp nimRawSetjmp nimSigSetjmp + """.split + proc initDefines*() = gSymbols = newStringTable(modeStyleInsensitive) defineSymbol("nimrod") # 'nimrod' is always defined @@ -50,8 +86,21 @@ proc initDefines*() = defineSymbol("nimunion") defineSymbol("nimnewshared") defineSymbol("nimrequiresnimframe") + defineSymbol("nimparsebiggestfloatmagic") + defineSymbol("nimalias") # add platform specific symbols: + for c in low(CPU)..high(CPU): + declareSymbol("cpu" & $CPU[c].bit) + declareSymbol(normalize(EndianToStr[CPU[c].endian])) + declareSymbol(CPU[c].name) + for o in low(platform.OS)..high(platform.OS): + declareSymbol(platform.OS[o].name) + + for a in additionalSymbols: + declareSymbol(a) + + # ----------------------------------------------------------- case targetCPU of cpuI386: defineSymbol("x86") of cpuIa64: defineSymbol("itanium") @@ -87,5 +136,10 @@ proc initDefines*() = defineSymbol(normalize(EndianToStr[CPU[targetCPU].endian])) defineSymbol(CPU[targetCPU].name) defineSymbol(platform.OS[targetOS].name) + declareSymbol("emulatedthreadvars") if platform.OS[targetOS].props.contains(ospLacksThreadVars): defineSymbol("emulatedthreadvars") + case targetOS + of osSolaris, osNetbsd, osFreebsd, osOpenbsd, osMacosx: + defineSymbol("nimRawSetjmp") + else: discard diff --git a/compiler/guards.nim b/compiler/guards.nim index 4cf06fe026..431de61566 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -758,7 +758,7 @@ proc pleViaModelRec(m: var TModel; a, b: PNode): TImplication = result = impliesLe(fact, a, b) if result != impUnknown: return result if sameTree(y, a): - result = ple(m, x, b) + result = ple(m, b, x) if result != impUnknown: return result proc pleViaModel(model: TModel; aa, bb: PNode): TImplication = diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 6687e2e8ec..dfe498e472 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -10,6 +10,25 @@ # This is the JavaScript code generator. # Soon also a Luajit code generator. ;-) +discard """ +The JS code generator contains only 2 tricks: + +Trick 1 +------- +Some locations (for example 'var int') require "fat pointers" (``etyBaseIndex``) +which are pairs (array, index). The derefence operation is then 'array[index]'. +Check ``mapType`` for the details. + +Trick 2 +------- +It is preferable to generate '||' and '&&' if possible since that is more +idiomatic and hence should be friendlier for the JS JIT implementation. However +code like ``foo and (let bar = baz())`` cannot be translated this way. Instead +the expressions need to be transformed into statements. ``isSimpleExpr`` +implements the required case distinction. +""" + + import ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os, @@ -833,8 +852,8 @@ proc genSwap(p: PProc, n: PNode) = "local $1 = $2; $2 = $3; $3 = $1;$n", [ tmp, a.address, b.address]) tmp = tmp2 - appf(p.body, "var $1 = $2; $2 = $3; $3 = $1" | - "local $1 = $2; $2 = $3; $3 = $1", [tmp, a.res, b.res]) + appf(p.body, "var $1 = $2; $2 = $3; $3 = $1;" | + "local $1 = $2; $2 = $3; $3 = $1;", [tmp, a.res, b.res]) proc getFieldPosition(f: PNode): int = case f.kind @@ -881,14 +900,15 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) = a, b: TCompRes first: BiggestInt r.typ = etyBaseIndex - gen(p, n.sons[0], a) - gen(p, n.sons[1], b) + let m = if n.kind == nkHiddenAddr: n.sons[0] else: n + gen(p, m.sons[0], a) + gen(p, m.sons[1], b) internalAssert a.typ != etyBaseIndex and b.typ != etyBaseIndex r.address = a.res - var typ = skipTypes(n.sons[0].typ, abstractPtrs) + var typ = skipTypes(m.sons[0].typ, abstractPtrs) if typ.kind in {tyArray, tyArrayConstr}: first = firstOrd(typ.sons[0]) else: first = 0 - if optBoundsCheck in p.options and not isConstExpr(n.sons[1]): + if optBoundsCheck in p.options and not isConstExpr(m.sons[1]): useMagic(p, "chckIndx") r.res = ropef("chckIndx($1, $2, $3.length)-$2", [b.res, toRope(first), a.res]) @@ -1321,7 +1341,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of mLengthSeq, mLengthOpenArray, mLengthArray: unaryExpr(p, n, r, "", "$1.length") of mHigh: - if skipTypes(n.sons[0].typ, abstractVar).kind == tyString: + if skipTypes(n.sons[1].typ, abstractVar).kind == tyString: unaryExpr(p, n, r, "", "($1.length-2)") else: unaryExpr(p, n, r, "", "($1.length-1)") @@ -1351,7 +1371,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of mEcho: genEcho(p, n, r) of mSlurp, mStaticExec: localError(n.info, errXMustBeCompileTime, n.sons[0].sym.name.s) - of mCopyStr: binaryExpr(p, n, r, "", "($1.slice($2,-1))") + of mCopyStr: binaryExpr(p, n, r, "", "($1.slice($2))") of mCopyStrLast: ternaryExpr(p, n, r, "", "($1.slice($2, ($3)+1).concat(0))") of mNewString: unaryExpr(p, n, r, "mnewString", "mnewString($1)") of mNewStringOfCap: unaryExpr(p, n, r, "mnewString", "mnewString(0)") @@ -1532,6 +1552,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = genSym(p, n, r) of nkCharLit..nkInt64Lit: r.res = toRope(n.intVal) + r.kind = resExpr of nkNilLit: if isEmptyType(n.typ): discard @@ -1539,8 +1560,10 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = r.typ = etyBaseIndex r.address = toRope"null" | toRope"nil" r.res = toRope"0" + r.kind = resExpr else: r.res = toRope"null" | toRope"nil" + r.kind = resExpr of nkStrLit..nkTripleStrLit: if skipTypes(n.typ, abstractVarRange).kind == tyString: useMagic(p, "cstrToNimstr") @@ -1556,6 +1579,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = if f > 0.0: r.res = toRope"Infinity" else: r.res = toRope"-Infinity" else: r.res = toRope(f.toStrMaxPrecision) + r.kind = resExpr of nkCallKinds: if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic != mNone): genMagic(p, n, r) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index c5b9d0f006..62e13b9c42 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -103,43 +103,51 @@ discard """ """ +# Important things to keep in mind: +# * Don't base the analysis on nkProcDef et al. This doesn't work for +# instantiated (formerly generic) procs. The analysis has to look at nkSym. +# This also means we need to prevent the same proc is processed multiple +# times via the 'processed' set. +# * Keep in mind that the owner of some temporaries used to be unreliable. +# * For closure iterators we merge the "real" potential closure with the +# local storage requirements for efficiency. This means closure iterators +# have slightly different semantics from ordinary closures. + + const upName* = ":up" # field name for the 'up' reference - paramName* = ":env" + paramName* = ":envP" envName* = ":env" type - PInnerContext = ref TInnerContext POuterContext = ref TOuterContext + TIter = object + fn, closureParam, state, resultSym: PSym # most are only valid if + # fn.kind == skClosureIterator + obj: PType + PEnv = ref TEnv - TDep = tuple[e: PEnv, field: PSym] TEnv {.final.} = object of TObject - attachedNode: PNode - createdVar: PSym # if != nil it is a used environment + attachedNode, replacementNode: PNode + createdVar: PNode # if != nil it is a used environment; for closure + # iterators this can be 'envParam.env' createdVarComesFromIter: bool capturedVars: seq[PSym] # captured variables in this environment - deps: seq[TDep] # dependencies - up: PEnv + up, next: PEnv # outer scope and next to keep all in a list + upField: PSym # if != nil the dependency to the outer scope is used obj: PType - - TInnerContext = object - fn: PSym - closureParam: PSym - localsToAccess: TIdNodeTable + fn: PSym # function that belongs to this scope; + # if up.fn != fn then we cross function boundaries. + # This is an important case to consider. + vars: TIntSet # variables belonging to this environment TOuterContext = object fn: PSym # may also be a module! - currentEnv: PEnv - isIter: bool # first class iterator? + head: PEnv capturedVars, processed: TIntSet - localsToEnv: TIdTable # PSym->PEnv mapping localsToAccess: TIdNodeTable lambdasToEnv: TIdTable # PSym->PEnv mapping - up: POuterContext - - closureParam, state, resultSym: PSym # only if isIter - obj: PType # only if isIter proc getStateType(iter: PSym): PType = var n = newNodeI(nkRange, iter.info) @@ -147,12 +155,20 @@ proc getStateType(iter: PSym): PType = addSon(n, newIntNode(nkIntLit, 0)) result = newType(tyRange, iter) result.n = n - rawAddSon(result, getSysType(tyInt)) + var intType = nilOrSysInt() + if intType.isNil: intType = newType(tyInt, iter) + rawAddSon(result, intType) proc createStateField(iter: PSym): PSym = result = newSym(skField, getIdent(":state"), iter, iter.info) result.typ = getStateType(iter) +proc createEnvObj(owner: PSym): PType = + # YYY meh, just add the state field for every closure for now, it's too + # hard to figure out if it comes from a closure iterator: + result = createObj(owner, owner.info) + rawAddField(result, createStateField(owner)) + proc newIterResult(iter: PSym): PSym = if resultPos < iter.ast.len: result = iter.ast.sons[resultPos].sym @@ -164,6 +180,7 @@ proc newIterResult(iter: PSym): PSym = iter.ast.add newSymNode(result) proc addHiddenParam(routine: PSym, param: PSym) = + assert param.kind == skParam var params = routine.ast.sons[paramsPos] # -1 is correct here as param.position is 0 based but we have at position 0 # some nkEffect node: @@ -175,7 +192,7 @@ proc addHiddenParam(routine: PSym, param: PSym) = proc getHiddenParam(routine: PSym): PSym = let params = routine.ast.sons[paramsPos] let hidden = lastSon(params) - assert hidden.kind == nkSym + internalAssert hidden.kind == nkSym and hidden.sym.kind == skParam result = hidden.sym proc getEnvParam(routine: PSym): PSym = @@ -184,161 +201,191 @@ proc getEnvParam(routine: PSym): PSym = if hidden.kind == nkSym and hidden.sym.name.s == paramName: result = hidden.sym -proc initIterContext(c: POuterContext, iter: PSym) = - c.fn = iter - c.capturedVars = initIntSet() +proc initIter(iter: PSym): TIter = + result.fn = iter + if iter.kind == skClosureIterator: + var cp = getEnvParam(iter) + if cp == nil: + result.obj = createEnvObj(iter) - var cp = getEnvParam(iter) - if cp == nil: - c.obj = createObj(iter, iter.info) - - cp = newSym(skParam, getIdent(paramName), iter, iter.info) - incl(cp.flags, sfFromGeneric) - cp.typ = newType(tyRef, iter) - rawAddSon(cp.typ, c.obj) - addHiddenParam(iter, cp) - - c.state = createStateField(iter) - addField(c.obj, c.state) - else: - c.obj = cp.typ.sons[0] - assert c.obj.kind == tyObject - if c.obj.n.len > 0: - c.state = c.obj.n[0].sym + cp = newSym(skParam, getIdent(paramName), iter, iter.info) + incl(cp.flags, sfFromGeneric) + cp.typ = newType(tyRef, iter) + rawAddSon(cp.typ, result.obj) + addHiddenParam(iter, cp) else: - c.state = createStateField(iter) - addField(c.obj, c.state) + result.obj = cp.typ.sons[0] + assert result.obj.kind == tyObject + internalAssert result.obj.n.len > 0 + result.state = result.obj.n[0].sym + result.closureParam = cp + if iter.typ.sons[0] != nil: + result.resultSym = newIterResult(iter) + #iter.ast.add(newSymNode(c.resultSym)) - c.closureParam = cp - if iter.typ.sons[0] != nil: - c.resultSym = newIterResult(iter) - #iter.ast.add(newSymNode(c.resultSym)) - -proc newOuterContext(fn: PSym, up: POuterContext = nil): POuterContext = +proc newOuterContext(fn: PSym): POuterContext = new(result) result.fn = fn result.capturedVars = initIntSet() result.processed = initIntSet() initIdNodeTable(result.localsToAccess) - initIdTable(result.localsToEnv) initIdTable(result.lambdasToEnv) - result.isIter = fn.kind == skClosureIterator - if result.isIter: initIterContext(result, fn) -proc newInnerContext(fn: PSym): PInnerContext = +proc newEnv(o: POuterContext; up: PEnv, n: PNode; owner: PSym): PEnv = new(result) - result.fn = fn - initIdNodeTable(result.localsToAccess) - -proc newEnv(outerProc: PSym, up: PEnv, n: PNode): PEnv = - new(result) - result.deps = @[] result.capturedVars = @[] - result.obj = createObj(outerProc, outerProc.info) result.up = up result.attachedNode = n + result.fn = owner + result.vars = initIntSet() + result.next = o.head + o.head = result + if owner.kind != skModule and (up == nil or up.fn != owner): + let param = getEnvParam(owner) + if param != nil: + result.obj = param.typ.sons[0] + assert result.obj.kind == tyObject + if result.obj.isNil: + result.obj = createEnvObj(owner) proc addCapturedVar(e: PEnv, v: PSym) = for x in e.capturedVars: if x == v: return - # XXX meh, just add the state field for every closure for now, it's too - # hard to figure out if it comes from a closure iterator: - if e.obj.n.len == 0: addField(e.obj, createStateField(v.owner)) e.capturedVars.add(v) addField(e.obj, v) - -proc addDep(e, d: PEnv, owner: PSym): PSym = - for x, field in items(e.deps): - if x == d: return field - var pos = sonsLen(e.obj.n) - result = newSym(skField, getIdent(upName & $pos), owner, owner.info) - result.typ = newType(tyRef, owner) - result.position = pos - assert d.obj != nil - rawAddSon(result.typ, d.obj) - addField(e.obj, result) - e.deps.add((d, result)) -proc newCall(a, b: PSym): PNode = +proc newCall(a: PSym, b: PNode): PNode = result = newNodeI(nkCall, a.info) result.add newSymNode(a) - result.add newSymNode(b) + result.add b -proc isInnerProc(s, outerProc: PSym): bool {.inline.} = - result = s.kind in {skProc, skMethod, skConverter, skClosureIterator} and - s.skipGenericOwner == outerProc +proc isInnerProc(s, outerProc: PSym): bool = + if s.kind in {skProc, skMethod, skConverter, skClosureIterator}: + var owner = s.skipGenericOwner + while true: + if owner.isNil: return false + if owner == outerProc: return true + owner = owner.owner #s.typ.callConv == ccClosure -proc addClosureParam(i: PInnerContext, e: PEnv) = - var cp = getEnvParam(i.fn) +proc addClosureParam(fn: PSym; e: PEnv) = + var cp = getEnvParam(fn) if cp == nil: - cp = newSym(skParam, getIdent(paramName), i.fn, i.fn.info) + cp = newSym(skParam, getIdent(paramName), fn, fn.info) incl(cp.flags, sfFromGeneric) - cp.typ = newType(tyRef, i.fn) + cp.typ = newType(tyRef, fn) rawAddSon(cp.typ, e.obj) - addHiddenParam(i.fn, cp) - else: - e.obj = cp.typ.sons[0] - assert e.obj.kind == tyObject - i.closureParam = cp - #echo "closure param added for ", i.fn.name.s, " ", i.fn.id - -proc dummyClosureParam(o: POuterContext, i: PInnerContext) = - var e = o.currentEnv - if idTableGet(o.lambdasToEnv, i.fn) == nil: - idTablePut(o.lambdasToEnv, i.fn, e) - if i.closureParam == nil: addClosureParam(i, e) + addHiddenParam(fn, cp) + #else: + #cp.typ.sons[0] = e.obj + #assert e.obj.kind == tyObject proc illegalCapture(s: PSym): bool {.inline.} = result = skipTypes(s.typ, abstractInst).kind in {tyVar, tyOpenArray, tyVarargs} or s.kind == skResult -proc captureVar(o: POuterContext, i: PInnerContext, local: PSym, - info: TLineInfo) = - # for inlined variables the owner is still wrong, so it can happen that it's - # not a captured variable at all ... *sigh* - var it = PEnv(idTableGet(o.localsToEnv, local)) - if it == nil: return - - if illegalCapture(local) or o.fn.id != local.owner.id or - i.fn.typ.callConv notin {ccClosure, ccDefault}: - # Currently captures are restricted to a single level of nesting: - localError(info, errIllegalCaptureX, local.name.s) - i.fn.typ.callConv = ccClosure - #echo "captureVar ", i.fn.name.s, i.fn.id, " ", local.name.s, local.id - - incl(i.fn.typ.flags, tfCapturesEnv) - - # we need to remember which inner most closure belongs to this lambda: - var e = o.currentEnv - if idTableGet(o.lambdasToEnv, i.fn) == nil: - idTablePut(o.lambdasToEnv, i.fn, e) - - # variable already captured: - if idNodeTableGet(i.localsToAccess, local) != nil: return - if i.closureParam == nil: addClosureParam(i, e) - - # check which environment `local` belongs to: - var access = newSymNode(i.closureParam) - addCapturedVar(it, local) - if it == e: - # common case: local directly in current environment: - discard - else: - # it's in some upper environment: - access = indirectAccess(access, addDep(e, it, i.fn), info) - access = indirectAccess(access, local, info) - if o.isIter: - if not containsOrIncl(o.capturedVars, local.id): addField(o.obj, local) - else: - incl(o.capturedVars, local.id) - idNodeTablePut(i.localsToAccess, local, access) - proc interestingVar(s: PSym): bool {.inline.} = result = s.kind in {skVar, skLet, skTemp, skForVar, skParam, skResult} and sfGlobal notin s.flags +proc nestedAccess(top: PEnv; local: PSym): PNode = + # Parts after the transformation are in []: + # + # proc main = + # var [:env.]foo = 23 + # proc outer(:paramO) = + # [var :envO; createClosure(:envO); :envO.up = paramO] + # proc inner(:paramI) = + # echo [:paramI.up.]foo + # inner([:envO]) + # outer([:env]) + if not interestingVar(local) or top.fn == local.owner: + return nil + # check it's in fact a captured variable: + var it = top + while it != nil: + if it.vars.contains(local.id): break + it = it.up + if it == nil: return nil + let envParam = top.fn.getEnvParam + internalAssert(not envParam.isNil) + var access = newSymNode(envParam) + it = top.up + while it != nil: + if it.vars.contains(local.id): + access = indirectAccess(access, local, local.info) + return access + internalAssert it.upField != nil + access = indirectAccess(access, it.upField, local.info) + it = it.up + when false: + # Type based expression construction works too, but turned out to hide + # other bugs: + while true: + let obj = access.typ.sons[0] + let field = getFieldFromObj(obj, local) + if field != nil: + return rawIndirectAccess(access, field, local.info) + let upField = lookupInRecord(obj.n, getIdent(upName)) + if upField == nil: break + access = rawIndirectAccess(access, upField, local.info) + return nil + +proc createUpField(obj, fieldType: PType): PSym = + let pos = obj.n.len + result = newSym(skField, getIdent(upName), obj.owner, obj.owner.info) + result.typ = newType(tyRef, obj.owner) + result.position = pos + rawAddSon(result.typ, fieldType) + #rawAddField(obj, result) + addField(obj, result) + +proc captureVar(o: POuterContext; top: PEnv; local: PSym; + info: TLineInfo): bool = + # first check if we should be concerned at all: + var it = top + while it != nil: + if it.vars.contains(local.id): break + it = it.up + if it == nil: return false + # yes, so mark every 'up' pointer as taken: + if illegalCapture(local) or top.fn.typ.callConv notin {ccClosure, ccDefault}: + localError(info, errIllegalCaptureX, local.name.s) + it = top + while it != nil: + if it.vars.contains(local.id): break + # keep in mind that the first element of the chain belong to top.fn itself + # and these don't need any upFields + if it.upField == nil and it.up != nil and it.fn != top.fn: + it.upField = createUpField(it.obj, it.up.obj) + + if it.fn != local.owner: + it.fn.typ.callConv = ccClosure + incl(it.fn.typ.flags, tfCapturesEnv) + + var u = it.up + while u != nil and u.fn == it.fn: u = u.up + addClosureParam(it.fn, u) + + if idTableGet(o.lambdasToEnv, it.fn) == nil: + if u != nil: idTablePut(o.lambdasToEnv, it.fn, u) + + it = it.up + # don't do this: 'top' might not require a closure: + #if idTableGet(o.lambdasToEnv, it.fn) == nil: + # idTablePut(o.lambdasToEnv, it.fn, top) + + # mark as captured: + #if top.iter != nil: + # if not containsOrIncl(o.capturedVars, local.id): + # #addField(top.iter.obj, local) + # addCapturedVar(it, local) + #else: + incl(o.capturedVars, local.id) + addCapturedVar(it, local) + result = true + proc semCaptureSym*(s, owner: PSym) = if interestingVar(s) and owner.id != s.owner.id and s.kind != skResult: if owner.typ != nil and not isGenericRoutine(owner): @@ -350,28 +397,20 @@ proc semCaptureSym*(s, owner: PSym) = # since the analysis is not entirely correct, we don't set 'tfCapturesEnv' # here -proc gatherVars(o: POuterContext, i: PInnerContext, n: PNode) = - # gather used vars for closure generation - if n == nil: return +proc gatherVars(o: POuterContext; e: PEnv; n: PNode): int = + # gather used vars for closure generation; returns number of captured vars + if n == nil: return 0 case n.kind of nkSym: var s = n.sym - if interestingVar(s) and i.fn.id != s.owner.id: - captureVar(o, i, s, n.info) - elif s.kind in {skProc, skMethod, skConverter} and - s.skipGenericOwner == o.fn and - tfCapturesEnv in s.typ.flags and s != i.fn: - # call to some other inner proc; we need to track the dependencies for - # this: - let env = PEnv(idTableGet(o.lambdasToEnv, i.fn)) - if env == nil: internalError(n.info, "no environment computed") - if o.currentEnv != env: - discard addDep(o.currentEnv, env, i.fn) - internalError(n.info, "too complex environment handling required") - of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkClosure: discard + if interestingVar(s) and e.fn != s.owner: + if captureVar(o, e, s, n.info): result = 1 + of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkClosure, nkProcDef, + nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, nkTypeSection: + discard else: - for k in countup(0, sonsLen(n) - 1): - gatherVars(o, i, n.sons[k]) + for k in countup(0, sonsLen(n) - 1): + result += gatherVars(o, e, n.sons[k]) proc generateThunk(prc: PNode, dest: PType): PNode = ## Converts 'prc' into '(thunk, nil)' so that it's compatible with @@ -395,84 +434,143 @@ proc transformOuterConv(n: PNode): PNode = if dest.callConv == ccClosure and source.callConv == ccDefault: result = generateThunk(n.sons[1], dest) -proc makeClosure(prc, env: PSym, info: TLineInfo): PNode = +proc makeClosure(prc: PSym; env: PNode; info: TLineInfo): PNode = result = newNodeIT(nkClosure, info, prc.typ) result.add(newSymNode(prc)) if env == nil: result.add(newNodeIT(nkNilLit, info, getSysType(tyNil))) else: - result.add(newSymNode(env)) + result.add(env) -proc transformInnerProc(o: POuterContext, i: PInnerContext, n: PNode): PNode = +proc newClosureCreationVar(e: PEnv): PNode = + var v = newSym(skVar, getIdent(envName), e.fn, e.attachedNode.info) + incl(v.flags, sfShadowed) + v.typ = newType(tyRef, e.fn) + v.typ.rawAddSon(e.obj) + if e.fn.kind == skClosureIterator: + let it = initIter(e.fn) + addUniqueField(it.obj, v) + result = indirectAccess(newSymNode(it.closureParam), v, v.info) + else: + result = newSymNode(v) + +proc getClosureVar(e: PEnv): PNode = + if e.createdVar == nil: + result = newClosureCreationVar(e) + e.createdVar = result + else: + result = e.createdVar + +proc findEnv(o: POuterContext; s: PSym): PEnv = + var env = o.head + while env != nil: + if env.fn == s: break + env = env.next + internalAssert env != nil and env.up != nil + result = env.up + while result.fn == s: result = result.up + +proc transformInnerProc(o: POuterContext; e: PEnv, n: PNode): PNode = case n.kind of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard of nkSym: let s = n.sym - if s == i.fn: + if s == e.fn: # recursive calls go through (lambda, hiddenParam): - assert i.closureParam != nil, i.fn.name.s - result = makeClosure(s, i.closureParam, n.info) + result = makeClosure(s, getEnvParam(s).newSymNode, n.info) elif isInnerProc(s, o.fn) and s.typ.callConv == ccClosure: - # ugh: call to some other inner proc; - assert i.closureParam != nil - # XXX this is not correct in general! may also be some 'closure.upval' - result = makeClosure(s, i.closureParam, n.info) + # ugh: call to some other inner proc; + result = makeClosure(s, findEnv(o, s).getClosureVar, n.info) else: # captured symbol? - result = idNodeTableGet(i.localsToAccess, n.sym) - of nkLambdaKinds, nkIteratorDef: - if n.typ != nil: - result = transformInnerProc(o, i, n.sons[namePos]) + result = nestedAccess(e, n.sym) + #result = idNodeTableGet(i.localsToAccess, n.sym) + #of nkLambdaKinds, nkIteratorDef: + # if n.typ != nil: + # result = transformInnerProc(o, e, n.sons[namePos]) + #of nkClosure: + # let x = transformInnerProc(o, e, n.sons[0]) + # if x != nil: n.sons[0] = x of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, - nkClosure: + nkLambdaKinds, nkIteratorDef, nkClosure: # don't recurse here: discard else: for j in countup(0, sonsLen(n) - 1): - let x = transformInnerProc(o, i, n.sons[j]) + let x = transformInnerProc(o, e, n.sons[j]) if x != nil: n.sons[j] = x proc closureCreationPoint(n: PNode): PNode = - result = newNodeI(nkStmtList, n.info) - result.add(emptyNode) - result.add(n) + if n.kind == nkStmtList and n.len >= 1 and n[0].kind == nkEmpty: + # we already have a free slot + result = n + else: + result = newNodeI(nkStmtList, n.info) + result.add(emptyNode) + result.add(n) + #result.flags.incl nfLL -proc searchForInnerProcs(o: POuterContext, n: PNode) = +proc addParamsToEnv(fn: PSym; env: PEnv) = + let params = fn.typ.n + for i in 1.. declaredBlock. Note: The definition # counts, not the block where it is captured! @@ -481,26 +579,29 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) = if it.kind == nkCommentStmt: discard elif it.kind == nkIdentDefs: var L = sonsLen(it) - if it.sons[0].kind != nkSym: internalError(it.info, "transformOuter") - #echo "set: ", it.sons[0].sym.name.s, " ", o.currentBlock == nil - idTablePut(o.localsToEnv, it.sons[0].sym, o.currentEnv) - searchForInnerProcs(o, it.sons[L-1]) + if it.sons[0].kind == nkSym: + # this can be false for recursive invokations that already + # transformed it into 'env.varName': + env.vars.incl(it.sons[0].sym.id) + searchForInnerProcs(o, it.sons[L-1], env) elif it.kind == nkVarTuple: var L = sonsLen(it) for j in countup(0, L-3): #echo "set: ", it.sons[j].sym.name.s, " ", o.currentBlock == nil - idTablePut(o.localsToEnv, it.sons[j].sym, o.currentEnv) - searchForInnerProcs(o, it.sons[L-1]) + if it.sons[j].kind == nkSym: + env.vars.incl(it.sons[j].sym.id) + searchForInnerProcs(o, it.sons[L-1], env) else: - internalError(it.info, "transformOuter") + internalError(it.info, "searchForInnerProcs") + of nkClosure: + searchForInnerProcs(o, n.sons[0], env) of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, - nkClosure, nkTypeSection: + nkTypeSection: # don't recurse here: - # XXX recurse here and setup 'up' pointers discard else: for i in countup(0, sonsLen(n) - 1): - searchForInnerProcs(o, n.sons[i]) + searchForInnerProcs(o, n.sons[i], env) proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = # Bugfix: unfortunately we cannot use 'nkFastAsgn' here as that would @@ -512,24 +613,12 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = result.sons[0] = le result.sons[1] = ri -proc newClosureCreationVar(o: POuterContext; e: PEnv): PSym = - result = newSym(skVar, getIdent(envName), o.fn, e.attachedNode.info) - incl(result.flags, sfShadowed) - result.typ = newType(tyRef, o.fn) - result.typ.rawAddSon(e.obj) - -proc getClosureVar(o: POuterContext; e: PEnv): PSym = - if e.createdVar == nil: - result = newClosureCreationVar(o, e) - e.createdVar = result - else: - result = e.createdVar - -proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode = +proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PNode): PNode = result = newNodeI(nkStmtList, env.info) - var v = newNodeI(nkVarSection, env.info) - addVar(v, newSymNode(env)) - result.add(v) + if env.kind == nkSym: + var v = newNodeI(nkVarSection, env.info) + addVar(v, env) + result.add(v) # add 'new' statement: result.add(newCall(getSysSym"internalNew", env)) @@ -548,21 +637,25 @@ proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode = idNodeTablePut(o.localsToAccess, local, fieldAccess) else: result.add(newAsgnStmt(fieldAccess, existing, env.info)) - # add support for 'up' references: - for e, field in items(scope.deps): - # add ``env.up = env2`` - result.add(newAsgnStmt(indirectAccess(env, field, env.info), - newSymNode(getClosureVar(o, e)), env.info)) - + if scope.upField != nil: + # "up" chain has been used: + if scope.up.fn != scope.fn: + # crosses function boundary: + result.add(newAsgnStmt(indirectAccess(env, scope.upField, env.info), + newSymNode(getEnvParam(scope.fn)), env.info)) + else: + result.add(newAsgnStmt(indirectAccess(env, scope.upField, env.info), + getClosureVar(scope.up), env.info)) + proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode = - var env = getClosureVar(o, scope) + var env = getClosureVar(scope) result = rawClosureCreation(o, scope, env) proc generateIterClosureCreation(o: POuterContext; env: PEnv; - scope: PNode): PSym = + scope: PNode): PNode = if env.createdVarComesFromIter or env.createdVar.isNil: # we have to create a new closure: - result = newClosureCreationVar(o, env) + result = newClosureCreationVar(env) let cc = rawClosureCreation(o, env, result) var insertPoint = scope.sons[0] if insertPoint.kind == nkEmpty: scope.sons[0] = cc @@ -577,21 +670,25 @@ proc generateIterClosureCreation(o: POuterContext; env: PEnv; proc interestingIterVar(s: PSym): bool {.inline.} = result = s.kind in {skVar, skLet, skTemp, skForVar} and sfGlobal notin s.flags -proc transformOuterProc(o: POuterContext, n: PNode): PNode +proc transformOuterProc(o: POuterContext, n: PNode, it: TIter): PNode -proc transformYield(c: POuterContext, n: PNode): PNode = - inc c.state.typ.n.sons[1].intVal - let stateNo = c.state.typ.n.sons[1].intVal +proc transformYield(c: POuterContext, n: PNode, it: TIter): PNode = + assert it.state != nil + assert it.state.typ != nil + assert it.state.typ.n != nil + inc it.state.typ.n.sons[1].intVal + let stateNo = it.state.typ.n.sons[1].intVal var stateAsgnStmt = newNodeI(nkAsgn, n.info) - stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info)) + stateAsgnStmt.add(rawIndirectAccess(newSymNode(it.closureParam), + it.state, n.info)) stateAsgnStmt.add(newIntTypeNode(nkIntLit, stateNo, getSysType(tyInt))) var retStmt = newNodeI(nkReturnStmt, n.info) if n.sons[0].kind != nkEmpty: var a = newNodeI(nkAsgn, n.sons[0].info) - var retVal = transformOuterProc(c, n.sons[0]) - addSon(a, newSymNode(c.resultSym)) + var retVal = transformOuterProc(c, n.sons[0], it) + addSon(a, newSymNode(it.resultSym)) addSon(a, if retVal.isNil: n.sons[0] else: retVal) retStmt.add(a) else: @@ -605,17 +702,18 @@ proc transformYield(c: POuterContext, n: PNode): PNode = result.add(retStmt) result.add(stateLabelStmt) -proc transformReturn(c: POuterContext, n: PNode): PNode = +proc transformReturn(c: POuterContext, n: PNode, it: TIter): PNode = result = newNodeI(nkStmtList, n.info) var stateAsgnStmt = newNodeI(nkAsgn, n.info) - stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info)) + stateAsgnStmt.add(rawIndirectAccess(newSymNode(it.closureParam), it.state, + n.info)) stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt))) result.add(stateAsgnStmt) result.add(n) -proc outerProcSons(o: POuterContext, n: PNode) = +proc outerProcSons(o: POuterContext, n: PNode, it: TIter) = for i in countup(0, sonsLen(n) - 1): - let x = transformOuterProc(o, n.sons[i]) + let x = transformOuterProc(o, n.sons[i], it) if x != nil: n.sons[i] = x proc liftIterSym*(n: PNode): PNode = @@ -631,27 +729,137 @@ proc liftIterSym*(n: PNode): PNode = addVar(v, newSymNode(env)) result.add(v) # add 'new' statement: - result.add(newCall(getSysSym"internalNew", env)) - result.add makeClosure(iter, env, n.info) + let envAsNode = env.newSymNode + result.add newCall(getSysSym"internalNew", envAsNode) + result.add makeClosure(iter, envAsNode, n.info) -proc transformOuterProc(o: POuterContext, n: PNode): PNode = - if n == nil: return nil +when false: + proc transformRemainingLocals(n: PNode; it: TIter): PNode = + assert it.fn.kind == skClosureIterator + result = n + case n.kind + of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard + of nkSym: + let local = n.sym + if interestingIterVar(local) and it.fn == local.owner: + addUniqueField(it.obj, local) + result = indirectAccess(newSymNode(it.closureParam), local, n.info) + else: + result = newNodeI(n.kind, n.info, n.len) + for i in 0.. 0 or env.upField != nil) + +# We have to split up environment creation in 2 steps: +# 1. Generate it and store it in env.replacementNode +# 2. Insert replacementNode into its forseen slot. +# This split is necessary so that assignments belonging to closure +# creation like 'env.param = param' are not transformed +# into 'env.param = env.param'. +proc createEnvironments(o: POuterContext) = + var env = o.head + while env != nil: + if envActive(env): + var scope = env.attachedNode + assert scope.kind == nkStmtList + if scope.sons[0].kind == nkEmpty: + # prepare for closure construction: + env.replacementNode = generateClosureCreation(o, env) + env = env.next + +proc finishEnvironments(o: POuterContext) = + var env = o.head + while env != nil: + if env.replacementNode != nil: + var scope = env.attachedNode + assert scope.kind == nkStmtList + if scope.sons[0].kind == nkEmpty: + # change the empty node to contain the closure construction: + scope.sons[0] = env.replacementNode + when false: + if env.fn.kind == skClosureIterator: + scope.sons[0] = transformRemainingLocals(env.replacementNode, + initIter(env.fn)) + else: + scope.sons[0] = env.replacementNode + env = env.next + +proc transformOuterProcBody(o: POuterContext, n: PNode; it: TIter): PNode = + if nfLL in n.flags: + result = nil + elif it.fn.kind == skClosureIterator: + # unfortunately control flow is still convoluted and we can end up + # multiple times here for the very same iterator. We shield against this + # with some rather primitive check for now: + if n.kind == nkStmtList and n.len > 0: + if n.sons[0].kind == nkGotoState: return nil + if n.len > 1 and n[1].kind == nkStmtList and n[1].len > 0 and + n[1][0].kind == nkGotoState: + return nil + result = newNodeI(nkStmtList, it.fn.info) + var gs = newNodeI(nkGotoState, it.fn.info) + assert it.closureParam != nil + assert it.state != nil + gs.add(rawIndirectAccess(newSymNode(it.closureParam), it.state, it.fn.info)) + result.add(gs) + var state0 = newNodeI(nkState, it.fn.info) + state0.add(newIntNode(nkIntLit, 0)) + result.add(state0) + + let newBody = transformOuterProc(o, n, it) + if newBody != nil: + result.add(newBody) + else: + result.add(n) + + var stateAsgnStmt = newNodeI(nkAsgn, it.fn.info) + stateAsgnStmt.add(rawIndirectAccess(newSymNode(it.closureParam), + it.state, it.fn.info)) + stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt))) + result.add(stateAsgnStmt) + result.flags.incl nfLL + else: + result = transformOuterProc(o, n, it) + if result != nil: result.flags.incl nfLL + +proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode = + if n == nil or nfLL in n.flags: return nil case n.kind of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard of nkSym: var local = n.sym - if o.isIter and interestingIterVar(local) and o.fn.id == local.owner.id: - if not containsOrIncl(o.capturedVars, local.id): addField(o.obj, local) - return indirectAccess(newSymNode(o.closureParam), local, n.info) + if isInnerProc(local, o.fn) and o.processed.contains(local.id): + o.processed.excl(local.id) + let body = local.getBody + let newBody = transformOuterProcBody(o, body, initIter(local)) + if newBody != nil: + local.ast.sons[bodyPos] = newBody + + if it.fn.kind == skClosureIterator and interestingIterVar(local) and + it.fn == local.owner: + # every local goes through the closure: + #if not containsOrIncl(o.capturedVars, local.id): + # addField(it.obj, local) + if contains(o.capturedVars, local.id): + # change 'local' to 'closure.local', unless it's a 'byCopy' variable: + # if sfByCopy notin local.flags: + result = idNodeTableGet(o.localsToAccess, local) + assert result != nil, "cannot find: " & local.name.s + return result + else: + addUniqueField(it.obj, local) + return indirectAccess(newSymNode(it.closureParam), local, n.info) var closure = PEnv(idTableGet(o.lambdasToEnv, local)) - if local.kind == skClosureIterator: # consider: [i1, i2, i1] Since we merged the iterator's closure # with the captured owning variables, we need to generate the # closure generation code again: - if local == o.fn: message(n.info, errRecursiveDependencyX, local.name.s) + if local == o.fn or local == it.fn: + message(n.info, errRecursiveDependencyX, local.name.s) # XXX why doesn't this work? if closure.isNil: return liftIterSym(n) @@ -662,7 +870,6 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode = if closure != nil: # we need to replace the lambda with '(lambda, env)': - let a = closure.createdVar if a != nil: return makeClosure(local, a, n.info) @@ -678,14 +885,6 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode = return makeClosure(local, x, n.info) if not contains(o.capturedVars, local.id): return - var env = PEnv(idTableGet(o.localsToEnv, local)) - if env == nil: return - var scope = env.attachedNode - assert scope.kind == nkStmtList - if scope.sons[0].kind == nkEmpty: - # change the empty node to contain the closure construction: - scope.sons[0] = generateClosureCreation(o, env) - # change 'local' to 'closure.local', unless it's a 'byCopy' variable: # if sfByCopy notin local.flags: result = idNodeTableGet(o.localsToAccess, local) @@ -694,73 +893,64 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode = # to access the local as a local. of nkLambdaKinds, nkIteratorDef: if n.typ != nil: - result = transformOuterProc(o, n.sons[namePos]) - of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, - nkClosure: + result = transformOuterProc(o, n.sons[namePos], it) + of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef: # don't recurse here: discard + of nkClosure: + if n.sons[0].kind == nkSym: + var local = n.sons[0].sym + if isInnerProc(local, o.fn) and o.processed.contains(local.id): + o.processed.excl(local.id) + let body = local.getBody + let newBody = transformOuterProcBody(o, body, initIter(local)) + if newBody != nil: + local.ast.sons[bodyPos] = newBody + when false: + if n.sons[1].kind == nkSym: + var local = n.sons[1].sym + if it.fn.kind == skClosureIterator and interestingIterVar(local) and + it.fn == local.owner: + # every local goes through the closure: + addUniqueField(it.obj, local) + n.sons[1] = indirectAccess(newSymNode(it.closureParam), local, n.info) of nkHiddenStdConv, nkHiddenSubConv, nkConv: - let x = transformOuterProc(o, n.sons[1]) + let x = transformOuterProc(o, n.sons[1], it) if x != nil: n.sons[1] = x result = transformOuterConv(n) of nkYieldStmt: - if o.isIter: result = transformYield(o, n) - else: outerProcSons(o, n) + if it.fn.kind == skClosureIterator: result = transformYield(o, n, it) + else: outerProcSons(o, n, it) of nkReturnStmt: - if o.isIter: result = transformReturn(o, n) - else: outerProcSons(o, n) + if it.fn.kind == skClosureIterator: result = transformReturn(o, n, it) + else: outerProcSons(o, n, it) else: - outerProcSons(o, n) - -proc liftIterator(c: POuterContext, body: PNode): PNode = - let iter = c.fn - result = newNodeI(nkStmtList, iter.info) - var gs = newNodeI(nkGotoState, iter.info) - gs.add(indirectAccess(newSymNode(c.closureParam), c.state, iter.info)) - result.add(gs) - var state0 = newNodeI(nkState, iter.info) - state0.add(newIntNode(nkIntLit, 0)) - result.add(state0) - - let newBody = transformOuterProc(c, body) - if newBody != nil: - result.add(newBody) - else: - result.add(body) - - var stateAsgnStmt = newNodeI(nkAsgn, iter.info) - stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam), - c.state,iter.info)) - stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt))) - result.add(stateAsgnStmt) + outerProcSons(o, n, it) proc liftLambdas*(fn: PSym, body: PNode): PNode = # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs # the transformation even when compiling to JS ... - if body.kind == nkEmpty or gCmd == cmdCompileToJS: + if body.kind == nkEmpty or gCmd == cmdCompileToJS or + fn.skipGenericOwner.kind != skModule: # ignore forward declaration: result = body else: + #if fn.name.s == "cbOuter": + # echo rendertree(fn.ast, {renderIds}) var o = newOuterContext(fn) let ex = closureCreationPoint(body) - o.currentEnv = newEnv(fn, nil, ex) - # put all params into the environment so they can be captured: - let params = fn.typ.n - for i in 1.. n.ident else: result = nil of oimSelfModule: - result = nextIdentIter(o.it, c.topLevelScope.symbols) + result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n) of oimOtherModule: - result = nextIdentIter(o.it, o.m.tab) + result = nextIdentIter(o.it, o.m.tab).skipAlias(n) of oimSymChoice: if o.symChoiceIndex < sonsLen(n): result = n.sons[o.symChoiceIndex].sym @@ -329,31 +361,27 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = o.mode = oimSymChoiceLocalLookup o.scope = c.currentScope result = firstIdentExcluding(o.it, o.scope.symbols, - n.sons[0].sym.name, o.inSymChoice) + n.sons[0].sym.name, o.inSymChoice).skipAlias(n) while result == nil: o.scope = o.scope.parent if o.scope == nil: break result = firstIdentExcluding(o.it, o.scope.symbols, - n.sons[0].sym.name, o.inSymChoice) + n.sons[0].sym.name, o.inSymChoice).skipAlias(n) of oimSymChoiceLocalLookup: - result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice) + result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n) while result == nil: o.scope = o.scope.parent if o.scope == nil: break result = firstIdentExcluding(o.it, o.scope.symbols, - n.sons[0].sym.name, o.inSymChoice) + n.sons[0].sym.name, o.inSymChoice).skipAlias(n) if result != nil and result.kind == skStub: loadStub(result) -when false: - proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode, - flags = {checkUndeclared}): PSym = - var o: TOverloadIter - result = initOverloadIter(o, c, n) - var a = result - while a != nil: - if sfImmediate in a.flags: return a - a = nextOverloadIter(o, c, n) - if result == nil and checkUndeclared in flags: - localError(n.info, errUndeclaredIdentifier, n.considerQuotedIdent.s) - result = errorSym(c, n) +proc pickSym*(c: PContext, n: PNode; kind: TSymKind; + flags: TSymFlags = {}): PSym = + var o: TOverloadIter + var a = initOverloadIter(o, c, n) + while a != nil: + if a.kind == kind and flags <= a.flags: + return a + a = nextOverloadIter(o, c, n) diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index e2afa43628..e1fb09e449 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -56,6 +56,7 @@ proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode = result.add newAsgnStmt(newSymNode(temp), value) for i in 0 .. n.len-3: + if n.sons[i].kind == nkSym: v.addVar(n.sons[i]) result.add newAsgnStmt(n.sons[i], newTupleAccess(value, i)) proc createObj*(owner: PSym, info: TLineInfo): PType = @@ -64,6 +65,22 @@ proc createObj*(owner: PSym, info: TLineInfo): PType = incl result.flags, tfFinal result.n = newNodeI(nkRecList, info) +proc rawAddField*(obj: PType; field: PSym) = + assert field.kind == skField + field.position = sonsLen(obj.n) + addSon(obj.n, newSymNode(field)) + +proc rawIndirectAccess*(a: PNode; field: PSym; info: TLineInfo): PNode = + # returns a[].field as a node + assert field.kind == skField + var deref = newNodeI(nkHiddenDeref, info) + deref.typ = a.typ.skipTypes(abstractInst).sons[0] + addSon(deref, a) + result = newNodeI(nkDotExpr, info) + addSon(result, deref) + addSon(result, newSymNode(field)) + result.typ = field.typ + proc addField*(obj: PType; s: PSym) = # because of 'gensym' support, we have to mangle the name with its ID. # This is hacky but the clean solution is much more complex than it looks. @@ -74,6 +91,16 @@ proc addField*(obj: PType; s: PSym) = field.position = sonsLen(obj.n) addSon(obj.n, newSymNode(field)) +proc addUniqueField*(obj: PType; s: PSym) = + let fieldName = getIdent(s.name.s & $s.id) + if lookupInRecord(obj.n, fieldName) == nil: + var field = newSym(skField, fieldName, s.owner, s.info) + let t = skipIntLit(s.typ) + field.typ = t + assert t.kind != tyStmt + field.position = sonsLen(obj.n) + addSon(obj.n, newSymNode(field)) + proc newDotExpr(obj, b: PSym): PNode = result = newNodeI(nkDotExpr, obj.info) let field = getSymFromList(obj.typ.n, getIdent(b.name.s & $b.id)) @@ -95,13 +122,28 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode = t = t.sons[0] if t == nil: break t = t.skipTypes(abstractInst) - assert field != nil, b + #if field == nil: + # echo "FIELD ", b + # debug deref.typ + internalAssert field != nil addSon(deref, a) result = newNodeI(nkDotExpr, info) addSon(result, deref) addSon(result, newSymNode(field)) result.typ = field.typ +proc getFieldFromObj*(t: PType; v: PSym): PSym = + assert v.kind != skField + let fieldName = getIdent(v.name.s & $v.id) + var t = t + while true: + assert t.kind == tyObject + result = getSymFromList(t.n, fieldName) + if result != nil: break + t = t.sons[0] + if t == nil: break + t = t.skipTypes(abstractInst) + proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode = # returns a[].b as a node result = indirectAccess(a, b.name.s & $b.id, info) @@ -144,14 +186,14 @@ proc callProc(a: PNode): PNode = # - a proc returning non GC'ed memory --> pass as hidden 'var' parameter # - not in a parallel environment --> requires a flowVar for memory safety type - TSpawnResult = enum + TSpawnResult* = enum srVoid, srFlowVar, srByVar TFlowVarKind = enum fvInvalid # invalid type T for 'FlowVar[T]' fvGC # FlowVar of a GC'ed type fvBlob # FlowVar of a blob type -proc spawnResult(t: PType; inParallel: bool): TSpawnResult = +proc spawnResult*(t: PType; inParallel: bool): TSpawnResult = if t.isEmptyType: srVoid elif inParallel and not containsGarbageCollectedRef(t): srByVar else: srFlowVar @@ -161,7 +203,8 @@ proc flowVarKind(t: PType): TFlowVarKind = elif containsGarbageCollectedRef(t): fvInvalid else: fvBlob -proc addLocalVar(varSection: PNode; owner: PSym; typ: PType; v: PNode): PSym = +proc addLocalVar(varSection, varInit: PNode; owner: PSym; typ: PType; + v: PNode): PSym = result = newSym(skTemp, getIdent(genPrefix), owner, varSection.info) result.typ = typ incl(result.flags, sfFromGeneric) @@ -169,8 +212,14 @@ proc addLocalVar(varSection: PNode; owner: PSym; typ: PType; v: PNode): PSym = var vpart = newNodeI(nkIdentDefs, varSection.info, 3) vpart.sons[0] = newSymNode(result) vpart.sons[1] = ast.emptyNode - vpart.sons[2] = v + vpart.sons[2] = if varInit.isNil: v else: ast.emptyNode varSection.add vpart + if varInit != nil: + let deepCopyCall = newNodeI(nkCall, varInit.info, 3) + deepCopyCall.sons[0] = newSymNode(createMagic("deepCopy", mDeepCopy)) + deepCopyCall.sons[1] = newSymNode(result) + deepCopyCall.sons[2] = v + varInit.add deepCopyCall discard """ We generate roughly this: @@ -203,24 +252,24 @@ stmtList: """ proc createWrapperProc(f: PNode; threadParam, argsParam: PSym; - varSection, call, barrier, fv: PNode; + varSection, varInit, call, barrier, fv: PNode; spawnKind: TSpawnResult): PSym = var body = newNodeI(nkStmtList, f.info) var threadLocalBarrier: PSym if barrier != nil: - var varSection = newNodeI(nkVarSection, barrier.info) - threadLocalBarrier = addLocalVar(varSection, argsParam.owner, + var varSection2 = newNodeI(nkVarSection, barrier.info) + threadLocalBarrier = addLocalVar(varSection2, nil, argsParam.owner, barrier.typ, barrier) - body.add varSection + body.add varSection2 body.add callCodeGenProc("barrierEnter", threadLocalBarrier.newSymNode) var threadLocalProm: PSym if spawnKind == srByVar: - threadLocalProm = addLocalVar(varSection, argsParam.owner, fv.typ, fv) + threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv) elif fv != nil: internalAssert fv.typ.kind == tyGenericInst - threadLocalProm = addLocalVar(varSection, argsParam.owner, fv.typ, fv) - + threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv) body.add varSection + body.add varInit if fv != nil and spawnKind != srByVar: # generate: # fv.owner = threadParam @@ -273,7 +322,8 @@ proc createCastExpr(argsParam: PSym; objType: PType): PNode = result.typ.rawAddSon(objType) proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym, - castExpr, call, varSection, result: PNode) = + castExpr, call, + varSection, varInit, result: PNode) = let formals = n[0].typ.n let tmpName = getIdent(genPrefix) for i in 1 .. 0 and s[i-1] in {'A'..'Z'}: + # don't skip '_' as it's essential for e.g. 'GC_disable' + result.add('_') + inc i + result.add s[i] + else: + inc i + result.add toUpper(s[i]) + elif allUpper: + result.add toLower(s[i]) + else: + result.add s[i] + inc i + +proc replaceInFile(info: TLineInfo; newName: string) = + loadFile(info) + + let line = gSourceFiles[info.fileIndex].lines[info.line-1] + var first = min(info.col.int, line.len) + if first < 0: return + #inc first, skipIgnoreCase(line, "proc ", first) + while first > 0 and line[first-1] in prettybase.Letters: dec first + if first < 0: return + if line[first] == '`': inc first + + let last = first+identLen(line, first)-1 + if differ(line, first, last, newName): + # last-first+1 != newName.len or + var x = line.substr(0, first-1) & newName & line.substr(last+1) + system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) + gSourceFiles[info.fileIndex].dirty = true + +proc checkStyle(info: TLineInfo, s: string, k: TSymKind; sym: PSym) = + let beau = beautifyName(s, k) + if s != beau: + if gStyleCheck == StyleCheck.Auto: + sym.name = getIdent(beau) + replaceInFile(info, beau) + else: + message(info, hintName, beau) + +proc styleCheckDefImpl(info: TLineInfo; s: PSym; k: TSymKind) = + # operators stay as they are: + if k in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters: return + if k in {skType, skGenericParam} and sfAnon in s.flags: return + if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern: + checkStyle(info, s.name.s, k, s) + +template styleCheckDef*(info: TLineInfo; s: PSym; k: TSymKind) = + when defined(nimfix): + if gStyleCheck != StyleCheck.None: styleCheckDefImpl(info, s, k) + +template styleCheckDef*(info: TLineInfo; s: PSym) = + styleCheckDef(info, s, s.kind) +template styleCheckDef*(s: PSym) = + styleCheckDef(s.info, s, s.kind) + +proc styleCheckUseImpl(info: TLineInfo; s: PSym) = + if info.fileIndex < 0: return + # we simply convert it to what it looks like in the definition + # for consistency + + # operators stay as they are: + if s.kind in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters: + return + if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return + let newName = s.name.s + + replaceInFile(info, newName) + #if newName == "File": writeStackTrace() + +template styleCheckUse*(info: TLineInfo; s: PSym) = + when defined(nimfix): + if gStyleCheck != StyleCheck.None: styleCheckUseImpl(info, s) diff --git a/compiler/nimfix/prettybase.nim b/compiler/nimfix/prettybase.nim new file mode 100644 index 0000000000..8e0f5db6d8 --- /dev/null +++ b/compiler/nimfix/prettybase.nim @@ -0,0 +1,93 @@ +# +# +# The Nim Compiler +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +import ast, msgs, strutils, idents, lexbase, streams +from os import splitFile + +type + TSourceFile* = object + lines*: seq[string] + dirty*, isNimfixFile*: bool + fullpath*, newline*: string + fileIdx*: int32 + +var + gSourceFiles*: seq[TSourceFile] = @[] + +proc loadFile*(info: TLineInfo) = + let i = info.fileIndex + if i >= gSourceFiles.len: + gSourceFiles.setLen(i+1) + if gSourceFiles[i].lines.isNil: + gSourceFiles[i].fileIdx = info.fileIndex + gSourceFiles[i].lines = @[] + let path = info.toFullPath + gSourceFiles[i].fullpath = path + gSourceFiles[i].isNimfixFile = path.splitFile.ext == ".nimfix" + # we want to die here for IOError: + for line in lines(path): + gSourceFiles[i].lines.add(line) + # extract line ending of the file: + var lex: TBaseLexer + open(lex, newFileStream(path, fmRead)) + var pos = lex.bufpos + while true: + case lex.buf[pos] + of '\c': + gSourceFiles[i].newline = "\c\L" + break + of '\L', '\0': + gSourceFiles[i].newline = "\L" + break + else: discard + inc pos + close(lex) + +const + Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'} + +proc identLen*(line: string, start: int): int = + while start+result < line.len and line[start+result] in Letters: + inc result + +proc differ*(line: string, a, b: int, x: string): bool = + let y = line[a..b] + result = cmpIgnoreStyle(y, x) == 0 and y != x + +proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) = + loadFile(info) + + let line = gSourceFiles[info.fileIndex].lines[info.line-1] + var first = min(info.col.int, line.len) + if first < 0: return + #inc first, skipIgnoreCase(line, "proc ", first) + while first > 0 and line[first-1] in Letters: dec first + if first < 0: return + if line[first] == '`': inc first + + let last = first+identLen(line, first)-1 + if cmpIgnoreStyle(line[first..last], oldSym.s) == 0: + var x = line.substr(0, first-1) & newSym.s & line.substr(last+1) + system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) + gSourceFiles[info.fileIndex].dirty = true + #if newSym.s == "File": writeStackTrace() + +proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) = + replaceDeprecated(info, oldSym.name, newSym.name) + +proc replaceComment*(info: TLineInfo) = + loadFile(info) + + let line = gSourceFiles[info.fileIndex].lines[info.line-1] + var first = info.col.int + if line[first] != '#': inc first + + var x = line.substr(0, first-1) & "discard " & line.substr(first+1).escape + system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) + gSourceFiles[info.fileIndex].dirty = true diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 44e16cec85..ae1c6053f1 100644 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -1,3 +1,6 @@ +; This config file holds configuration information about the Nim compiler +; and project. + [Project] Name: "Nimrod" Version: "$version" @@ -34,11 +37,11 @@ Files: "config/nimdoc.cfg" Files: "config/nimdoc.tex.cfg" [Documentation] -Files: "doc/*.txt" -Files: "doc/*.html" -Files: "doc/*.cfg" -Files: "doc/*.pdf" -Files: "doc/*.ini" +; Files: "doc/*.html" +; Files: "doc/*.cfg" +; Files: "doc/*.pdf" +; Files: "doc/*.ini" +Files: "doc/overview.html" Start: "doc/overview.html" @@ -61,13 +64,9 @@ Files: "compiler/readme.txt" Files: "compiler/nimrod.ini" Files: "compiler/nimrod.cfg" Files: "compiler/*.nim" -Files: "compiler/c2nim/*.nim" -Files: "compiler/c2nim/*.cfg" -Files: "compiler/pas2nim/*.nim" -Files: "compiler/pas2nim/*.cfg" - -Files: "build/empty.txt" -Files: "bin/empty.txt" +Files: "doc/*.txt" +Files: "compiler/nimfix/*.nim" +Files: "compiler/nimfix/*.cfg" [Lib] @@ -115,17 +114,22 @@ Files: "examples/*.tmpl" [Windows] Files: "bin/nimrod.exe" +Files: "bin/nimrod_debug.exe" Files: "bin/c2nim.exe" Files: "bin/niminst.exe" Files: "bin/nimgrep.exe" Files: "dist/*.dll" Files: "koch.exe" -Files: "dist/mingw" +; Files: "dist/mingw" Files: "start.bat" BinPath: r"bin;dist\mingw\bin;dist" -InnoSetup: "Yes" +; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry +Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip" +Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip" +Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe" +; for now only NSIS supports optional downloads [UnixBin] Files: "bin/nimrod" @@ -140,6 +144,9 @@ UninstallScript: "yes" path = r"c:\Program Files (x86)\Inno Setup 5\iscc.exe" flags = "/Q" +[NSIS] +path = r"c:\Program Files (x86)\NSIS\makensis.exe" +flags = "/V0" [C_Compiler] path = r"" diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim index efe3d83bfe..618d98698f 100644 --- a/compiler/nimrod.nim +++ b/compiler/nimrod.nim @@ -58,7 +58,7 @@ proc handleCmdLine() = if msgs.gErrorCounter == 0: when hasTinyCBackend: if gCmd == cmdRun: - tccgen.run() + tccgen.run(service.arguments) if optRun in gGlobalOptions: if gCmd == cmdCompileToJS: var ex: string @@ -79,7 +79,7 @@ proc handleCmdLine() = var ex = quoteShell(binPath) execExternalProgram(ex & ' ' & service.arguments) -when defined(GC_setMaxPause): +when declared(GC_setMaxPause): GC_setMaxPause 2_000 when compileOption("gc", "v2") or compileOption("gc", "refc"): diff --git a/compiler/nversion.nim b/compiler/nversion.nim index 3c868ed2af..bd1f79ac6b 100644 --- a/compiler/nversion.nim +++ b/compiler/nversion.nim @@ -14,7 +14,7 @@ const MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets? VersionMajor* = 0 VersionMinor* = 9 - VersionPatch* = 5 + VersionPatch* = 6 VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch RodFileVersion* = "1215" # modify this if the rod-format changes! diff --git a/compiler/options.nim b/compiler/options.nim index 58a340d213..02719cacce 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -95,7 +95,7 @@ var optBoundsCheck, optOverflowCheck, optAssert, optWarns, optHints, optStackTrace, optLineTrace, optPatterns, optNilCheck} - gGlobalOptions*: TGlobalOptions = {} + gGlobalOptions*: TGlobalOptions = {optThreadAnalysis} gExitcode*: int8 gCmd*: TCommands = cmdNone # the command gSelectedGC* = gcRefc # the selected GC diff --git a/compiler/pas2nim/nimrod.cfg b/compiler/pas2nim/nimrod.cfg deleted file mode 100644 index cfeda63ed6..0000000000 --- a/compiler/pas2nim/nimrod.cfg +++ /dev/null @@ -1,4 +0,0 @@ -# Use the modules of the compiler - -path: "$nimrod/compiler" - diff --git a/compiler/pas2nim/pas2nim.nim b/compiler/pas2nim/pas2nim.nim deleted file mode 100644 index d100281670..0000000000 --- a/compiler/pas2nim/pas2nim.nim +++ /dev/null @@ -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) diff --git a/compiler/pas2nim/paslex.nim b/compiler/pas2nim/paslex.nim deleted file mode 100644 index f24b0c420a..0000000000 --- a/compiler/pas2nim/paslex.nim +++ /dev/null @@ -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) diff --git a/compiler/pas2nim/pasparse.nim b/compiler/pas2nim/pasparse.nim deleted file mode 100644 index a6f8363f61..0000000000 --- a/compiler/pas2nim/pasparse.nim +++ /dev/null @@ -1,1513 +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 the parser of the Pascal variant Nimrod is written in. -# It transfers a Pascal module into a Nimrod AST. Then the renderer can be -# used to convert the AST to its text representation. - -import - os, llstream, paslex, idents, strutils, ast, astalgo, msgs, options - -type - TSection = enum - seImplementation, seInterface - TContext = enum - conExpr, conStmt, conTypeDesc - TParserFlag* = enum - pfRefs, ## use "ref" instead of "ptr" for Pascal's ^typ - pfMoreReplacements, ## use more than the default replacements - pfImportBlackList ## use import blacklist - TParser*{.final.} = object - section: TSection - inParamList: bool - context: TContext # needed for the @emit command - lastVarSection: PNode - lex: TLexer - tok: TToken - repl: TIdTable # replacements - flags: set[TParserFlag] - - TReplaceTuple* = array[0..1, string] - -const - ImportBlackList*: array[1..3, string] = ["nsystem", "sysutils", "charsets"] - stdReplacements*: array[1..19, TReplaceTuple] = [["include", "incl"], - ["exclude", "excl"], ["pchar", "cstring"], ["assignfile", "open"], - ["integer", "int"], ["longword", "int32"], ["cardinal", "int"], - ["boolean", "bool"], ["shortint", "int8"], ["smallint", "int16"], - ["longint", "int32"], ["byte", "int8"], ["word", "int16"], - ["single", "float32"], ["double", "float64"], ["real", "float"], - ["length", "len"], ["len", "length"], ["setlength", "setlen"]] - nimReplacements*: array[1..35, TReplaceTuple] = [["nimread", "read"], - ["nimwrite", "write"], ["nimclosefile", "close"], ["closefile", "close"], - ["openfile", "open"], ["nsystem", "system"], ["ntime", "times"], - ["nos", "os"], ["nmath", "math"], ["ncopy", "copy"], ["addChar", "add"], - ["halt", "quit"], ["nobject", "TObject"], ["eof", "EndOfFile"], - ["input", "stdin"], ["output", "stdout"], ["addu", "`+%`"], - ["subu", "`-%`"], ["mulu", "`*%`"], ["divu", "`/%`"], ["modu", "`%%`"], - ["ltu", "`<%`"], ["leu", "`<=%`"], ["shlu", "`shl`"], ["shru", "`shr`"], - ["assigned", "not isNil"], ["eintoverflow", "EOverflow"], ["format", "`%`"], - ["snil", "nil"], ["tostringf", "$"], ["ttextfile", "tfile"], - ["tbinaryfile", "tfile"], ["strstart", "0"], ["nl", "\"\\n\""], - ["tostring", "$"]] - -proc parseUnit*(p: var TParser): PNode -proc openParser*(p: var TParser, filename: string, inputStream: PLLStream, - flags: set[TParserFlag] = {}) -proc closeParser*(p: var TParser) -proc exSymbol*(n: var PNode) -proc fixRecordDef*(n: var PNode) - # XXX: move these two to an auxiliary module - -# implementation - -proc openParser(p: var TParser, filename: string, - inputStream: PLLStream, flags: set[TParserFlag] = {}) = - openLexer(p.lex, filename, inputStream) - initIdTable(p.repl) - for i in countup(low(stdReplacements), high(stdReplacements)): - idTablePut(p.repl, getIdent(stdReplacements[i][0]), - getIdent(stdReplacements[i][1])) - if pfMoreReplacements in flags: - for i in countup(low(nimReplacements), high(nimReplacements)): - idTablePut(p.repl, getIdent(nimReplacements[i][0]), - getIdent(nimReplacements[i][1])) - p.flags = flags - -proc closeParser(p: var TParser) = closeLexer(p.lex) -proc getTok(p: var TParser) = getTok(p.lex, p.tok) - -proc parMessage(p: TParser, msg: TMsgKind, arg = "") = - lexMessage(p.lex, msg, arg) - -proc parLineInfo(p: TParser): TLineInfo = - result = getLineInfo(p.lex) - -proc skipCom(p: var TParser, n: PNode) = - while p.tok.xkind == pxComment: - if (n != nil): - if n.comment == nil: n.comment = p.tok.literal - else: add(n.comment, "\n" & p.tok.literal) - else: - parMessage(p, warnCommentXIgnored, p.tok.literal) - getTok(p) - -proc expectIdent(p: TParser) = - if p.tok.xkind != pxSymbol: - lexMessage(p.lex, errIdentifierExpected, $(p.tok)) - -proc eat(p: var TParser, xkind: TTokKind) = - if p.tok.xkind == xkind: getTok(p) - else: lexMessage(p.lex, errTokenExpected, tokKindToStr(xkind)) - -proc opt(p: var TParser, xkind: TTokKind) = - if p.tok.xkind == xkind: getTok(p) - -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 createIdentNodeP(ident: PIdent, p: TParser): PNode = - result = newNodeP(nkIdent, p) - var x = PIdent(idTableGet(p.repl, ident)) - if x != nil: result.ident = x - else: result.ident = ident - -proc parseExpr(p: var TParser): PNode -proc parseStmt(p: var TParser): PNode -proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode - -proc parseEmit(p: var TParser, definition: PNode): PNode = - getTok(p) # skip 'emit' - result = ast.emptyNode - if p.tok.xkind != pxCurlyDirRi: - case p.context - of conExpr: - result = parseExpr(p) - of conStmt: - result = parseStmt(p) - if p.tok.xkind != pxCurlyDirRi: - var a = result - result = newNodeP(nkStmtList, p) - addSon(result, a) - while p.tok.xkind != pxCurlyDirRi: - addSon(result, parseStmt(p)) - of conTypeDesc: - result = parseTypeDesc(p, definition) - eat(p, pxCurlyDirRi) - -proc parseCommand(p: var TParser, definition: PNode = nil): PNode = - result = ast.emptyNode - getTok(p) - if p.tok.ident.id == getIdent("discard").id: - result = newNodeP(nkDiscardStmt, p) - getTok(p) - eat(p, pxCurlyDirRi) - addSon(result, parseExpr(p)) - elif p.tok.ident.id == getIdent("set").id: - getTok(p) - eat(p, pxCurlyDirRi) - result = parseExpr(p) - if result.kind == nkEmpty: internalError("emptyNode modified") - result.kind = nkCurly - elif p.tok.ident.id == getIdent("cast").id: - getTok(p) - eat(p, pxCurlyDirRi) - var a = parseExpr(p) - if (a.kind == nkCall) and (sonsLen(a) == 2): - result = newNodeP(nkCast, p) - addSon(result, a.sons[0]) - addSon(result, a.sons[1]) - else: - parMessage(p, errInvalidDirectiveX, $p.tok) - result = a - elif p.tok.ident.id == getIdent("emit").id: - result = parseEmit(p, definition) - elif p.tok.ident.id == getIdent("ignore").id: - getTok(p) - eat(p, pxCurlyDirRi) - while true: - case p.tok.xkind - of pxEof: - parMessage(p, errTokenExpected, "{@emit}") - of pxCommand: - getTok(p) - if p.tok.ident.id == getIdent("emit").id: - result = parseEmit(p, definition) - break - else: - while (p.tok.xkind != pxCurlyDirRi) and (p.tok.xkind != pxEof): - getTok(p) - eat(p, pxCurlyDirRi) - else: - getTok(p) # skip token - elif p.tok.ident.id == getIdent("ptr").id: - result = newNodeP(nkPtrTy, p) - getTok(p) - eat(p, pxCurlyDirRi) - elif p.tok.ident.id == getIdent("tuple").id: - result = newNodeP(nkTupleTy, p) - getTok(p) - eat(p, pxCurlyDirRi) - elif p.tok.ident.id == getIdent("acyclic").id: - result = newIdentNodeP(p.tok.ident, p) - getTok(p) - eat(p, pxCurlyDirRi) - else: - parMessage(p, errInvalidDirectiveX, $p.tok) - while true: - getTok(p) - if p.tok.xkind == pxCurlyDirRi or p.tok.xkind == pxEof: break - eat(p, pxCurlyDirRi) - result = ast.emptyNode - -proc getPrecedence(kind: TTokKind): int = - case kind - of pxDiv, pxMod, pxStar, pxSlash, pxShl, pxShr, pxAnd: result = 5 - of pxPlus, pxMinus, pxOr, pxXor: result = 4 - of pxIn, pxEquals, pxLe, pxLt, pxGe, pxGt, pxNeq, pxIs: result = 3 - else: result = -1 - -proc rangeExpr(p: var TParser): PNode = - var a = parseExpr(p) - if p.tok.xkind == pxDotDot: - result = newNodeP(nkRange, p) - addSon(result, a) - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - else: - result = a - -proc bracketExprList(p: var TParser, first: PNode): PNode = - result = newNodeP(nkBracketExpr, p) - addSon(result, first) - getTok(p) - skipCom(p, result) - while true: - if p.tok.xkind == pxBracketRi: - getTok(p) - break - if p.tok.xkind == pxEof: - parMessage(p, errTokenExpected, tokKindToStr(pxBracketRi)) - break - var a = rangeExpr(p) - skipCom(p, a) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - -proc exprColonEqExpr(p: var TParser, kind: TNodeKind, - tok: TTokKind): PNode = - var a = parseExpr(p) - if p.tok.xkind == tok: - result = newNodeP(kind, p) - getTok(p) - skipCom(p, result) - addSon(result, a) - addSon(result, parseExpr(p)) - else: - result = a - -proc exprListAux(p: var TParser, elemKind: TNodeKind, - endTok, sepTok: TTokKind, result: PNode) = - getTok(p) - skipCom(p, result) - while true: - if p.tok.xkind == endTok: - getTok(p) - break - if p.tok.xkind == pxEof: - parMessage(p, errTokenExpected, tokKindToStr(endTok)) - break - var a = exprColonEqExpr(p, elemKind, sepTok) - skipCom(p, a) - if (p.tok.xkind == pxComma) or (p.tok.xkind == pxSemicolon): - getTok(p) - skipCom(p, a) - addSon(result, a) - -proc qualifiedIdent(p: var TParser): PNode = - if p.tok.xkind == pxSymbol: - result = createIdentNodeP(p.tok.ident, p) - else: - parMessage(p, errIdentifierExpected, $p.tok) - return ast.emptyNode - getTok(p) - skipCom(p, result) - if p.tok.xkind == pxDot: - getTok(p) - skipCom(p, result) - if p.tok.xkind == pxSymbol: - var a = result - result = newNodeI(nkDotExpr, a.info) - addSon(result, a) - addSon(result, createIdentNodeP(p.tok.ident, p)) - getTok(p) - else: - parMessage(p, errIdentifierExpected, $p.tok) - -proc qualifiedIdentListAux(p: var TParser, endTok: TTokKind, - result: PNode) = - getTok(p) - skipCom(p, result) - while true: - if p.tok.xkind == endTok: - getTok(p) - break - if p.tok.xkind == pxEof: - parMessage(p, errTokenExpected, tokKindToStr(endTok)) - break - var a = qualifiedIdent(p) - skipCom(p, a) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - -proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind, - endTok, sepTok: TTokKind): PNode = - result = newNodeP(kind, p) - exprListAux(p, elemKind, endTok, sepTok, result) - -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 identOrLiteral(p: var TParser): PNode = - case p.tok.xkind - of pxSymbol: - result = createIdentNodeP(p.tok.ident, p) - getTok(p) - of pxIntLit: - result = newIntNodeP(nkIntLit, p.tok.iNumber, p) - setBaseFlags(result, p.tok.base) - getTok(p) - of pxInt64Lit: - result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p) - setBaseFlags(result, p.tok.base) - getTok(p) - of pxFloatLit: - result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p) - setBaseFlags(result, p.tok.base) - getTok(p) - of pxStrLit: - if len(p.tok.literal) != 1: result = newStrNodeP(nkStrLit, p.tok.literal, p) - else: result = newIntNodeP(nkCharLit, ord(p.tok.literal[0]), p) - getTok(p) - of pxNil: - result = newNodeP(nkNilLit, p) - getTok(p) - of pxParLe: - # () constructor - result = exprColonEqExprList(p, nkPar, nkExprColonExpr, pxParRi, pxColon) - #if hasSonWith(result, nkExprColonExpr) then - # replaceSons(result, nkExprColonExpr, nkExprEqExpr) - if (sonsLen(result) > 1) and not hasSonWith(result, nkExprColonExpr): - result.kind = nkBracket # is an array constructor - of pxBracketLe: - # [] constructor - result = newNodeP(nkBracket, p) - getTok(p) - skipCom(p, result) - while (p.tok.xkind != pxBracketRi) and (p.tok.xkind != pxEof): - var a = rangeExpr(p) - if a.kind == nkRange: - result.kind = nkCurly # it is definitely a set literal - opt(p, pxComma) - skipCom(p, a) - assert(a != nil) - addSon(result, a) - eat(p, pxBracketRi) - of pxCommand: - result = parseCommand(p) - else: - parMessage(p, errExprExpected, $(p.tok)) - getTok(p) # we must consume a token here to prevend endless loops! - result = ast.emptyNode - if result.kind != nkEmpty: skipCom(p, result) - -proc primary(p: var TParser): PNode = - # prefix operator? - if (p.tok.xkind == pxNot) or (p.tok.xkind == pxMinus) or - (p.tok.xkind == pxPlus): - result = newNodeP(nkPrefix, p) - var a = newIdentNodeP(getIdent($p.tok), p) - addSon(result, a) - getTok(p) - skipCom(p, a) - addSon(result, primary(p)) - return - elif p.tok.xkind == pxAt: - result = newNodeP(nkAddr, p) - var a = newIdentNodeP(getIdent($p.tok), p) - getTok(p) - if p.tok.xkind == pxBracketLe: - result = newNodeP(nkPrefix, p) - addSon(result, a) - addSon(result, identOrLiteral(p)) - else: - addSon(result, primary(p)) - return - result = identOrLiteral(p) - while true: - case p.tok.xkind - of pxParLe: - var a = result - result = newNodeP(nkCall, p) - addSon(result, a) - exprListAux(p, nkExprEqExpr, pxParRi, pxEquals, result) - of pxDot: - var a = result - result = newNodeP(nkDotExpr, p) - addSon(result, a) - getTok(p) # skip '.' - skipCom(p, result) - if p.tok.xkind == pxSymbol: - addSon(result, createIdentNodeP(p.tok.ident, p)) - getTok(p) - else: - parMessage(p, errIdentifierExpected, $p.tok) - of pxHat: - var a = result - result = newNodeP(nkBracketExpr, p) - addSon(result, a) - getTok(p) - of pxBracketLe: - result = bracketExprList(p, result) - else: break - -proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind = - var - nextop: TTokKind - v2, node, opNode: PNode - v = primary(p) # expand while operators have priorities higher than 'limit' - var op = p.tok.xkind - var opPred = getPrecedence(op) - while (opPred > limit): - node = newNodeP(nkInfix, p) - opNode = newIdentNodeP(getIdent($(p.tok)), p) # skip operator: - getTok(p) - case op - of pxPlus: - case p.tok.xkind - of pxPer: - getTok(p) - eat(p, pxCurlyDirRi) - opNode.ident = getIdent("+%") - of pxAmp: - getTok(p) - eat(p, pxCurlyDirRi) - opNode.ident = getIdent("&") - else: - discard - of pxMinus: - if p.tok.xkind == pxPer: - getTok(p) - eat(p, pxCurlyDirRi) - opNode.ident = getIdent("-%") - of pxEquals: - opNode.ident = getIdent("==") - of pxNeq: - opNode.ident = getIdent("!=") - else: - discard - skipCom(p, opNode) # read sub-expression with higher priority - nextop = lowestExprAux(p, v2, opPred) - addSon(node, opNode) - addSon(node, v) - addSon(node, v2) - v = node - op = nextop - opPred = getPrecedence(nextop) - result = op # return first untreated operator - -proc fixExpr(n: PNode): PNode = - result = n - case n.kind - of nkInfix: - if n.sons[1].kind == nkBracket: n.sons[1].kind = nkCurly - if n.sons[2].kind == nkBracket: n.sons[2].kind = nkCurly - if (n.sons[0].kind == nkIdent): - if (n.sons[0].ident.id == getIdent("+").id): - if (n.sons[1].kind == nkCharLit) and (n.sons[2].kind == nkStrLit) and - (n.sons[2].strVal == ""): - result = newStrNode(nkStrLit, chr(int(n.sons[1].intVal)) & "") - result.info = n.info - return # do not process sons as they don't exist anymore - elif (n.sons[1].kind in {nkCharLit, nkStrLit}) or - (n.sons[2].kind in {nkCharLit, nkStrLit}): - n.sons[0].ident = getIdent("&") # fix operator - else: - discard - if not (n.kind in {nkEmpty..nkNilLit}): - for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i]) - -proc parseExpr(p: var TParser): PNode = - var oldcontext = p.context - p.context = conExpr - if p.tok.xkind == pxCommand: - result = parseCommand(p) - else: - discard lowestExprAux(p, result, - 1) - result = fixExpr(result) - p.context = oldcontext - -proc parseExprStmt(p: var TParser): PNode = - var info = parLineInfo(p) - var a = parseExpr(p) - if p.tok.xkind == pxAsgn: - getTok(p) - skipCom(p, a) - var b = parseExpr(p) - result = newNodeI(nkAsgn, info) - addSon(result, a) - addSon(result, b) - else: - result = a - -proc inImportBlackList(ident: PIdent): bool = - for i in countup(low(ImportBlackList), high(ImportBlackList)): - if ident.id == getIdent(ImportBlackList[i]).id: - return true - -proc parseUsesStmt(p: var TParser): PNode = - var a: PNode - result = newNodeP(nkImportStmt, p) - getTok(p) # skip `import` - skipCom(p, result) - while true: - case p.tok.xkind - of pxEof: break - of pxSymbol: a = newIdentNodeP(p.tok.ident, p) - else: - parMessage(p, errIdentifierExpected, $(p.tok)) - break - getTok(p) # skip identifier, string - skipCom(p, a) - if pfImportBlackList notin p.flags or not inImportBlackList(a.ident): - addSon(result, createIdentNodeP(a.ident, p)) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - else: - break - if sonsLen(result) == 0: result = ast.emptyNode - -proc parseIncludeDir(p: var TParser): PNode = - result = newNodeP(nkIncludeStmt, p) - getTok(p) # skip `include` - var filename = "" - while true: - case p.tok.xkind - of pxSymbol, pxDot, pxDotDot, pxSlash: - add(filename, $p.tok) - getTok(p) - of pxStrLit: - filename = p.tok.literal - getTok(p) - break - of pxCurlyDirRi: - break - else: - parMessage(p, errIdentifierExpected, $p.tok) - break - addSon(result, newStrNodeP(nkStrLit, changeFileExt(filename, "nim"), p)) - if filename == "config.inc": result = ast.emptyNode - -proc definedExprAux(p: var TParser): PNode = - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP(getIdent("defined"), p)) - expectIdent(p) - addSon(result, createIdentNodeP(p.tok.ident, p)) - getTok(p) - -proc isHandledDirective(p: TParser): bool = - if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: - case toLower(p.tok.ident.s) - of "else", "endif": result = false - else: result = true - -proc parseStmtList(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - while true: - case p.tok.xkind - of pxEof: - break - of pxCurlyDirLe, pxStarDirLe: - if not isHandledDirective(p): break - else: - discard - addSon(result, parseStmt(p)) - if sonsLen(result) == 1: result = result.sons[0] - -proc parseIfDirAux(p: var TParser, result: PNode) = - addSon(result.sons[0], parseStmtList(p)) - if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: - var endMarker = succ(p.tok.xkind) - if toLower(p.tok.ident.s) == "else": - var s = newNodeP(nkElse, p) - while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p) - eat(p, endMarker) - addSon(s, parseStmtList(p)) - addSon(result, s) - if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: - endMarker = succ(p.tok.xkind) - if toLower(p.tok.ident.s) == "endif": - while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p) - eat(p, endMarker) - else: - parMessage(p, errXExpected, "{$endif}") - else: - parMessage(p, errXExpected, "{$endif}") - -proc parseIfdefDir(p: var TParser, endMarker: TTokKind): PNode = - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - addSon(result.sons[0], definedExprAux(p)) - eat(p, endMarker) - parseIfDirAux(p, result) - -proc parseIfndefDir(p: var TParser, endMarker: TTokKind): PNode = - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - var e = newNodeP(nkCall, p) - addSon(e, newIdentNodeP(getIdent("not"), p)) - addSon(e, definedExprAux(p)) - eat(p, endMarker) - addSon(result.sons[0], e) - parseIfDirAux(p, result) - -proc parseIfDir(p: var TParser, endMarker: TTokKind): PNode = - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - addSon(result.sons[0], parseExpr(p)) - eat(p, endMarker) - parseIfDirAux(p, result) - -proc parseDirective(p: var TParser): PNode = - result = ast.emptyNode - if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return - var endMarker = succ(p.tok.xkind) - if p.tok.ident != nil: - case toLower(p.tok.ident.s) - of "include": - result = parseIncludeDir(p) - eat(p, endMarker) - of "if": result = parseIfDir(p, endMarker) - of "ifdef": result = parseIfdefDir(p, endMarker) - of "ifndef": result = parseIfndefDir(p, endMarker) - else: - # skip unknown compiler directive - while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p) - eat(p, endMarker) - else: - eat(p, endMarker) - -proc parseRaise(p: var TParser): PNode = - result = newNodeP(nkRaiseStmt, p) - getTok(p) - skipCom(p, result) - if p.tok.xkind != pxSemicolon: addSon(result, parseExpr(p)) - else: addSon(result, ast.emptyNode) - -proc parseIf(p: var TParser): PNode = - result = newNodeP(nkIfStmt, p) - while true: - getTok(p) # skip ``if`` - var branch = newNodeP(nkElifBranch, p) - skipCom(p, branch) - addSon(branch, parseExpr(p)) - eat(p, pxThen) - skipCom(p, branch) - addSon(branch, parseStmt(p)) - skipCom(p, branch) - addSon(result, branch) - if p.tok.xkind == pxElse: - getTok(p) - if p.tok.xkind != pxIf: - # ordinary else part: - branch = newNodeP(nkElse, p) - skipCom(p, result) # BUGFIX - addSon(branch, parseStmt(p)) - addSon(result, branch) - break - else: - break - -proc parseWhile(p: var TParser): PNode = - result = newNodeP(nkWhileStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - eat(p, pxDo) - skipCom(p, result) - addSon(result, parseStmt(p)) - -proc parseRepeat(p: var TParser): PNode = - result = newNodeP(nkWhileStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, newIdentNodeP(getIdent("true"), p)) - var s = newNodeP(nkStmtList, p) - while p.tok.xkind != pxEof and p.tok.xkind != pxUntil: - addSon(s, parseStmt(p)) - eat(p, pxUntil) - var a = newNodeP(nkIfStmt, p) - skipCom(p, a) - var b = newNodeP(nkElifBranch, p) - var c = newNodeP(nkBreakStmt, p) - addSon(c, ast.emptyNode) - addSon(b, parseExpr(p)) - skipCom(p, a) - addSon(b, c) - addSon(a, b) - if b.sons[0].kind == nkIdent and b.sons[0].ident.id == getIdent("false").id: - discard - else: - addSon(s, a) - addSon(result, s) - -proc parseCase(p: var TParser): PNode = - var b: PNode - result = newNodeP(nkCaseStmt, p) - getTok(p) - addSon(result, parseExpr(p)) - eat(p, pxOf) - skipCom(p, result) - while (p.tok.xkind != pxEnd) and (p.tok.xkind != pxEof): - if p.tok.xkind == pxElse: - b = newNodeP(nkElse, p) - getTok(p) - else: - b = newNodeP(nkOfBranch, p) - while (p.tok.xkind != pxEof) and (p.tok.xkind != pxColon): - addSon(b, rangeExpr(p)) - opt(p, pxComma) - skipCom(p, b) - eat(p, pxColon) - skipCom(p, b) - addSon(b, parseStmt(p)) - addSon(result, b) - if b.kind == nkElse: break - eat(p, pxEnd) - -proc parseTry(p: var TParser): PNode = - result = newNodeP(nkTryStmt, p) - getTok(p) - skipCom(p, result) - var b = newNodeP(nkStmtList, p) - while not (p.tok.xkind in {pxFinally, pxExcept, pxEof, pxEnd}): - addSon(b, parseStmt(p)) - addSon(result, b) - if p.tok.xkind == pxExcept: - getTok(p) - while p.tok.ident.id == getIdent("on").id: - b = newNodeP(nkExceptBranch, p) - getTok(p) - var e = qualifiedIdent(p) - if p.tok.xkind == pxColon: - getTok(p) - e = qualifiedIdent(p) - addSon(b, e) - eat(p, pxDo) - addSon(b, parseStmt(p)) - addSon(result, b) - if p.tok.xkind == pxCommand: discard parseCommand(p) - if p.tok.xkind == pxElse: - b = newNodeP(nkExceptBranch, p) - getTok(p) - addSon(b, parseStmt(p)) - addSon(result, b) - if p.tok.xkind == pxFinally: - b = newNodeP(nkFinally, p) - getTok(p) - var e = newNodeP(nkStmtList, p) - while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd): - addSon(e, parseStmt(p)) - if sonsLen(e) == 0: addSon(e, newNodeP(nkNilLit, p)) - addSon(result, e) - eat(p, pxEnd) - -proc parseFor(p: var TParser): PNode = - result = newNodeP(nkForStmt, p) - getTok(p) - skipCom(p, result) - expectIdent(p) - addSon(result, createIdentNodeP(p.tok.ident, p)) - getTok(p) - eat(p, pxAsgn) - var a = parseExpr(p) - var b = ast.emptyNode - var c = newNodeP(nkCall, p) - if p.tok.xkind == pxTo: - addSon(c, newIdentNodeP(getIdent("countup"), p)) - getTok(p) - b = parseExpr(p) - elif p.tok.xkind == pxDownto: - addSon(c, newIdentNodeP(getIdent("countdown"), p)) - getTok(p) - b = parseExpr(p) - else: - parMessage(p, errTokenExpected, tokKindToStr(pxTo)) - addSon(c, a) - addSon(c, b) - eat(p, pxDo) - skipCom(p, result) - addSon(result, c) - addSon(result, parseStmt(p)) - -proc parseParam(p: var TParser): PNode = - var a: PNode - result = newNodeP(nkIdentDefs, p) - var v = ast.emptyNode - case p.tok.xkind - of pxConst: - getTok(p) - of pxVar: - getTok(p) - v = newNodeP(nkVarTy, p) - of pxOut: - getTok(p) - v = newNodeP(nkVarTy, p) - else: - discard - while true: - case p.tok.xkind - of pxSymbol: a = createIdentNodeP(p.tok.ident, p) - of pxColon, pxEof, pxParRi, pxEquals: break - else: - parMessage(p, errIdentifierExpected, $p.tok) - return - getTok(p) # skip identifier - skipCom(p, a) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - if p.tok.xkind == pxColon: - getTok(p) - skipCom(p, result) - if v.kind != nkEmpty: addSon(v, parseTypeDesc(p)) - else: v = parseTypeDesc(p) - addSon(result, v) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind != pxEquals: - parMessage(p, errColonOrEqualsExpected, $p.tok) - if p.tok.xkind == pxEquals: - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - else: - addSon(result, ast.emptyNode) - -proc parseParamList(p: var TParser): PNode = - var a: PNode - result = newNodeP(nkFormalParams, p) - addSon(result, ast.emptyNode) # return type - if p.tok.xkind == pxParLe: - p.inParamList = true - getTok(p) - skipCom(p, result) - while true: - case p.tok.xkind - of pxSymbol, pxConst, pxVar, pxOut: - a = parseParam(p) - of pxParRi: - getTok(p) - break - else: - parMessage(p, errTokenExpected, ")") - break - skipCom(p, a) - if p.tok.xkind == pxSemicolon: - getTok(p) - skipCom(p, a) - addSon(result, a) - p.inParamList = false - if p.tok.xkind == pxColon: - getTok(p) - skipCom(p, result) - result.sons[0] = parseTypeDesc(p) - -proc parseCallingConvention(p: var TParser): PNode = - result = ast.emptyNode - if p.tok.xkind == pxSymbol: - case toLower(p.tok.ident.s) - of "stdcall", "cdecl", "safecall", "syscall", "inline", "fastcall": - result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(p.tok.ident, p)) - getTok(p) - opt(p, pxSemicolon) - of "register": - result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("fastcall"), p)) - getTok(p) - opt(p, pxSemicolon) - else: - discard - -proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode = - var e: PNode - result = parseCallingConvention(p) - noBody = false - while p.tok.xkind == pxSymbol: - case toLower(p.tok.ident.s) - of "assembler", "overload", "far": - getTok(p) - opt(p, pxSemicolon) - of "forward": - noBody = true - getTok(p) - opt(p, pxSemicolon) - of "importc": - # This is a fake for platform module. There is no ``importc`` - # directive in Pascal. - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("importc"), p)) - noBody = true - getTok(p) - opt(p, pxSemicolon) - of "noconv": - # This is a fake for platform module. There is no ``noconv`` - # directive in Pascal. - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("noconv"), p)) - noBody = true - getTok(p) - opt(p, pxSemicolon) - of "procvar": - # This is a fake for the Nimrod compiler. There is no ``procvar`` - # directive in Pascal. - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("procvar"), p)) - getTok(p) - opt(p, pxSemicolon) - of "varargs": - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("varargs"), p)) - getTok(p) - opt(p, pxSemicolon) - of "external": - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - getTok(p) - noBody = true - e = newNodeP(nkExprColonExpr, p) - addSon(e, newIdentNodeP(getIdent("dynlib"), p)) - addSon(e, parseExpr(p)) - addSon(result, e) - opt(p, pxSemicolon) - if (p.tok.xkind == pxSymbol) and - (p.tok.ident.id == getIdent("name").id): - e = newNodeP(nkExprColonExpr, p) - getTok(p) - addSon(e, newIdentNodeP(getIdent("importc"), p)) - addSon(e, parseExpr(p)) - addSon(result, e) - else: - addSon(result, newIdentNodeP(getIdent("importc"), p)) - opt(p, pxSemicolon) - else: - e = parseCallingConvention(p) - if e.kind == nkEmpty: break - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, e.sons[0]) - -proc parseRoutineType(p: var TParser): PNode = - result = newNodeP(nkProcTy, p) - getTok(p) - skipCom(p, result) - addSon(result, parseParamList(p)) - opt(p, pxSemicolon) - addSon(result, parseCallingConvention(p)) - skipCom(p, result) - -proc parseEnum(p: var TParser): PNode = - var a: PNode - result = newNodeP(nkEnumTy, p) - getTok(p) - skipCom(p, result) - addSon(result, ast.emptyNode) # it does not inherit from any enumeration - while true: - case p.tok.xkind - of pxEof, pxParRi: break - of pxSymbol: a = newIdentNodeP(p.tok.ident, p) - else: - parMessage(p, errIdentifierExpected, $(p.tok)) - break - getTok(p) # skip identifier - skipCom(p, a) - if (p.tok.xkind == pxEquals) or (p.tok.xkind == pxAsgn): - getTok(p) - skipCom(p, a) - var b = a - a = newNodeP(nkEnumFieldDef, p) - addSon(a, b) - addSon(a, parseExpr(p)) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - eat(p, pxParRi) - -proc identVis(p: var TParser): PNode = - # identifier with visability - var a = createIdentNodeP(p.tok.ident, p) - if p.section == seInterface: - result = newNodeP(nkPostfix, p) - addSon(result, newIdentNodeP(getIdent("*"), p)) - addSon(result, a) - else: - result = a - getTok(p) - -type - TSymbolParser = proc (p: var TParser): PNode {.nimcall.} - -proc rawIdent(p: var TParser): PNode = - result = createIdentNodeP(p.tok.ident, p) - getTok(p) - -proc parseIdentColonEquals(p: var TParser, - identParser: TSymbolParser): PNode = - var a: PNode - result = newNodeP(nkIdentDefs, p) - while true: - case p.tok.xkind - of pxSymbol: a = identParser(p) - of pxColon, pxEof, pxParRi, pxEquals: break - else: - parMessage(p, errIdentifierExpected, $(p.tok)) - return - skipCom(p, a) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - if p.tok.xkind == pxColon: - getTok(p) - skipCom(p, result) - addSon(result, parseTypeDesc(p)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind != pxEquals: - parMessage(p, errColonOrEqualsExpected, $(p.tok)) - if p.tok.xkind == pxEquals: - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind == pxSemicolon: - getTok(p) - skipCom(p, result) - -proc parseRecordCase(p: var TParser): PNode = - var b, c: PNode - result = newNodeP(nkRecCase, p) - getTok(p) - var a = newNodeP(nkIdentDefs, p) - addSon(a, rawIdent(p)) - eat(p, pxColon) - addSon(a, parseTypeDesc(p)) - addSon(a, ast.emptyNode) - addSon(result, a) - eat(p, pxOf) - skipCom(p, result) - while true: - case p.tok.xkind - of pxEof, pxEnd: - break - of pxElse: - b = newNodeP(nkElse, p) - getTok(p) - else: - b = newNodeP(nkOfBranch, p) - while (p.tok.xkind != pxEof) and (p.tok.xkind != pxColon): - addSon(b, rangeExpr(p)) - opt(p, pxComma) - skipCom(p, b) - eat(p, pxColon) - skipCom(p, b) - c = newNodeP(nkRecList, p) - eat(p, pxParLe) - while (p.tok.xkind != pxParRi) and (p.tok.xkind != pxEof): - addSon(c, parseIdentColonEquals(p, rawIdent)) - opt(p, pxSemicolon) - skipCom(p, lastSon(c)) - eat(p, pxParRi) - opt(p, pxSemicolon) - if sonsLen(c) > 0: skipCom(p, lastSon(c)) - else: addSon(c, newNodeP(nkNilLit, p)) - addSon(b, c) - addSon(result, b) - if b.kind == nkElse: break - -proc parseRecordPart(p: var TParser): PNode = - result = ast.emptyNode - while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd): - if result.kind == nkEmpty: result = newNodeP(nkRecList, p) - case p.tok.xkind - of pxSymbol: - addSon(result, parseIdentColonEquals(p, rawIdent)) - opt(p, pxSemicolon) - skipCom(p, lastSon(result)) - of pxCase: - addSon(result, parseRecordCase(p)) - of pxComment: - skipCom(p, lastSon(result)) - else: - parMessage(p, errIdentifierExpected, $p.tok) - break - -proc exSymbol(n: var PNode) = - case n.kind - of nkPostfix: - discard - of nkPragmaExpr: - exSymbol(n.sons[0]) - of nkIdent, nkAccQuoted: - var a = newNodeI(nkPostFix, n.info) - addSon(a, newIdentNode(getIdent("*"), n.info)) - addSon(a, n) - n = a - else: internalError(n.info, "exSymbol(): " & $n.kind) - -proc fixRecordDef(n: var PNode) = - case n.kind - of nkRecCase: - fixRecordDef(n.sons[0]) - for i in countup(1, sonsLen(n) - 1): - var length = sonsLen(n.sons[i]) - fixRecordDef(n.sons[i].sons[length - 1]) - of nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch, nkObjectTy: - for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i]) - of nkIdentDefs: - for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i]) - of nkNilLit, nkEmpty: discard - else: internalError(n.info, "fixRecordDef(): " & $n.kind) - -proc addPragmaToIdent(ident: var PNode, pragma: PNode) = - var pragmasNode: PNode - if ident.kind != nkPragmaExpr: - pragmasNode = newNodeI(nkPragma, ident.info) - var e = newNodeI(nkPragmaExpr, ident.info) - addSon(e, ident) - addSon(e, pragmasNode) - ident = e - else: - pragmasNode = ident.sons[1] - if pragmasNode.kind != nkPragma: - internalError(ident.info, "addPragmaToIdent") - addSon(pragmasNode, pragma) - -proc parseRecordBody(p: var TParser, result, definition: PNode) = - skipCom(p, result) - var a = parseRecordPart(p) - if result.kind != nkTupleTy: fixRecordDef(a) - addSon(result, a) - eat(p, pxEnd) - case p.tok.xkind - of pxSymbol: - if p.tok.ident.id == getIdent("acyclic").id: - if definition != nil: - addPragmaToIdent(definition.sons[0], newIdentNodeP(p.tok.ident, p)) - else: - internalError(result.info, "anonymous record is not supported") - getTok(p) - else: - internalError(result.info, "parseRecordBody") - of pxCommand: - if definition != nil: addPragmaToIdent(definition.sons[0], parseCommand(p)) - else: internalError(result.info, "anonymous record is not supported") - else: - discard - opt(p, pxSemicolon) - skipCom(p, result) - -proc parseRecordOrObject(p: var TParser, kind: TNodeKind, - definition: PNode): PNode = - result = newNodeP(kind, p) - getTok(p) - addSon(result, ast.emptyNode) - if p.tok.xkind == pxParLe: - var a = newNodeP(nkOfInherit, p) - getTok(p) - addSon(a, parseTypeDesc(p)) - addSon(result, a) - eat(p, pxParRi) - else: - addSon(result, ast.emptyNode) - parseRecordBody(p, result, definition) - -proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode = - var oldcontext = p.context - p.context = conTypeDesc - if p.tok.xkind == pxPacked: getTok(p) - case p.tok.xkind - of pxCommand: - result = parseCommand(p, definition) - of pxProcedure, pxFunction: - result = parseRoutineType(p) - of pxRecord: - getTok(p) - if p.tok.xkind == pxCommand: - result = parseCommand(p) - if result.kind != nkTupleTy: internalError(result.info, "parseTypeDesc") - parseRecordBody(p, result, definition) - var a = lastSon(result) # embed nkRecList directly into nkTupleTy - for i in countup(0, sonsLen(a) - 1): - if i == 0: result.sons[sonsLen(result) - 1] = a.sons[0] - else: addSon(result, a.sons[i]) - else: - result = newNodeP(nkObjectTy, p) - addSon(result, ast.emptyNode) - addSon(result, ast.emptyNode) - parseRecordBody(p, result, definition) - if definition != nil: - addPragmaToIdent(definition.sons[0], newIdentNodeP(getIdent("final"), p)) - else: - internalError(result.info, "anonymous record is not supported") - of pxObject: result = parseRecordOrObject(p, nkObjectTy, definition) - of pxParLe: result = parseEnum(p) - of pxArray: - result = newNodeP(nkBracketExpr, p) - getTok(p) - if p.tok.xkind == pxBracketLe: - addSon(result, newIdentNodeP(getIdent("array"), p)) - getTok(p) - addSon(result, rangeExpr(p)) - eat(p, pxBracketRi) - else: - if p.inParamList: addSon(result, newIdentNodeP(getIdent("openarray"), p)) - else: addSon(result, newIdentNodeP(getIdent("seq"), p)) - eat(p, pxOf) - addSon(result, parseTypeDesc(p)) - of pxSet: - result = newNodeP(nkBracketExpr, p) - getTok(p) - eat(p, pxOf) - addSon(result, newIdentNodeP(getIdent("set"), p)) - addSon(result, parseTypeDesc(p)) - of pxHat: - getTok(p) - if p.tok.xkind == pxCommand: result = parseCommand(p) - elif pfRefs in p.flags: result = newNodeP(nkRefTy, p) - else: result = newNodeP(nkPtrTy, p) - addSon(result, parseTypeDesc(p)) - of pxType: - getTok(p) - result = parseTypeDesc(p) - else: - var a = primary(p) - if p.tok.xkind == pxDotDot: - result = newNodeP(nkBracketExpr, p) - var r = newNodeP(nkRange, p) - addSon(result, newIdentNodeP(getIdent("range"), p)) - getTok(p) - addSon(r, a) - addSon(r, parseExpr(p)) - addSon(result, r) - else: - result = a - p.context = oldcontext - -proc parseTypeDef(p: var TParser): PNode = - result = newNodeP(nkTypeDef, p) - addSon(result, identVis(p)) - addSon(result, ast.emptyNode) # generic params - if p.tok.xkind == pxEquals: - getTok(p) - skipCom(p, result) - addSon(result, parseTypeDesc(p, result)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind == pxSemicolon: - getTok(p) - skipCom(p, result) - -proc parseTypeSection(p: var TParser): PNode = - result = newNodeP(nkTypeSection, p) - getTok(p) - skipCom(p, result) - while p.tok.xkind == pxSymbol: - addSon(result, parseTypeDef(p)) - -proc parseConstant(p: var TParser): PNode = - result = newNodeP(nkConstDef, p) - addSon(result, identVis(p)) - if p.tok.xkind == pxColon: - getTok(p) - skipCom(p, result) - addSon(result, parseTypeDesc(p)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind != pxEquals: - parMessage(p, errColonOrEqualsExpected, $(p.tok)) - if p.tok.xkind == pxEquals: - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind == pxSemicolon: - getTok(p) - skipCom(p, result) - -proc parseConstSection(p: var TParser): PNode = - result = newNodeP(nkConstSection, p) - getTok(p) - skipCom(p, result) - while p.tok.xkind == pxSymbol: - addSon(result, parseConstant(p)) - -proc parseVar(p: var TParser): PNode = - result = newNodeP(nkVarSection, p) - getTok(p) - skipCom(p, result) - while p.tok.xkind == pxSymbol: - addSon(result, parseIdentColonEquals(p, identVis)) - p.lastVarSection = result - -proc parseRoutine(p: var TParser): PNode = - var noBody: bool - result = newNodeP(nkProcDef, p) - getTok(p) - skipCom(p, result) - expectIdent(p) - addSon(result, identVis(p)) - # patterns, generic parameters: - addSon(result, ast.emptyNode) - addSon(result, ast.emptyNode) - addSon(result, parseParamList(p)) - opt(p, pxSemicolon) - addSon(result, parseRoutineSpecifiers(p, noBody)) - addSon(result, ast.emptyNode) - if (p.section == seInterface) or noBody: - addSon(result, ast.emptyNode) - else: - var stmts = newNodeP(nkStmtList, p) - while true: - case p.tok.xkind - of pxVar: addSon(stmts, parseVar(p)) - of pxConst: addSon(stmts, parseConstSection(p)) - of pxType: addSon(stmts, parseTypeSection(p)) - of pxComment: skipCom(p, result) - of pxBegin: break - else: - parMessage(p, errTokenExpected, "begin") - break - var a = parseStmt(p) - for i in countup(0, sonsLen(a) - 1): addSon(stmts, a.sons[i]) - addSon(result, stmts) - -proc fixExit(p: var TParser, n: PNode): bool = - if (p.tok.ident.id == getIdent("exit").id): - var length = sonsLen(n) - if (length <= 0): return - var a = n.sons[length-1] - if (a.kind == nkAsgn) and (a.sons[0].kind == nkIdent) and - (a.sons[0].ident.id == getIdent("result").id): - delSon(a, 0) - a.kind = nkReturnStmt - result = true - getTok(p) - opt(p, pxSemicolon) - skipCom(p, a) - -proc fixVarSection(p: var TParser, counter: PNode) = - if p.lastVarSection == nil: return - assert(counter.kind == nkIdent) - for i in countup(0, sonsLen(p.lastVarSection) - 1): - var v = p.lastVarSection.sons[i] - for j in countup(0, sonsLen(v) - 3): - if v.sons[j].ident.id == counter.ident.id: - delSon(v, j) - if sonsLen(v) <= 2: - delSon(p.lastVarSection, i) - return - -proc exSymbols(n: PNode) = - case n.kind - of nkEmpty..nkNilLit: discard - of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos]) - of nkWhenStmt, nkStmtList: - for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i]) - of nkVarSection, nkConstSection: - for i in countup(0, sonsLen(n) - 1): exSymbol(n.sons[i].sons[0]) - of nkTypeSection: - for i in countup(0, sonsLen(n) - 1): - exSymbol(n.sons[i].sons[0]) - if n.sons[i].sons[2].kind == nkObjectTy: - fixRecordDef(n.sons[i].sons[2]) - else: discard - -proc parseBegin(p: var TParser, result: PNode) = - getTok(p) - while true: - case p.tok.xkind - of pxComment: addSon(result, parseStmt(p)) - of pxSymbol: - if not fixExit(p, result): addSon(result, parseStmt(p)) - of pxEnd: - getTok(p) - break - of pxSemicolon: getTok(p) - of pxEof: parMessage(p, errExprExpected) - else: - var a = parseStmt(p) - if a.kind != nkEmpty: addSon(result, a) - if sonsLen(result) == 0: addSon(result, newNodeP(nkNilLit, p)) - -proc parseStmt(p: var TParser): PNode = - var oldcontext = p.context - p.context = conStmt - result = ast.emptyNode - case p.tok.xkind - of pxBegin: - result = newNodeP(nkStmtList, p) - parseBegin(p, result) - of pxCommand: result = parseCommand(p) - of pxCurlyDirLe, pxStarDirLe: - if isHandledDirective(p): result = parseDirective(p) - of pxIf: result = parseIf(p) - of pxWhile: result = parseWhile(p) - of pxRepeat: result = parseRepeat(p) - of pxCase: result = parseCase(p) - of pxTry: result = parseTry(p) - of pxProcedure, pxFunction: result = parseRoutine(p) - of pxType: result = parseTypeSection(p) - of pxConst: result = parseConstSection(p) - of pxVar: result = parseVar(p) - of pxFor: - result = parseFor(p) - fixVarSection(p, result.sons[0]) - of pxRaise: result = parseRaise(p) - of pxUses: result = parseUsesStmt(p) - of pxProgram, pxUnit, pxLibrary: - # skip the pointless header - while not (p.tok.xkind in {pxSemicolon, pxEof}): getTok(p) - getTok(p) - of pxInitialization: getTok(p) # just skip the token - of pxImplementation: - p.section = seImplementation - result = newNodeP(nkCommentStmt, p) - result.comment = "# implementation" - getTok(p) - of pxInterface: - p.section = seInterface - getTok(p) - of pxComment: - result = newNodeP(nkCommentStmt, p) - skipCom(p, result) - of pxSemicolon: getTok(p) - of pxSymbol: - if p.tok.ident.id == getIdent("break").id: - result = newNodeP(nkBreakStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, ast.emptyNode) - elif p.tok.ident.id == getIdent("continue").id: - result = newNodeP(nkContinueStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, ast.emptyNode) - elif p.tok.ident.id == getIdent("exit").id: - result = newNodeP(nkReturnStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, ast.emptyNode) - else: - result = parseExprStmt(p) - of pxDot: getTok(p) # BUGFIX for ``end.`` in main program - else: result = parseExprStmt(p) - opt(p, pxSemicolon) - if result.kind != nkEmpty: skipCom(p, result) - p.context = oldcontext - -proc parseUnit(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - getTok(p) # read first token - while true: - case p.tok.xkind - of pxEof, pxEnd: break - of pxBegin: parseBegin(p, result) - of pxCurlyDirLe, pxStarDirLe: - if isHandledDirective(p): addSon(result, parseDirective(p)) - else: parMessage(p, errXNotAllowedHere, p.tok.ident.s) - else: addSon(result, parseStmt(p)) - opt(p, pxEnd) - opt(p, pxDot) - if p.tok.xkind != pxEof: - addSon(result, parseStmt(p)) # comments after final 'end.' - diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index a17773aa4b..d73494c6e0 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -24,7 +24,8 @@ const wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, - wGensym, wInject, wRaises, wTags, wUses, wOperator, wDelegator, wGcSafe} + wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, + wOverride} converterPragmas* = procPragmas methodPragmas* = procPragmas templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, @@ -35,8 +36,8 @@ const iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises, - wTags, wUses, wOperator, wGcSafe} - exprPragmas* = {wLine} + wTags, wLocks, wGcSafe} + exprPragmas* = {wLine, wLocks} stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, @@ -44,27 +45,27 @@ const wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated, wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto, - wInjectStmt} + wInjectStmt, wDeprecated} lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, - wRaises, wUses, wTags, wGcSafe} + wRaises, wLocks, wTags, wGcSafe} typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow, wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wBorrow, wGcSafe} fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, - wImportCpp, wImportObjC, wError} + wImportCpp, wImportObjC, wError, wGuard} varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern, wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal, - wGensym, wInject, wCodegenDecl} + wGensym, wInject, wCodegenDecl, wGuard} constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl, wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject} letPragmas* = varPragmas procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect, - wThread, wRaises, wUses, wTags, wGcSafe} + wThread, wRaises, wLocks, wTags, wGcSafe} allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) @@ -127,12 +128,16 @@ proc processImportCpp(s: PSym, extname: string) = incl(s.flags, sfImportc) incl(s.flags, sfInfixCall) excl(s.flags, sfForward) + let m = s.getModule() + incl(m.flags, sfCompileToCpp) proc processImportObjC(s: PSym, extname: string) = setExternName(s, extname) incl(s.flags, sfImportc) incl(s.flags, sfNamedParamCall) excl(s.flags, sfForward) + let m = s.getModule() + incl(m.flags, sfCompileToObjC) proc newEmptyStrNode(n: PNode): PNode {.noinline.} = result = newNodeIT(nkStrLit, n.info, getSysType(tyString)) @@ -513,27 +518,6 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) = else: invalidPragma(n) -proc pragmaUses(c: PContext, n: PNode) = - proc processExc(c: PContext, x: PNode): PNode = - if x.kind in {nkAccQuoted, nkIdent, nkSym, - nkOpenSymChoice, nkClosedSymChoice}: - if considerQuotedIdent(x).s == "*": - return newSymNode(ast.anyGlobal) - result = c.semExpr(c, x) - if result.kind != nkSym or sfGlobal notin result.sym.flags: - localError(x.info, "'$1' is not a global variable" % result.renderTree) - result = newSymNode(ast.anyGlobal) - - if n.kind == nkExprColonExpr: - let it = n.sons[1] - if it.kind notin {nkCurly, nkBracket}: - n.sons[1] = processExc(c, it) - else: - for i in 0 .. % high(int16): localError(it.info, errPowerOfTwoExpected) else: - sym.typ.align = align - of wSize: + sym.typ.align = align.int16 + of wSize: if sym.typ == nil: invalidPragma(it) var size = expectIntLit(c, it) if not isPowerOfTwo(size) or size <= 0 or size > 8: @@ -628,11 +651,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, # implies nodecl, because otherwise header would not make sense if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s) of wDestructor: - if sym.typ.sons.len == 2: - sym.flags.incl sfDestructor - else: - invalidPragma(it) - of wNosideeffect: + sym.flags.incl sfOverriden + if sym.name.s.normalize != "destroy": + localError(n.info, errGenerated, "destructor has to be named 'destroy'") + of wOverride: + sym.flags.incl sfOverriden + of wNosideeffect: noVal(it) incl(sym.flags, sfNoSideEffect) if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect) @@ -646,17 +670,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, processDynLib(c, it, sym) of wCompilerproc: noVal(it) # compilerproc may not get a string! - if sfFromGeneric notin sym.flags: - makeExternExport(sym, "$1", it.info) - incl(sym.flags, sfCompilerProc) - incl(sym.flags, sfUsed) # suppress all those stupid warnings - registerCompilerProc(sym) - of wProcVar: + if sfFromGeneric notin sym.flags: markCompilerProc(sym) + of wProcVar: noVal(it) incl(sym.flags, sfProcvar) - of wDeprecated: - noVal(it) - if sym != nil: incl(sym.flags, sfDeprecated) + of wDeprecated: + if it.kind == nkExprColonExpr: deprecatedStmt(c, it) + elif sym != nil: incl(sym.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated) of wVarargs: noVal(it) @@ -787,10 +807,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, if sym == nil: invalidPragma(it) of wLine: pragmaLine(c, it) of wRaises, wTags: pragmaRaisesOrTags(c, it) - of wUses: pragmaUses(c, it) - of wOperator: - if sym == nil: invalidPragma(it) - else: sym.position = expectIntLit(c, it) + of wGuard: + if sym == nil or sym.kind notin {skVar, skLet, skField}: + invalidPragma(it) + else: + sym.guard = pragmaGuard(c, it, sym.kind) of wInjectStmt: if it.kind != nkExprColonExpr: localError(it.info, errExprExpected) diff --git a/compiler/procfind.nim b/compiler/procfind.nim index 0354d585d3..9f52cc117c 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -70,8 +70,15 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym = var it: TIdentIter result = initIdentIter(it, scope.symbols, fn.name) while result != nil: - if result.kind in skProcKinds and - sameType(result.typ, fn.typ, flags): return + if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags): + case equalParams(result.typ.n, fn.typ.n) + of paramsEqual: + return + of paramsIncompatible: + localError(fn.info, errNotOverloadable, fn.name.s) + return + of paramsNotEqual: + discard result = nextIdentIter(it, scope.symbols) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 0b1312ccc8..c97b2f3216 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -925,7 +925,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: gsub(g, n.sons[0]) of nkLambda: - putWithSpace(g, tkLambda, "proc") + putWithSpace(g, tkProc, "proc") gsub(g, n.sons[paramsPos]) gsub(g, n.sons[pragmasPos]) put(g, tkSpaces, Space) diff --git a/compiler/sem.nim b/compiler/sem.nim index 8025ef70de..26a59334c0 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -16,7 +16,7 @@ import procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch, intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting, evaltempl, patterns, parampatterns, sempass2, pretty, semmacrosanity, - semparallel + semparallel, lowerings # implementation diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 65a2d7ab89..927b23cf25 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -81,6 +81,8 @@ proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) = if c.inCompilesContext > 0: # fail fast: globalError(n.info, errTypeMismatch, "") + if errors.len == 0: + localError(n.info, errExprXCannotBeCalled, n[0].renderTree) var result = msgKindToString(errTypeMismatch) add(result, describeArgs(c, n, 1)) add(result, ')') diff --git a/compiler/semdestruct.nim b/compiler/semdestruct.nim index 791bef823f..3c30dc1bd9 100644 --- a/compiler/semdestruct.nim +++ b/compiler/semdestruct.nim @@ -125,8 +125,7 @@ proc instantiateDestructor(c: PContext, typ: PType): PType = # The destructor is either user-defined or automatically # generated by the compiler in a member-wise fashion. var t = skipTypes(typ, {tyConst, tyMutable}).skipGenericAlias - let typeHoldingUserDefinition = if t.kind == tyGenericInst: t.base - else: t + let typeHoldingUserDefinition = if t.kind == tyGenericInst: t.base else: t if typeHoldingUserDefinition.destructor != nil: # XXX: This is not entirely correct for recursive types, but we need diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 7f97124e12..46e6f1ab3c 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -82,7 +82,8 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, tyTuple, tySet, tyUInt..tyUInt64: - result = inlineConst(n, s) + if s.magic == mNone: result = inlineConst(n, s) + else: result = newSymNode(s, n.info) of tyArrayConstr, tySequence: # Consider:: # const x = [] @@ -184,13 +185,15 @@ proc isCastable(dst, src: PType): bool = # castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString, # tySequence, tyPointer, tyNil, tyOpenArray, # tyProc, tySet, tyEnum, tyBool, tyChar} + if skipTypes(dst, abstractInst-{tyOpenArray}).kind == tyOpenArray: + return false var dstSize, srcSize: BiggestInt dstSize = computeSize(dst) srcSize = computeSize(src) if dstSize < 0: result = false - elif srcSize < 0: + elif srcSize < 0: result = false elif not typeAllowed(dst, skParam): result = false @@ -198,6 +201,8 @@ proc isCastable(dst, src: PType): bool = result = (dstSize >= srcSize) or (skipTypes(dst, abstractInst).kind in IntegralTypes) or (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes) + if result and src.kind == tyNil: + result = dst.size <= platform.ptrSize proc isSymChoice(n: PNode): bool {.inline.} = result = n.kind in nkSymChoices @@ -591,7 +596,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = const FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl, mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap, - mAppendSeqElem, mNewSeq, mReset, mShallowCopy} + mAppendSeqElem, mNewSeq, mReset, mShallowCopy, mDeepCopy} # get the real type of the callee # it may be a proc var with a generic alias type, so we skip over them @@ -657,7 +662,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = # optimization pass: not necessary for correctness of the semantic pass if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and - {sfForward, sfImportc} * callee.flags == {}: + {sfForward, sfImportc} * callee.flags == {} and n.typ != nil: if sfCompileTime notin callee.flags and optImplicitStatic notin gOptions: return @@ -1369,20 +1374,19 @@ proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = if onlyCurrentScope: return checkSonsLen(n, 2) var m = lookUpForDefined(c, n.sons[0], onlyCurrentScope) - if (m != nil) and (m.kind == skModule): - if (n.sons[1].kind == nkIdent): - var ident = n.sons[1].ident - if m == c.module: - result = strTableGet(c.topLevelScope.symbols, ident) - else: - result = strTableGet(m.tab, ident) + if m != nil and m.kind == skModule: + let ident = considerQuotedIdent(n[1]) + if m == c.module: + result = strTableGet(c.topLevelScope.symbols, ident) else: - localError(n.sons[1].info, errIdentifierExpected, "") + result = strTableGet(m.tab, ident) of nkAccQuoted: result = lookUpForDefined(c, considerQuotedIdent(n), onlyCurrentScope) of nkSym: result = n.sym - else: + of nkOpenSymChoice, nkClosedSymChoice: + result = n.sons[0].sym + else: localError(n.info, errIdentifierExpected, renderTree(n)) result = nil @@ -1390,10 +1394,16 @@ proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = checkSonsLen(n, 2) # we replace this node by a 'true' or 'false' node: result = newIntNode(nkIntLit, 0) - if lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: - result.intVal = 1 - elif not onlyCurrentScope and (n.sons[1].kind == nkIdent) and - condsyms.isDefined(n.sons[1].ident): + if not onlyCurrentScope and considerQuotedIdent(n[0]).s == "defined": + if n.sons[1].kind != nkIdent: + localError(n.info, "obsolete usage of 'defined', use 'declared' instead") + elif condsyms.isDefined(n.sons[1].ident): + result.intVal = 1 + elif not condsyms.isDeclared(n.sons[1].ident): + message(n.info, warnUser, + "undeclared conditional symbol; use --symbol to declare it: " & + n[1].ident.s) + elif lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: result.intVal = 1 result.info = n.info result.typ = getSysType(tyBool) @@ -1604,6 +1614,11 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType; initIdTable(bindings) bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t) result = c.semGenerateInstance(c, sym, bindings, info) + # since it's an instantiation, we unmark it as a compilerproc. Otherwise + # codegen would fail: + if sfCompilerProc in result.flags: + result.flags = result.flags - {sfCompilerProc, sfExportC, sfImportC} + result.loc.r = nil proc setMs(n: PNode, s: PSym): PNode = result = n @@ -1642,10 +1657,10 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = result = setMs(n, s) result.sons[1] = semExpr(c, n.sons[1]) if not result[1].typ.isEmptyType: - if c.inParallelStmt > 0: - result.typ = result[1].typ - else: + if spawnResult(result[1].typ, c.inParallelStmt > 0) == srFlowVar: result.typ = createFlowVar(c, result[1].typ, n.info) + else: + result.typ = result[1].typ result.add instantiateCreateFlowVarCall(c, result[1].typ, n.info).newSymNode else: result = semDirectOp(c, n, flags) @@ -1757,8 +1772,9 @@ proc checkPar(n: PNode): TParKind = var length = sonsLen(n) if length == 0: result = paTuplePositions # () - elif length == 1: - result = paSingle # (expr) + elif length == 1: + if n.sons[0].kind == nkExprColonExpr: result = paTupleFields + else: result = paSingle # (expr) else: if n.sons[0].kind == nkExprColonExpr: result = paTupleFields else: result = paTuplePositions diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 934434951c..a004d14659 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -36,10 +36,11 @@ proc semGenericStmtScope(c: PContext, n: PNode, template macroToExpand(s: expr): expr = s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfImmediate in s.flags) -proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode = +proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, + ctx: var TIntSet): PNode = incl(s.flags, sfUsed) case s.kind - of skUnknown: + of skUnknown: # Introduced in this pass! Leave it as an identifier. result = n of skProc, skMethod, skIterators, skConverter: @@ -48,11 +49,13 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode = if macroToExpand(s): let n = fixImmediateParams(n) result = semTemplateExpr(c, n, s, {efNoSemCheck}) + result = semGenericStmt(c, result, {}, ctx) else: result = symChoice(c, n, s, scOpen) of skMacro: if macroToExpand(s): result = semMacroExpr(c, n, n, s, {efNoSemCheck}) + result = semGenericStmt(c, result, {}, ctx) else: result = symChoice(c, n, s, scOpen) of skGenericParam: @@ -80,7 +83,7 @@ proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags, elif s.name.id in ctx: result = symChoice(c, n, s, scForceOpen) else: - result = semGenericStmtSymbol(c, n, s) + result = semGenericStmtSymbol(c, n, s, ctx) # else: leave as nkIdent proc newDot(n, b: PNode): PNode = @@ -95,8 +98,9 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, var s = qualifiedLookUp(c, n, luf) if s != nil: - result = semGenericStmtSymbol(c, n, s) + result = semGenericStmtSymbol(c, n, s, ctx) else: + n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx) result = n let n = n[1] let ident = considerQuotedIdent(n) @@ -107,7 +111,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, elif s.name.id in ctx: result = newDot(result, symChoice(c, n, s, scForceOpen)) else: - let sym = semGenericStmtSymbol(c, n, s) + let sym = semGenericStmtSymbol(c, n, s, ctx) if sym.kind == nkSym: result = newDot(result, symChoice(c, n, s, scForceOpen)) else: @@ -158,6 +162,7 @@ proc semGenericStmt(c: PContext, n: PNode, of skMacro: if macroToExpand(s): result = semMacroExpr(c, n, n, s, {efNoSemCheck}) + result = semGenericStmt(c, result, {}, ctx) else: n.sons[0] = symChoice(c, n.sons[0], s, scOption) result = n @@ -165,6 +170,7 @@ proc semGenericStmt(c: PContext, n: PNode, if macroToExpand(s): let n = fixImmediateParams(n) result = semTemplateExpr(c, n, s, {efNoSemCheck}) + result = semGenericStmt(c, result, {}, ctx) else: n.sons[0] = symChoice(c, n.sons[0], s, scOption) result = n diff --git a/compiler/seminst.nim b/compiler/seminst.nim index b93d7ca157..b205eb09a4 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -33,7 +33,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable, localError(a.info, errCannotInstantiateX, s.name.s) t = errorType(c) elif t.kind == tyGenericParam: - internalError(a.info, "instantiateGenericParamList: " & q.name.s) + localError(a.info, errCannotInstantiateX, q.name.s) + t = errorType(c) elif t.kind == tyGenericInvokation: #t = instGenericContainer(c, a, t) t = generateTypeInstance(c, pt, a, t) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index f943e70061..d4aeba32ac 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -126,7 +126,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, result.typ = getSysType(tyString) of mInstantiationInfo: result = semInstantiationInfo(c, n) of mOrd: result = semOrd(c, n) - of mHigh: result = semLowHigh(c, n, mHigh) + of mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic) of mShallowCopy: result = semShallowCopy(c, n, flags) of mNBindSym: result = semBindSym(c, n) of mLocals: result = semLocals(c, n) diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim index c594a47883..7c489c3b6f 100644 --- a/compiler/semparallel.nim +++ b/compiler/semparallel.nim @@ -23,7 +23,7 @@ import ast, astalgo, idents, lowerings, magicsys, guards, sempass2, msgs, - renderer + renderer, types from trees import getMagic from strutils import `%` @@ -406,12 +406,17 @@ proc transformSpawn(owner: PSym; n, barrier: PNode): PNode = if result.isNil: result = newNodeI(nkStmtList, n.info) result.add n - result.add wrapProcForSpawn(owner, m, b.typ, barrier, it[0]) - it.sons[it.len-1] = emptyNode + let t = b[1][0].typ.sons[0] + if spawnResult(t, true) == srByVar: + result.add wrapProcForSpawn(owner, m, b.typ, barrier, it[0]) + it.sons[it.len-1] = emptyNode + else: + it.sons[it.len-1] = wrapProcForSpawn(owner, m, b.typ, barrier, nil) if result.isNil: result = n of nkAsgn, nkFastAsgn: let b = n[1] - if getMagic(b) == mSpawn: + if getMagic(b) == mSpawn and (let t = b[1][0].typ.sons[0]; + spawnResult(t, true) == srByVar): let m = transformSlices(b) return wrapProcForSpawn(owner, m, b.typ, barrier, n[0]) result = transformSpawnSons(owner, n, barrier) @@ -462,4 +467,3 @@ proc liftParallel*(owner: PSym; n: PNode): PNode = result.add callCodeGenProc("openBarrier", barrier) result.add transformSpawn(owner, body, barrier) result.add callCodeGenProc("closeBarrier", barrier) - diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index c8ce5e7875..da4adcf49d 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -115,7 +115,7 @@ proc useVar(a: PEffects, n: PNode) = a.addUse(copyNode(n)) if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and tfGcSafe notin s.typ.flags: - message(n.info, warnGcUnsafe, renderTree(n)) + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) a.gcUnsafe = true type @@ -315,7 +315,6 @@ proc documentRaises*(n: PNode) = if n.sons[namePos].kind != nkSym: return documentEffect(n, n.sons[pragmasPos], wRaises, exceptionEffects) documentEffect(n, n.sons[pragmasPos], wTags, tagEffects) - documentEffect(n, n.sons[pragmasPos], wUses, usesEffects) template notGcSafe(t): expr = {tfGcSafe, tfNoSideEffect} * t.flags == {} @@ -332,13 +331,9 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) = mergeTags(tracked, tagSpec, n) if notGcSafe(s.typ) and sfImportc notin s.flags: - message(n.info, warnGcUnsafe, renderTree(n)) + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true - when trackGlobals: - let usesSpec = effectSpec(pragma, wUses) - mergeUses(tracked, usesSpec, n) - proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = let n = n.skipConv if paramType != nil and tfNotNil in paramType.flags and @@ -358,7 +353,7 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = of impYes: discard proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) = - let op = n.typ + let op = skipConvAndClosure(n).typ if op != nil and op.kind == tyProc and n.kind != nkNilLit: internalAssert op.n.sons[0].kind == nkEffectList var effectList = op.n.sons[0] @@ -367,21 +362,24 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) = propagateEffects(tracked, n, s.sym) elif effectList.len == 0: if isForwardedProc(n): + # we have no explicit effects but it's a forward declaration and so it's + # stated there are no additional effects, so simply propagate them: propagateEffects(tracked, n, n.sym) else: + # we have no explicit effects so assume the worst: addEffect(tracked, createRaise(n)) addTag(tracked, createTag(n)) when trackGlobals: addUse(tracked, createAnyGlobal(n)) - # assume GcUnsafe unless in its type: - if notGcSafe(op): - message(n.info, warnGcUnsafe, renderTree(n)) + # assume GcUnsafe unless in its type; 'forward' does not matter: + if notGcSafe(op): + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true else: mergeEffects(tracked, effectList.sons[exceptionEffects], n) mergeTags(tracked, effectList.sons[tagEffects], n) when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n) if notGcSafe(op): - message(n.info, warnGcUnsafe, renderTree(n)) + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true notNilCheck(tracked, n, paramType) @@ -510,9 +508,6 @@ proc track(tracked: PEffects, n: PNode) = if op != nil and op.kind == tyProc and op.n.sons[0].kind == nkEffectList: if a.kind == nkSym and a.sym == tracked.owner: tracked.isRecursive = true - elif notGcSafe(op) and not importedFromC(a): - message(n.info, warnGcUnsafe, renderTree(n)) - tracked.gcUnsafe = true var effectList = op.n.sons[0] if a.kind == nkSym and a.sym.kind == skMethod: propagateEffects(tracked, n, a.sym) @@ -528,6 +523,11 @@ proc track(tracked: PEffects, n: PNode) = mergeEffects(tracked, effectList.sons[exceptionEffects], n) mergeTags(tracked, effectList.sons[tagEffects], n) when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n) + if notGcSafe(op) and not importedFromC(a): + # and it's not a recursive call: + if not (a.kind == nkSym and a.sym == tracked.owner): + message(n.info, warnGcUnsafe, renderTree(n)) + tracked.gcUnsafe = true for i in 1 .. 0 if we are in inlining context (copy vars) nestedProcs: int # > 0 if we are in a nested proc contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' - inLoop: int # > 0 if we are in a loop PTransf = ref TTransfContext proc newTransNode(a: PNode): PTransNode {.inline.} = @@ -201,6 +200,18 @@ proc newLabel(c: PTransf, n: PNode): PSym = result = newSym(skLabel, nil, getCurrOwner(c), n.info) result.name = getIdent(genPrefix & $result.id) +proc freshLabels(c: PTransf, n: PNode; symMap: var TIdTable) = + if n.kind in {nkBlockStmt, nkBlockExpr}: + if n.sons[0].kind == nkSym: + let x = newLabel(c, n[0]) + idTablePut(symMap, n[0].sym, x) + n.sons[0].sym = x + if n.kind == nkSym and n.sym.kind == skLabel: + let x = PSym(idTableGet(symMap, n.sym)) + if x != nil: n.sym = x + else: + for i in 0 .. 0 or n.sons[0].kind != nkEmpty: - result = n.PTransNode - else: - let labl = c.breakSyms[c.breakSyms.high] - result = transformSons(c, n) - result[0] = newSymNode(labl).PTransNode - proc transformLoopBody(c: PTransf, n: PNode): PTransNode = # What if it contains "continue" and "break"? "break" needs # an explicit label too, but not the same! @@ -239,6 +242,37 @@ proc transformLoopBody(c: PTransf, n: PNode): PTransNode = else: result = transform(c, n) +proc transformWhile(c: PTransf; n: PNode): PTransNode = + if c.inlining > 0: + result = transformSons(c, n) + else: + let labl = newLabel(c, n) + c.breakSyms.add(labl) + result = newTransNode(nkBlockStmt, n.info, 2) + result[0] = newSymNode(labl).PTransNode + + var body = newTransNode(n) + for i in 0..n.len-2: + body[i] = transform(c, n.sons[i]) + body[ 0: + result = n.PTransNode + when false: + let lablCopy = idNodeTableGet(c.transCon.mapping, n.sons[0].sym) + if lablCopy.isNil: + result = n.PTransNode + else: + result = newTransNode(n.kind, n.info, 1) + result[0] = lablCopy.PTransNode + else: + let labl = c.breakSyms[c.breakSyms.high] + result = transformSons(c, n) + result[0] = newSymNode(labl).PTransNode + proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) = # XXX: BUG: what if `n` is an expression with side-effects? for i in countup(0, sonsLen(c.transCon.forStmt) - 3): @@ -424,20 +458,32 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = var length = sonsLen(n) var call = n.sons[length - 2] + + let labl = newLabel(c, n) + c.breakSyms.add(labl) + result = newTransNode(nkBlockStmt, n.info, 2) + result[0] = newSymNode(labl).PTransNode + if call.typ.kind != tyIter and (call.kind notin nkCallKinds or call.sons[0].kind != nkSym or call.sons[0].sym.kind != skIterator): n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode - return lambdalifting.liftForLoop(n).PTransNode - #InternalError(call.info, "transformFor") + result[1] = lambdalifting.liftForLoop(n).PTransNode + discard c.breakSyms.pop + return result #echo "transforming: ", renderTree(n) - result = newTransNode(nkStmtList, n.info, 0) + var stmtList = newTransNode(nkStmtList, n.info, 0) + var loopBody = transformLoopBody(c, n.sons[length-1]) + + result[1] = stmtList + discard c.breakSyms.pop + var v = newNodeI(nkVarSection, n.info) for i in countup(0, length - 3): addVar(v, copyTree(n.sons[i])) # declare new vars - add(result, v.PTransNode) + add(stmtList, v.PTransNode) # Bugfix: inlined locals belong to the invoking routine, not to the invoked # iterator! @@ -453,27 +499,32 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = var formal = skipTypes(iter.typ, abstractInst).n.sons[i].sym if arg.typ.kind == tyIter: continue case putArgInto(arg, formal.typ) - of paDirectMapping: + of paDirectMapping: idNodeTablePut(newC.mapping, formal, arg) - of paFastAsgn: + of paFastAsgn: # generate a temporary and produce an assignment statement: var temp = newTemp(c, formal.typ, formal.info) addVar(v, newSymNode(temp)) - add(result, newAsgnStmt(c, newSymNode(temp), arg.PTransNode)) + add(stmtList, newAsgnStmt(c, newSymNode(temp), arg.PTransNode)) idNodeTablePut(newC.mapping, formal, newSymNode(temp)) of paVarAsgn: assert(skipTypes(formal.typ, abstractInst).kind == tyVar) idNodeTablePut(newC.mapping, formal, arg) # XXX BUG still not correct if the arg has a side effect! - var body = iter.getBody + var body = iter.getBody.copyTree pushInfoContext(n.info) + # XXX optimize this somehow. But the check "c.inlining" is not correct: + var symMap: TIdTable + initIdTable symMap + freshLabels(c, body, symMap) + inc(c.inlining) - add(result, transform(c, body)) - #findWrongOwners(c, result.pnode) + add(stmtList, transform(c, body)) + #findWrongOwners(c, stmtList.pnode) dec(c.inlining) popInfoContext() popTransCon(c) - # echo "transformed: ", result.PNode.renderTree + # echo "transformed: ", stmtList.PNode.renderTree proc getMagicOp(call: PNode): TMagic = if call.sons[0].kind == nkSym and @@ -643,25 +694,16 @@ proc transform(c: PTransf, n: PNode): PTransNode = if n.kind == nkMethodDef: methodDef(s, false) result = PTransNode(n) of nkForStmt: - inc c.inLoop result = transformFor(c, n) - dec c.inLoop of nkParForStmt: - inc c.inLoop result = transformSons(c, n) - dec c.inLoop of nkCaseStmt: result = transformCase(c, n) of nkContinueStmt: result = PTransNode(newNodeI(nkBreakStmt, n.info)) var labl = c.contSyms[c.contSyms.high] add(result, PTransNode(newSymNode(labl))) of nkBreakStmt: result = transformBreak(c, n) - of nkWhileStmt: - inc c.inLoop - result = newTransNode(n) - result[0] = transform(c, n.sons[0]) - result[1] = transformLoopBody(c, n.sons[1]) - dec c.inLoop + of nkWhileStmt: result = transformWhile(c, n) of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, nkCallStrLit: result = transformCall(c, n) @@ -740,6 +782,8 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode = # result = lambdalifting.liftIterator(prc, result) incl(result.flags, nfTransf) when useEffectSystem: trackProc(prc, result) + if prc.name.s == "testbody": + echo renderTree(result) proc transformStmt*(module: PSym, n: PNode): PNode = if nfTransf in n.flags: diff --git a/compiler/types.nim b/compiler/types.nim index 786eea14e7..c04413857d 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -99,7 +99,7 @@ proc isPureObject(typ: PType): bool = proc getOrdValue(n: PNode): BiggestInt = case n.kind - of nkCharLit..nkInt64Lit: result = n.intVal + of nkCharLit..nkUInt64Lit: result = n.intVal of nkNilLit: result = 0 of nkHiddenStdConv: result = getOrdValue(n.sons[1]) else: @@ -582,7 +582,10 @@ proc firstOrd(t: PType): BiggestInt = of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc, tyFieldAccessor: result = firstOrd(lastSon(t)) - else: + of tyOrdinal: + if t.len > 0: result = firstOrd(lastSon(t)) + else: internalError("invalid kind for first(" & $t.kind & ')') + else: internalError("invalid kind for first(" & $t.kind & ')') result = 0 @@ -617,7 +620,10 @@ proc lastOrd(t: PType): BiggestInt = tyTypeDesc, tyFieldAccessor: result = lastOrd(lastSon(t)) of tyProxy: result = 0 - else: + of tyOrdinal: + if t.len > 0: result = lastOrd(lastSon(t)) + else: internalError("invalid kind for last(" & $t.kind & ')') + else: internalError("invalid kind for last(" & $t.kind & ')') result = 0 @@ -907,9 +913,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = result = sameTypeAux(a.sons[0], b.sons[0], c) else: result = sameTypeAux(a.sons[0], b.sons[0], c) and sameFlags(a, b) - of tyEnum, tyForward, tyProxy: + of tyEnum, tyForward: # XXX generic enums do not make much sense, but require structural checking result = a.id == b.id and sameFlags(a, b) + of tyError: + result = b.kind == tyError of tyTuple: cycleCheck() result = sameTuple(a, b, c) and sameFlags(a, b) @@ -1363,3 +1371,35 @@ proc containsCompileTimeOnly*(t: PType): bool = if t.sons[i] != nil and isCompileTimeOnly(t.sons[i]): return true return false + +type + OrdinalType* = enum + NoneLike, IntLike, FloatLike + +proc classify*(t: PType): OrdinalType = + ## for convenient type checking: + if t == nil: + result = NoneLike + else: + case skipTypes(t, abstractVarRange).kind + of tyFloat..tyFloat128: result = FloatLike + of tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyChar, tyEnum: + result = IntLike + else: result = NoneLike + +proc skipConv*(n: PNode): PNode = + result = n + case n.kind + of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: + # only skip the conversion if it doesn't lose too important information + # (see bug #1334) + if n.sons[0].typ.classify == n.typ.classify: + result = n.sons[0] + of nkHiddenStdConv, nkHiddenSubConv, nkConv: + if n.sons[1].typ.classify == n.typ.classify: + result = n.sons[1] + else: discard + +proc skipConvTakeType*(n: PNode): PNode = + result = n.skipConv + result.typ = n.typ diff --git a/compiler/vm.nim b/compiler/vm.nim index 66595856ab..e40acca6ca 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -16,7 +16,7 @@ import ast except getstr import strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned, - parser, vmdeps, idents, trees, renderer, options, transf + parser, vmdeps, idents, trees, renderer, options, transf, parseutils from semfold import leValueConv, ordinalValToString from evaltempl import evalTemplate @@ -87,9 +87,7 @@ proc bailOut(c: PCtx; tos: PStackFrame) = when not defined(nimComputedGoto): {.pragma: computedGoto.} -proc myreset(n: var TFullReg) = - when defined(system.reset): - reset(n) +proc myreset(n: var TFullReg) = reset(n) template ensureKind(k: expr) {.immediate, dirty.} = if regs[ra].kind != k: @@ -776,6 +774,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = createStr regs[ra] regs[ra].node.strVal = substr(regs[rb].node.strVal, regs[rc].intVal.int, regs[rd].intVal.int) + of opcParseFloat: + decodeBC(rkInt) + inc pc + assert c.code[pc].opcode == opcParseFloat + let rd = c.code[pc].regA + var rcAddr = addr(regs[rc]) + if rcAddr.kind == rkRegisterAddr: rcAddr = rcAddr.regAddr + elif regs[rc].kind != rkFloat: + myreset(regs[rc]) + regs[rc].kind = rkFloat + regs[ra].intVal = parseBiggestFloat(regs[rb].node.strVal, + rcAddr.floatVal, regs[rd].intVal.int) of opcRangeChck: let rb = instr.regB let rc = instr.regC @@ -1068,6 +1078,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcNKind: decodeB(rkInt) regs[ra].intVal = ord(regs[rb].node.kind) + c.comesFromHeuristic = regs[rb].node.info of opcNIntVal: decodeB(rkInt) let a = regs[rb].node @@ -1243,8 +1254,16 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = internalError(c.debug[pc], "request to create a NimNode of invalid kind") let cc = regs[rc].node + regs[ra].node = newNodeI(TNodeKind(int(k)), - if cc.kind == nkNilLit: c.debug[pc] else: cc.info) + if cc.kind != nkNilLit: + cc.info + elif c.comesFromHeuristic.line > -1: + c.comesFromHeuristic + elif c.callsite != nil and c.callsite.safeLen > 1: + c.callsite[1].info + else: + c.debug[pc]) regs[ra].node.flags.incl nfIsRef of opcNCopyNimNode: decodeB(rkNode) diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index c391d8415f..cad48abeae 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -66,7 +66,7 @@ type opcMulSet, opcPlusSet, opcMinusSet, opcSymdiffSet, opcConcatStr, opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq, opcSwap, opcIsNil, opcOf, opcIs, - opcSubStr, opcConv, opcCast, opcQuit, opcReset, + opcSubStr, opcParseFloat, opcConv, opcCast, opcQuit, opcReset, opcNarrowS, opcNarrowU, opcAddStrCh, @@ -188,6 +188,7 @@ type features*: TSandboxFlags traceActive*: bool loopIterations*: int + comesFromHeuristic*: TLineInfo # Heuristic for better macro stack traces TPosition* = distinct int @@ -196,7 +197,8 @@ type proc newCtx*(module: PSym): PCtx = PCtx(code: @[], debug: @[], globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], - prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations) + prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations, + comesFromHeuristic: unknownLineInfo()) proc refresh*(c: PCtx, module: PSym) = c.module = module diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 9a213d8133..fdd8276cc3 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -12,11 +12,11 @@ import ast, types, msgs, osproc, streams, options proc readOutput(p: PProcess): string = result = "" var output = p.outputStream - discard p.waitForExit while not output.atEnd: result.add(output.readLine) result.add("\n") result.setLen(result.len - "\n".len) + discard p.waitForExit proc opGorge*(cmd, input: string): string = var p = startCmd(cmd) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index c1ec637ddb..a4ddc2e15f 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -43,18 +43,19 @@ type proc debugInfo(info: TLineInfo): string = result = info.toFilename.splitFile.name & ":" & $info.line -proc codeListing(c: PCtx, result: var string, start=0) = +proc codeListing(c: PCtx, result: var string, start=0; last = -1) = # first iteration: compute all necessary labels: var jumpTargets = initIntSet() - for i in start.. < c.code.len: + let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1) + for i in start..last: let x = c.code[i] if x.opcode in relativeJumps: jumpTargets.incl(i+x.regBx-wordExcess) # for debugging purposes var i = start - while i < c.code.len: + while i <= last: if i in jumpTargets: result.addf("L$1:\n", i) let x = c.code[i] @@ -82,9 +83,9 @@ proc codeListing(c: PCtx, result: var string, start=0) = result.add("\n") inc i -proc echoCode*(c: PCtx, start=0) {.deprecated.} = +proc echoCode*(c: PCtx, start=0; last = -1) {.deprecated.} = var buf = "" - codeListing(c, buf, start) + codeListing(c, buf, start, last) echo buf proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) = @@ -495,6 +496,7 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) = c.freeTempRange(x, n.len) template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar +proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym) proc needsAsgnPatch(n: PNode): bool = n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr, @@ -637,8 +639,10 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) = c.freeTemp(tmp) proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) = + var x = n.sons[1] + if x.kind in {nkAddr, nkHiddenAddr}: x = x.sons[0] let - dest = c.genx(n.sons[1], {gfAddrOf}) + dest = c.genx(x) tmp = c.genx(n.sons[2]) c.gABC(n, opc, dest, tmp, 0) #c.genAsgnPatch(n.sons[1], dest) @@ -852,6 +856,24 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = c.freeTemp(tmp1) c.freeTemp(tmp2) c.freeTemp(tmp3) + of mParseBiggestFloat: + if dest < 0: dest = c.getTemp(n.typ) + var d2: TRegister + # skip 'nkHiddenAddr': + let d2AsNode = n.sons[2].sons[0] + if needsAsgnPatch(d2AsNode): + d2 = c.getTemp(getSysType(tyFloat)) + else: + d2 = c.genx(d2AsNode) + var + tmp1 = c.genx(n.sons[1]) + tmp3 = c.genx(n.sons[3]) + c.gABC(n, opcParseFloat, dest, tmp1, d2) + c.gABC(n, opcParseFloat, tmp3) + c.freeTemp(tmp1) + c.freeTemp(tmp3) + c.genAsgnPatch(d2AsNode, d2) + c.freeTemp(d2) of mReset: unused(n, dest) var d = c.genx(n.sons[1]) @@ -1035,6 +1057,8 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; # nkAddr we must not use 'unneededIndirection', but for deref we use it. if not isAddr and unneededIndirection(n.sons[0]): gen(c, n.sons[0], dest, newflags) + elif isAddr and isGlobal(n.sons[0]): + gen(c, n.sons[0], dest, flags+{gfAddrOf}) else: let tmp = c.genx(n.sons[0], newflags) if dest < 0: dest = c.getTemp(n.typ) @@ -1075,6 +1099,8 @@ proc setSlot(c: PCtx; v: PSym) = # XXX generate type initialization here? if v.position == 0: if c.prc.maxSlots == 0: c.prc.maxSlots = 1 + if c.prc.maxSlots >= high(TRegister): + internalError(v.info, "cannot generate code; too many registers required") v.position = c.prc.maxSlots c.prc.slots[v.position] = (inUse: true, kind: if v.kind == skLet: slotFixedLet else: slotFixedVar) @@ -1098,10 +1124,9 @@ proc checkCanEval(c: PCtx; n: PNode) = # we need to ensure that we don't evaluate 'x' here: # proc foo() = var x ... let s = n.sym - if s.position == 0: - if s.kind in {skVar, skTemp, skLet, skParam, skResult} and - not s.isOwnedBy(c.prc.sym) and s.owner != c.module: - cannotEval(n) + if s.kind in {skVar, skTemp, skLet, skParam, skResult} and + not s.isOwnedBy(c.prc.sym) and s.owner != c.module: + cannotEval(n) proc isTemp(c: PCtx; dest: TDest): bool = result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown @@ -1228,6 +1253,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = c.gABx(n, opcLdGlobal, cc, s.position) c.gABC(n, opcNodeToReg, dest, cc) c.freeTemp(cc) + elif gfAddrOf in flags: + c.gABx(n, opcLdGlobalAddr, dest, s.position) else: c.gABx(n, opcLdGlobal, dest, s.position) else: diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index fbe0050313..d810319177 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -27,7 +27,7 @@ type wContinue, wConverter, wDiscard, wDistinct, wDiv, wDo, wElif, wElse, wEnd, wEnum, wExcept, wExport, wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn, - wInclude, wInterface, wIs, wIsnot, wIterator, wLambda, wLet, + wInclude, wInterface, wIs, wIsnot, wIterator, wLet, wMacro, wMethod, wMixin, wMod, wNil, wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, @@ -39,7 +39,7 @@ type wDestroy, - wImmediate, wDestructor, wDelegator, + wImmediate, wDestructor, wDelegator, wOverride, wImportCpp, wImportObjC, wImportCompilerProc, wImportc, wExportc, wIncompleteStruct, wRequiresInit, @@ -64,7 +64,7 @@ type wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt, wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wAsmNoStackFrame, - wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wUses, + wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, wAuto, wBool, wCatch, wChar, wClass, wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast, @@ -107,7 +107,7 @@ const "elif", "else", "end", "enum", "except", "export", "finally", "for", "from", "generic", "if", "import", "in", "include", "interface", "is", "isnot", "iterator", - "lambda", "let", + "let", "macro", "method", "mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc", "ptr", "raise", "ref", "return", @@ -122,7 +122,7 @@ const "destroy", - "immediate", "destructor", "delegator", + "immediate", "destructor", "delegator", "override", "importcpp", "importobjc", "importcompilerproc", "importc", "exportc", "incompletestruct", "requiresinit", "align", "nodecl", "pure", "sideeffect", @@ -147,7 +147,7 @@ const "computedgoto", "injectstmt", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", - "guard", "uses", + "guard", "locks", "auto", "bool", "catch", "char", "class", "const_cast", "default", "delete", "double", diff --git a/config/nim.cfg b/config/nim.cfg new file mode 100644 index 0000000000..df3835ace7 --- /dev/null +++ b/config/nim.cfg @@ -0,0 +1,139 @@ +# Configuration file for the Nimrod Compiler. +# (c) 2013 Andreas Rumpf + +# Feel free to edit the default values as you need. + +# You may set environment variables with +# @putenv "key" "val" +# Environment variables cannot be used in the options, however! + +cc = gcc + +# example of how to setup a cross-compiler: +arm.linux.gcc.exe = "arm-linux-gcc" +arm.linux.gcc.linkerexe = "arm-linux-gcc" + +path="$lib/core" +path="$lib/pure" +path="$lib/pure/collections" +path="$lib/pure/concurrency" +path="$lib/impure" +path="$lib/wrappers" +# path="$lib/wrappers/cairo" +# path="$lib/wrappers/gtk" +# path="$lib/wrappers/lua" +# path="$lib/wrappers/opengl" +path="$lib/wrappers/pcre" +path="$lib/wrappers/readline" +path="$lib/wrappers/sdl" +# path="$lib/wrappers/x11" +path="$lib/wrappers/zip" +path="$lib/wrappers/libffi" +path="$lib/windows" +path="$lib/posix" +path="$lib/js" +path="$lib/pure/unidecode" + +@if nimbabel: + babelpath="$home/.babel/pkgs/" +@end + +@if release or quick: + obj_checks:off + field_checks:off + range_checks:off + bound_checks:off + overflow_checks:off + assertions:off + stacktrace:off + linetrace:off + debugger:off + line_dir:off + dead_code_elim:on +@end + +@if release: + opt:speed +@end + +# additional options always passed to the compiler: +--parallel_build: "0" # 0 to auto-detect number of processors + +hint[LineTooLong]=off +#hint[XDeclaredButNotUsed]=off + +@if unix: + @if not bsd: + # -fopenmp + gcc.options.linker = "-ldl" + gpp.options.linker = "-ldl" + clang.options.linker = "-ldl" + tcc.options.linker = "-ldl" + @end + @if bsd or haiku: + # BSD got posix_spawn only recently, so we deactivate it for osproc: + define:useFork + # at least NetBSD has problems with thread local storage: + tlsEmulation:on + @end +@end + +# Configuration for the Intel C/C++ compiler: +@if windows: + icl.options.speed = "/Ox /arch:SSE2" + icl.options.always = "/nologo" +@end + +# Configuration for the GNU C/C++ compiler: +@if windows: + #gcc.path = r"$nimrod\dist\mingw\bin" + @if gcc: + tlsEmulation:on + @end +@end + +@if macosx: + cc = clang + tlsEmulation:on + gcc.options.always = "-w -fasm-blocks" + gpp.options.always = "-w -fasm-blocks -fpermissive" +@else: + gcc.options.always = "-w" + gpp.options.always = "-w -fpermissive" +@end + +gcc.options.speed = "-O3 -fno-strict-aliasing" +gcc.options.size = "-Os" +gcc.options.debug = "-g3 -O0" + +gpp.options.speed = "-O3 -fno-strict-aliasing" +gpp.options.size = "-Os" +gpp.options.debug = "-g3 -O0" +#passl = "-pg" + +# Configuration for the LLVM GCC compiler: +llvm_gcc.options.debug = "-g" +llvm_gcc.options.always = "-w" +llvm_gcc.options.speed = "-O2" +llvm_gcc.options.size = "-Os" + +# Configuration for the LLVM CLang compiler: +clang.options.debug = "-g" +clang.options.always = "-w" +clang.options.speed = "-O3" +clang.options.size = "-Os" + +# Configuration for the Visual C/C++ compiler: +vcc.options.linker = "/DEBUG /Zi /Fd\"$projectName.pdb\" /F33554432" # set the stack size to 8 MB +vcc.options.debug = "/Zi /Fd\"$projectName.pdb\"" +vcc.options.always = "/nologo" +vcc.options.speed = "/Ox /arch:SSE2" +vcc.options.size = "/O1" + +# Configuration for the Digital Mars C/C++ compiler: +@if windows: + dmc.path = r"$nimrod\dist\dm\bin" +@end + +# Configuration for the Tiny C Compiler: +tcc.options.always = "-w" diff --git a/config/nimrod.cfg b/config/nimrod.cfg index df3835ace7..075b65d631 100644 --- a/config/nimrod.cfg +++ b/config/nimrod.cfg @@ -130,10 +130,5 @@ vcc.options.always = "/nologo" vcc.options.speed = "/Ox /arch:SSE2" vcc.options.size = "/O1" -# Configuration for the Digital Mars C/C++ compiler: -@if windows: - dmc.path = r"$nimrod\dist\dm\bin" -@end - # Configuration for the Tiny C Compiler: tcc.options.always = "-w" diff --git a/copying.txt b/copying.txt index 4041ca0272..254b91c774 100644 --- a/copying.txt +++ b/copying.txt @@ -1,7 +1,7 @@ -=============================================================================== -Nimrod -- a Compiler for Nimrod. http://nimrod-code.org/ - -Copyright (C) 2004-2014 Andreas Rumpf. All rights reserved. +===================================================== +Nimrod -- a Compiler for Nimrod. http://nimrod-lang.org/ + +Copyright (C) 2006-2014 Andreas Rumpf. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/doc/advopt.txt b/doc/advopt.txt index 08465e4572..7a11e90419 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -12,6 +12,7 @@ Advanced commands: module dependency graph //dump dump all defined conditionals and search paths //check checks the project for syntax and semantic + //pretty homogenizes source code style //idetools compiler support for IDEs: possible options: --track:FILE,LINE,COL track a file/cursor position --trackDirty:DIRTY_FILE,ORIG_FILE,LINE,COL diff --git a/doc/backends.txt b/doc/backends.txt index 26576e7331..c2dbb0af66 100644 --- a/doc/backends.txt +++ b/doc/backends.txt @@ -322,6 +322,64 @@ earlier, JavaScript doesn't require an initialisation call to ``NimMain`` or similar function and you can call the exported Nimrod proc directly. +Nimcache naming logic +--------------------- + +The `nimcache`:idx: directory is generated during compilation and will hold +either temporary or final files depending on your backend target. The default +name for the directory is ``nimcache`` but you can use the ``--nimcache`` +`compiler switch `_ to change it. + +Nimcache and C like targets +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The C like backends will place their temporary ``.c``, ``.cpp`` or ``.m`` files +in the ``nimcache`` directory. The naming of these files follows the pattern +``babelPackageName_`` + ``nimrodSource``: + +* Filenames for modules imported from `Babel packages + `_ will end up with + ``babelPackageName_module.c``. For example, if you import the + ``argument_parser`` module from the same name Babel package you + will end up with a ``argument_parser_argument_parser.c`` file + under ``nimcache``. The name of the Babel package comes from the + ``proj.babel`` file, the actual contents are not read by the + compiler. + +* Filenames for non babel packages (like your project) will be + renamed from ``.nim`` to have the extension of your target backend + (from now on ``.c`` for these examples), but otherwise nothing + else will change. This will quickly break if your project consists + of a main ``proj.nim`` file which includes a ``utils/proj.nim`` + file: both ``proj.nim`` files will generate the same name ``proj.c`` + output in the ``nimcache`` directory overwriting themselves! + +* Filenames for modules found in the standard library will be named + ``stdlib_module.c``. Unless you are doing something special, you + will end up with at least ``stdlib_system.c``, since the `system + module `_ is always imported automatically. Same for + the `hashes module `_ which will be named + ``stdlib_hashes.c``. The ``stdlib_`` prefix comes from the *fake* + ``lib/stdlib.babel`` file. + +To find the name of a Babel package the compiler searches for a ``*.babel`` +file in the parent directory hierarchy of whatever module you are compiling. +Even if you are in a subdirectory of your project, a parent ``*.babel`` file +will influence the naming of the nimcache name. This means that on Unix systems +creating the file ``~/foo.babel`` will automatically prefix all nimcache files +not part of another package with the string ``foo_``. + + +Nimcache and the Javascript target +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unless you explicitly use the ``-o:filename.js`` switch as mentioned in the +previous examples, the compiler will create a ``filename.js`` file in the +``nimcache`` directory using the name of your input nimrod file. There are no +other temporary files generated, the output is always a single self contained +``.js`` file. + + Memory management ================= diff --git a/doc/basicopt.txt b/doc/basicopt.txt index 3a29b78298..3906238280 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -13,6 +13,7 @@ Options: -p, --path:PATH add path to search paths -d, --define:SYMBOL define a conditional symbol -u, --undef:SYMBOL undefine a conditional symbol + --symbol:SYMBOL declare a conditional symbol -f, --forceBuild force rebuilding of all modules --stackTrace:on|off turn stack tracing on|off --lineTrace:on|off turn line tracing on|off @@ -34,3 +35,5 @@ Options: -r, --run run the compiled program with given arguments --advanced show advanced command line switches -h, --help show this help + +Note: Even single letter options require the colon: -p:PATH. diff --git a/doc/c2nim.txt b/doc/c2nim.txt deleted file mode 100644 index 237af7fb22..0000000000 --- a/doc/c2nim.txt +++ /dev/null @@ -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 ``) 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... - diff --git a/doc/exception_hierarchy_fragment.txt b/doc/exception_hierarchy_fragment.txt new file mode 100644 index 0000000000..6ca68921f1 --- /dev/null +++ b/doc/exception_hierarchy_fragment.txt @@ -0,0 +1,31 @@ +* `E_Base `_ + * `EAccessViolation `_ + * `EArithmetic `_ + * `EDivByZero `_ + * `EOverflow `_ + * `EAssertionFailed `_ + * `EAsynch `_ + * `EControlC `_ + * `EDeadThread `_ + * `EFloatingPoint `_ + * `EFloatDivByZero `_ + * `EFloatInexact `_ + * `EFloatInvalidOp `_ + * `EFloatOverflow `_ + * `EFloatUnderflow `_ + * `EInvalidField `_ + * `EInvalidIndex `_ + * `EInvalidObjectAssignment `_ + * `EInvalidObjectConversion `_ + * `EInvalidValue `_ + * `EInvalidKey `_ + * `ENoExceptionToReraise `_ + * `EOutOfRange `_ + * `ESynch `_ + * `EOutOfMemory `_ + * `EResourceExhausted `_ + * `EStackOverflow `_ + * `ESystem `_ + * `EIO `_ + * `EOS `_ + * `EInvalidLibrary `_ diff --git a/doc/keywords.txt b/doc/keywords.txt index 60b1003980..a43b35475b 100644 --- a/doc/keywords.txt +++ b/doc/keywords.txt @@ -6,7 +6,7 @@ elif else end enum except export finally for from generic if import in include interface is isnot iterator -lambda let +let macro method mixin mod nil not notin object of or out diff --git a/doc/koch.txt b/doc/koch.txt index 0321518081..7be2be6d46 100644 --- a/doc/koch.txt +++ b/doc/koch.txt @@ -138,6 +138,13 @@ from rst to HTML. It also repeats the same operation but places the result in the ``web/upload`` which can be used to update the website at http://nimrod-lang.org. +By default the documentation will be built in parallel using the number of +available CPU cores. If any documentation build sub commands fail, they will +be rerun in serial fashion so that meaninful error output can be gathered for +inspection. The ``--parallelBuild:n`` switch or configuration option can be +used to force a specific number of parallel jobs or run everything serially +from the start (``n == 1``). + zip command ----------- diff --git a/doc/lib.txt b/doc/lib.txt index 2da753007b..26ea1b7350 100644 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -56,7 +56,10 @@ Core * `typeinfo `_ Provides (unsafe) access to Nimrod's run time type information. - + +* `typetraits `_ + This module defines compile-time reflection procs for working with types. + * `actors `_ Actor support for Nimrod; implemented as a layer on top of the threads and channels modules. @@ -447,10 +450,6 @@ Other This module contains code for reading from `stdin`:idx:. On UNIX the GNU readline library is wrapped and set up. -* `zmq `_ - Nimrod 0mq wrapper. This file contains the low level C wrappers as well as - some higher level constructs. - Wrappers ======== @@ -463,8 +462,6 @@ Windows specific * `windows `_ Contains a wrapper for the Win32 API. -* `ole2 `_ - Contains GUIDs for OLE2 automation support. * `shellapi `_ Contains a wrapper for the ``shellapi.h`` header. * `shfolder `_ @@ -594,7 +591,8 @@ compiler. .. raw:: html -
+
If you are reading this you are missing + babelpkglist.js or have javascript disabled in your browser.
Unofficial packages ------------------- @@ -605,7 +603,8 @@ Nimrod programming language. .. raw:: html -
+
If you are reading this you are missing + babelpkglist.js or have javascript disabled in your browser.
diff --git a/doc/manual.txt b/doc/manual.txt index 32b0541e9e..c150d27e22 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -1221,38 +1221,8 @@ branch switch ``system.reset`` has to be used. Set type -------- -The set type models the mathematical notion of a set. The set's -basetype can only be an ordinal type. The reason is that sets are implemented -as high performance bit vectors. - -Sets can be constructed via the set constructor: ``{}`` is the empty set. The -empty set is type compatible with any special set type. The constructor -can also be used to include elements (and ranges of elements) in the set: - -.. code-block:: nimrod - - {'a'..'z', '0'..'9'} # This constructs a set that contains the - # letters from 'a' to 'z' and the digits - # from '0' to '9' - -These operations are supported by sets: - -================== ======================================================== -operation meaning -================== ======================================================== -``A + B`` union of two sets -``A * B`` intersection of two sets -``A - B`` difference of two sets (A without B's elements) -``A == B`` set equality -``A <= B`` subset relation (A is subset of B or equal to B) -``A < B`` strong subset relation (A is a real subset of B) -``e in A`` set membership (A contains element e) -``A -+- B`` symmetric set difference (= (A - B) + (B - A)) -``card(A)`` the cardinality of A (number of elements in A) -``incl(A, elem)`` same as A = A + {elem} -``excl(A, elem)`` same as A = A - {elem} -================== ======================================================== +.. include:: sets_fragment.txt Reference and pointer types --------------------------- @@ -1451,7 +1421,7 @@ Examples: proc forEach(c: proc (x: int) {.cdecl.}) = ... - forEach(printItem) # this will NOT work because calling conventions differ + forEach(printItem) # this will NOT compile because calling conventions differ .. code-block:: nimrod @@ -2497,7 +2467,7 @@ variable to use: When the compiler reaches the second ``add`` call, both ``a`` and ``b`` could be used with the proc, so one gets ``Error: expression '(a|b)' has no type (or -is ambiguous)``. To solve this you would need to nest ``using`` with a +is ambiguous)``. To solve this one would need to nest ``using`` with a ``block`` statement so as to control the reach of the ``using`` statement. If expression @@ -4347,7 +4317,7 @@ Nimrod offers a special family of dot operators that can be used to intercept and rewrite proc call and field access attempts, referring to previously undeclared symbol names. They can be used to provide a fluent interface to objects lying outside the static confines of the -Nimrod's type system such as values from dynamic scripting languages +type system such as values from dynamic scripting languages or dynamic file formats such as JSON or XML. When Nimrod encounters an expression that cannot be resolved by the @@ -4379,8 +4349,8 @@ This operator will be matched against both field accesses and method calls. operator `.()` --------------- This operator will be matched exclusively against method calls. It has higher -precedence than the `.` operator and this allows you to handle expressions like -`x.y` and `x.y()` differently if you are interfacing with a scripting language +precedence than the `.` operator and this allows one to handle expressions like +`x.y` and `x.y()` differently if one is interfacing with a scripting language for example. operator `.=` @@ -4391,6 +4361,117 @@ This operator will be matched against assignments to missing fields. a.b = c # becomes `.=`(a, "b", c) +Type bound operations +===================== + +There are 3 operations that are bound to a type: + +1. Assignment +2. Destruction +3. Deep copying for communication between threads + +These operations can be *overriden* instead of *overloaded*. This means the +implementation is automatically lifted to structured types. For instance if type +``T`` has an overriden assignment operator ``=`` this operator is also used +for assignments of the type ``seq[T]``. Since these operations are bound to a +type they have to be bound to a nominal type for reasons of simplicity of +implementation: This means an overriden ``deepCopy`` for ``ref T`` is really +bound to ``T`` and not to ``ref T``. This also means that one cannot override +``deepCopy`` for both ``ptr T`` and ``ref T`` at the same time; instead a +helper distinct or object type has to be used for one pointer type. + + +operator `=` +------------ + +**Note**: Overriding the assignment operator has not yet been implemented. + +This operator is the assignment operator. Note that in the contexts +like ``let v = expr``, ``var v = expr``, ``parameter = defaultValue`` or for +parameter passing no assignment is performed. The ``override`` pragma is +optional for overriding ``=``. + + +destructors +----------- + +A destructor must have a single parameter with a concrete type (the name of a +generic type is allowed too). The name of the destructor has to be ``destroy`` +and it need to be annotated with the ``override`` pragma. + +``destroy(v)`` will be automatically invoked for every local stack +variable ``v`` that goes out of scope. + +If a structured type features a field with destructable type and +the user has not provided an explicit implementation, a destructor for the +structured type will be automatically generated. Calls to any base class +destructors in both user-defined and generated destructors will be inserted. + +A destructor is attached to the type it destructs; expressions of this type +can then only be used in *destructible contexts* and as parameters: + +.. code-block:: nimrod + type + TMyObj = object + x, y: int + p: pointer + + proc destroy(o: var TMyObj) {.override.} = + if o.p != nil: dealloc o.p + + proc open: TMyObj = + result = TMyObj(x: 1, y: 2, p: alloc(3)) + + proc work(o: TMyObj) = + echo o.x + # No destructor invoked here for 'o' as 'o' is a parameter. + + proc main() = + # destructor automatically invoked at the end of the scope: + var x = open() + # valid: pass 'x' to some other proc: + work(x) + + # Error: usage of a type with a destructor in a non destructible context + echo open() + +A destructible context is currently only the following: + +1. The ``expr`` in ``var x = expr``. +2. The ``expr`` in ``let x = expr``. +3. The ``expr`` in ``return expr``. +4. The ``expr`` in ``result = expr`` where ``result`` is the special symbol + introduced by the compiler. + +These rules ensure that the construction is tied to a variable and can easily +be destructed at its scope exit. Later versions of the language will improve +the support of destructors. + +Be aware that destructors are not called for objects allocated with ``new``. +This may change in future versions of language, but for now the ``finalizer`` +parameter to ``new`` has to be used. + + +deepCopy +-------- + +``deepCopy`` is a builtin that is invoked whenever data is passed to +a ``spawn``'ed proc to ensure memory safety. The programmer can override its +behaviour for a specific ``ref`` or ``ptr`` type ``T``. (Later versions of the +language may weaken this restriction.) + +The signature has to be: + +.. code-block:: nimrod + proc deepCopy(x: T): T {.override.} + +This mechanism is used by most data structures that support shared memory like +channels to implement thread safe automatic memory management. + +The builtin ``deepCopy`` can even clone closures and their environments. See +the documentation of `spawn`_ for details. + + Term rewriting macros ===================== @@ -4960,6 +5041,27 @@ first implementation to play with a language feature before a nicer syntax to access the feature becomes available. +deprecated pragma +----------------- + +The deprecated pragma is used to mark a symbol as deprecated: + +.. code-block:: nimrod + proc p() {.deprecated.} + var x {.deprecated.}: char + +It can also be used as a statement. Then it takes a list of *renamings*. The +upcoming ``nimfix`` tool can automatically update the code and perform these +renamings: + +.. code-block:: nimrod + type + File = object + Stream = ref object + {.deprecated: [TFile: File, PStream: Stream].} + + + noSideEffect pragma ------------------- The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side @@ -4970,9 +5072,9 @@ or ``ref T`` or ``ptr T`` this means no locations are modified. It is a static error to mark a proc/iterator to have no side effect if the compiler cannot verify this. -As a special semantic rule, the built-in ``debugEcho`` pretends to be free of -side effects, so that it can be used for debugging routines marked as -``noSideEffect``. +As a special semantic rule, the built-in `debugEcho `_ +pretends to be free of side effects, so that it can be used for debugging +routines marked as ``noSideEffect``. **Future directions**: ``func`` may become a keyword and syntactic sugar for a proc with no side effects: @@ -4985,62 +5087,14 @@ destructor pragma ----------------- The ``destructor`` pragma is used to mark a proc to act as a type destructor. -The proc must have a single parameter with a concrete type (the name of a -generic type is allowed too). +Its usage is deprecated, use the ``override`` pragma instead. +See `type bound operations`_. -Destructors will be automatically invoked when a local stack variable goes -out of scope. -If a record type features a field with destructable type and -the user have not provided explicit implementation, Nimrod will automatically -generate a destructor for the record type. Nimrod will automatically insert -calls to any base class destructors in both user-defined and generated -destructors. - -A destructor is attached to the type it destructs; expressions of this type -can then only be used in *destructible contexts* and as parameters: - -.. code-block:: nimrod - type - TMyObj = object - x, y: int - p: pointer - - proc destruct(o: var TMyObj) {.destructor.} = - if o.p != nil: dealloc o.p - - proc open: TMyObj = - result = TMyObj(x: 1, y: 2, p: alloc(3)) - - proc work(o: TMyObj) = - echo o.x - # No destructor invoked here for 'o' as 'o' is a parameter. - - proc main() = - # destructor automatically invoked at the end of the scope: - var x = open() - # valid: pass 'x' to some other proc: - work(x) - - # Error: usage of a type with a destructor in a non destructible context - echo open() - -A destructible context is currently only the following: - -1. The ``expr`` in ``var x = expr``. -2. The ``expr`` in ``let x = expr``. -3. The ``expr`` in ``return expr``. -4. The ``expr`` in ``result = expr`` where ``result`` is the special symbol - introduced by the compiler. - -These rules ensure that the construction is tied to a variable and can easily -be destructed at its scope exit. Later versions of the language will improve -the support of destructors. - -Be aware that destructors are not called for objects allocated with ``new``. -This may change in future versions of language, but for now use -the ``finalizer`` parameter to ``new``. +override pragma +--------------- +See `type bound operations`_ instead. procvar pragma -------------- @@ -5290,7 +5344,7 @@ See `Ordinary vs immediate templates`_. compilation option pragmas -------------------------- The listed pragmas here can be used to override the code generation options -for a section of code. +for a proc/method/converter. The implementation currently provides the following possible options (various others may be added later). @@ -5490,10 +5544,10 @@ spelled*: proc printf(formatstr: cstring) {.header: "", importc: "printf", varargs.} Note that this pragma is somewhat of a misnomer: Other backends will provide -the same feature under the same name. Also, if you are interfacing with C++ -you can use the `ImportCpp pragma `_ and +the same feature under the same name. Also, if one is interfacing with C++ +the `ImportCpp pragma `_ and interfacing with Objective-C the `ImportObjC pragma -`_. +`_ can be used. Exportc pragma @@ -5781,12 +5835,14 @@ used instead. `spawn`:idx: is used to pass a task to the thread pool: Currently the expression that ``spawn`` takes is however quite restricted: -* It must be a call expresion ``f(a, ...)``. +* It must be a call expression ``f(a, ...)``. * ``f`` must be ``gcsafe``. * ``f`` must not have the calling convention ``closure``. -* ``f``'s parameters may not be of type ``var`` nor may they contain ``ref``. - This means you have to use raw ``ptr``'s for data passing reminding the +* ``f``'s parameters may not be of type ``var``. + This means one has to use raw ``ptr``'s for data passing reminding the programmer to be careful. +* ``ref`` parameters are deeply copied which is a subtle semantic change and + can cause performance problems but ensures memory safety. * For *safe* data exchange between ``f`` and the caller a global ``TChannel`` needs to be used. Other means will be provided soon. diff --git a/doc/nimdoc.css b/doc/nimdoc.css index 6154f0b2eb..e3bab07de3 100644 --- a/doc/nimdoc.css +++ b/doc/nimdoc.css @@ -16,6 +16,11 @@ customize this style sheet. Andreas Rumpf */ +body { + color: black; + background: white; +} + /* used to remove borders from tables and images */ .borderless, table.borderless td, table.borderless th { border: 0 } diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 428c42f39d..016f0ed50c 100644 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -152,10 +152,12 @@ the first matching file is used. Generated C code directory -------------------------- -The generated files that Nimrod produces all go into a subdirectory called -``nimcache`` in your project directory. This makes it easy to delete all -generated files. - +The generated files that Nimrod produces all go into a subdirectory called +``nimcache`` in your project directory. This makes it easy to delete all +generated files. Files generated in this directory follow a naming logic which +you can read about in the `Nimrod Backend Integration document +`_. + However, the generated C code is not platform independent. C code generated for Linux does not compile on Windows, for instance. The comment on top of the C file lists the OS, CPU and CC the file has been compiled for. @@ -540,6 +542,58 @@ in C/C++). **Note**: This pragma will not exist for the LLVM backend. +Source code style +================= + +Nimrod allows you to `mix freely case and underscores as identifier separators +`_, so variables named ``MyPrecioussInt`` and +``my_preciouss_int`` are equivalent: + +.. code-block:: Nimrod + var MyPrecioussInt = 3 + # Following line compiles fine! + echo my_preciouss_int + +Since this can lead to many variants of the same source code (you can use +`nimgrep `_ instead of your typical ``grep`` to ignore style +problems) the compiler provides the command ``pretty`` to help unifying the +style of source code. Running ``nimrod pretty ugly_test.nim`` with this +example will generate a secondary file named ``ugly_test.pretty.nim`` with the +following content: + +.. code-block:: Nimrod + var MyPrecioussInt = 3 + # Following line compiles fine! + echo MyPrecioussInt + +During execution the ``pretty`` command will also run on Nimrod's standard +library, since it doesn't differentiate the standard library as something +special, and hence will warn of many *errors* which are out of your hand to +fix, creating respective ``.pretty.nim`` files all the way. You can ignore +these errors if they don't belong to your source and simply compare your +original version to the new pretty one. In fact, running ``pretty`` on our test +file will show the following:: + + Hint: ugly_test [Processing] + ugly_test.nim(1, 4) Error: name should be: myPrecioussInt + ugly_test.nim(1, 4) Error: name should be: myPrecioussInt + +At the moment ``pretty`` will homogenize the style of symbols but will leave +important changes for you to review. In this case the command is warning that a +variable name should not start with a capital letter, which is usually reserved +to `object types `_. To learn about the accepted `camel case +style `_ read `Coding Guidelines in +the Internals of Nimrod Compiler `_ or `Coding +Guidelines `_ and `NEP 1 +: Style Guide for Nimrod Code +`_ +from the Nimrod `GitHub wiki`_. + +This command is safe to run because it will never attempt to overwrite your +existing sources, but the respective ``.pretty.nim`` files **will** be +overwritten without notice. + + DynlibOverride ============== diff --git a/doc/sets_fragment.txt b/doc/sets_fragment.txt new file mode 100644 index 0000000000..fba3552690 --- /dev/null +++ b/doc/sets_fragment.txt @@ -0,0 +1,40 @@ +The set type models the mathematical notion of a set. The set's +basetype can only be an ordinal type. The reason is that sets are implemented +as high performance bit vectors. + +Sets can be constructed via the set constructor: ``{}`` is the empty set. The +empty set is type compatible with any concrete set type. The constructor +can also be used to include elements (and ranges of elements): + +.. code-block:: nimrod + type + TCharSet = set[char] + var + x: TCharSet + x = {'a'..'z', '0'..'9'} # This constructs a set that contains the + # letters from 'a' to 'z' and the digits + # from '0' to '9' + +These operations are supported by sets: + +================== ======================================================== +operation meaning +================== ======================================================== +``A + B`` union of two sets +``A * B`` intersection of two sets +``A - B`` difference of two sets (A without B's elements) +``A == B`` set equality +``A <= B`` subset relation (A is subset of B or equal to B) +``A < B`` strong subset relation (A is a real subset of B) +``e in A`` set membership (A contains element e) +``e notin A`` A does not contain element e +``contains(A, e)`` A contains element e +``A -+- B`` symmetric set difference (= (A - B) + (B - A)) +``card(A)`` the cardinality of A (number of elements in A) +``incl(A, elem)`` same as ``A = A + {elem}`` +``excl(A, elem)`` same as ``A = A - {elem}`` +================== ======================================================== + +Sets are often used to define a type for the *flags* of a procedure. This is +a much cleaner (and type safe) solution than just defining integer +constants that should be ``or``'ed together. diff --git a/doc/spawn.txt b/doc/spawn.txt index ed500f3a5c..c5c96ecf8b 100644 --- a/doc/spawn.txt +++ b/doc/spawn.txt @@ -53,13 +53,13 @@ restrictions / changes: * ``spawn`` within a ``parallel`` section has special semantics. * Every location of the form ``a[i]`` and ``a[i..j]`` and ``dest`` where ``dest`` is part of the pattern ``dest = spawn f(...)`` has to be - provable disjoint. This is called the *disjoint check*. + provably disjoint. This is called the *disjoint check*. * Every other complex location ``loc`` that is used in a spawned proc (``spawn f(loc)``) has to be immutable for the duration of the ``parallel`` section. This is called the *immutability check*. Currently it is not specified what exactly "complex location" means. We need to make this an optimization! -* Every array access has to be provable within bounds. This is called +* Every array access has to be provably within bounds. This is called the *bounds check*. * Slices are optimized so that no copy is performed. This optimization is not yet performed for ordinary slices outside of a ``parallel`` section. Slices diff --git a/doc/tut1.txt b/doc/tut1.txt index a2aa835ee5..ee642ce176 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -17,10 +17,9 @@ Introduction This document is a tutorial for the programming language *Nimrod*. -This tutorial assumes that you are familiar with basic programming concepts -like variables, types or statements but is kept very basic. The manual -contains many more examples of the advanced language features. - +This tutorial assumes that you are familiar with basic programming concepts +like variables, types or statements but is kept very basic. The `manual +`_ contains many more examples of the advanced language features. @@ -40,9 +39,9 @@ Save this code to the file "greetings.nim". Now compile and run it:: nimrod compile --run greetings.nim -With the ``--run`` switch Nimrod executes the file automatically -after compilation. You can give your program command line arguments by -appending them after the filename:: +With the ``--run`` `switch `_ Nimrod +executes the file automatically after compilation. You can give your program +command line arguments by appending them after the filename:: nimrod compile --run greetings.nim arg1 arg2 @@ -54,9 +53,10 @@ To compile a release version use:: nimrod c -d:release greetings.nim -By default the Nimrod compiler generates a large amount of runtime checks -aiming for your debugging pleasure. With ``-d:release`` these checks are -turned off and optimizations are turned on. +By default the Nimrod compiler generates a large amount of runtime checks +aiming for your debugging pleasure. With ``-d:release`` these checks are +`turned off and optimizations are turned on +`_. Though it should be pretty obvious what the program does, I will explain the syntax: statements which are not indented are executed when the program @@ -65,9 +65,10 @@ done with spaces only, tabulators are not allowed. String literals are enclosed in double quotes. The ``var`` statement declares a new variable named ``name`` of type ``string`` with the value that is -returned by the ``readLine`` procedure. Since the compiler knows that -``readLine`` returns a string, you can leave out the type in the declaration -(this is called `local type inference`:idx:). So this will work too: +returned by the `readLine `_ procedure. Since the +compiler knows that `readLine `_ returns a string, +you can leave out the type in the declaration (this is called `local type +inference`:idx:). So this will work too: .. code-block:: Nimrod var name = readLine(stdin) @@ -75,10 +76,10 @@ returned by the ``readLine`` procedure. Since the compiler knows that Note that this is basically the only form of type inference that exists in Nimrod: it is a good compromise between brevity and readability. -The "hello world" program contains several identifiers that are already -known to the compiler: ``echo``, ``readLine``, etc. These built-ins are -declared in the system_ module which is implicitly imported by any other -module. +The "hello world" program contains several identifiers that are already known +to the compiler: ``echo``, `readLine `_, etc. +These built-ins are declared in the system_ module which is implicitly +imported by any other module. Lexical elements @@ -154,11 +155,11 @@ the syntax, watch their indentation: when false: brokenCode() -Another option is to use the `discard`_ statement together with -*long string literals* to create block comments: +Another option is to use the `discard statement`_ together with *long string +literals* to create block comments: .. code-block:: nimrod - discard """ You can have any nimrod code text commented + discard """ You can have any Nimrod code text commented out inside this with no indentation restrictions. yes("May I ask a pointless question?") """ @@ -257,10 +258,10 @@ that can not be re-assigned, ``const`` means "enforce compile time evaluation and put it into a data section": .. code-block:: - const input = readline(stdin) # Error: constant expression expected + const input = readLine(stdin) # Error: constant expression expected .. code-block:: - let input = readline(stdin) # works + let input = readLine(stdin) # works Control flow statements @@ -285,9 +286,10 @@ The if statement is one way to branch the control flow: else: echo("Hi, ", name, "!") -There can be zero or more elif parts, and the else part is optional. The -keyword ``elif`` is short for ``else if``, and is useful to avoid excessive -indentation. (The ``""`` is the empty string. It contains no characters.) +There can be zero or more ``elif`` parts, and the ``else`` part is optional. +The keyword ``elif`` is short for ``else if``, and is useful to avoid +excessive indentation. (The ``""`` is the empty string. It contains no +characters.) Case statement @@ -338,7 +340,7 @@ the compiler that for every other value nothing should be done: of 3, 8: echo("The number is 3 or 8") else: discard -The empty ``discard`` statement is a *do nothing* statement. The compiler knows +The empty `discard statement`_ is a *do nothing* statement. The compiler knows that a case statement with an else part cannot fail and thus the error disappears. Note that it is impossible to cover all possible string values: that is why there is no such check for string cases. @@ -370,7 +372,8 @@ For statement ------------- The ``for`` statement is a construct to loop over any element an *iterator* -provides. The example uses the built-in ``countup`` iterator: +provides. The example uses the built-in `countup `_ +iterator: .. code-block:: nimrod echo("Counting to ten: ") @@ -378,11 +381,11 @@ provides. The example uses the built-in ``countup`` iterator: echo($i) # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines -The built-in ``$`` operator turns an integer (``int``) and many other types -into a string. The variable ``i`` is implicitly declared by the ``for`` loop -and has the type ``int``, because that is what ``countup`` returns. ``i`` runs -through the values 1, 2, .., 10. Each value is ``echo``-ed. This code does -the same: +The built-in `$ `_ operator turns an integer (``int``) and many +other types into a string. The variable ``i`` is implicitly declared by the +``for`` loop and has the type ``int``, because that is what `countup +`_ returns. ``i`` runs through the values 1, 2, .., 10. +Each value is ``echo``-ed. This code does the same: .. code-block:: nimrod echo("Counting to 10: ") @@ -400,8 +403,8 @@ Counting down can be achieved as easily (but is less often needed): echo($i) # --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines -Since counting up occurs so often in programs, Nimrod also has a ``..`` iterator -that does the same: +Since counting up occurs so often in programs, Nimrod also has a `.. +`_ iterator that does the same: .. code-block:: nimrod for i in 1..10: @@ -553,9 +556,10 @@ an expression is allowed: Procedures ========== -To define new commands like ``echo``, ``readline`` in the examples, the concept -of a `procedure` is needed. (Some languages call them *methods* or -*functions*.) In Nimrod new procedures are defined with the ``proc`` keyword: +To define new commands like `echo `_ and `readLine +`_ in the examples, the concept of a `procedure` +is needed. (Some languages call them *methods* or *functions*.) In Nimrod new +procedures are defined with the ``proc`` keyword: .. code-block:: nimrod proc yes(question: string): bool = @@ -649,7 +653,7 @@ a tuple as a return value instead of using var parameters. Discard statement ----------------- To call a procedure that returns a value just for its side effects and ignoring -its return value, a discard statement **has** to be used. Nimrod does not +its return value, a ``discard`` statement **has** to be used. Nimrod does not allow to silently throw away a return value: .. code-block:: nimrod @@ -665,8 +669,8 @@ been declared with the ``discardable`` pragma: p(3, 4) # now valid -The discard statement can also be used to create block comments as described -in the `Comments`_. +The ``discard`` statement can also be used to create block comments as +described in the `Comments`_ section. Named arguments @@ -730,12 +734,12 @@ Nimrod provides the ability to overload procedures similar to C++: echo(toString(13)) # calls the toString(x: int) proc echo(toString(true)) # calls the toString(x: bool) proc -(Note that ``toString`` is usually the ``$`` operator in Nimrod.) -The compiler chooses the most appropriate proc for the ``toString`` calls. How -this overloading resolution algorithm works exactly is not discussed here -(it will be specified in the manual soon). -However, it does not lead to nasty surprises and is based on a quite simple -unification algorithm. Ambiguous calls are reported as errors. +(Note that ``toString`` is usually the `$ `_ operator in +Nimrod.) The compiler chooses the most appropriate proc for the ``toString`` +calls. How this overloading resolution algorithm works exactly is not +discussed here (it will be specified in the manual soon). However, it does +not lead to nasty surprises and is based on a quite simple unification +algorithm. Ambiguous calls are reported as errors. Operators @@ -758,7 +762,7 @@ User defined operators are allowed. Nothing stops you from defining your own The operator's precedence is determined by its first character. The details can be found in the manual. -To define a new operator enclose the operator in "``": +To define a new operator enclose the operator in backticks "``": .. code-block:: nimrod proc `$` (x: myDataType): string = ... @@ -811,7 +815,8 @@ Let's return to the boring counting example: for i in countup(1, 10): echo($i) -Can a ``countup`` proc be written that supports this loop? Lets try: +Can a `countup `_ proc be written that supports this +loop? Lets try: .. code-block:: nimrod proc countup(a, b: int): int = @@ -976,24 +981,25 @@ type: The common operators ``+ - * / < <= == != > >=`` are defined for floats and follow the IEEE standard. -Automatic type conversion in expressions with different kinds -of floating point types is performed: the smaller type is -converted to the larger. Integer types are **not** converted to floating point -types automatically and vice versa. The ``toInt`` and ``toFloat`` procs can be -used for these conversions. +Automatic type conversion in expressions with different kinds of floating +point types is performed: the smaller type is converted to the larger. Integer +types are **not** converted to floating point types automatically and vice +versa. The `toInt `_ and `toFloat `_ +procs can be used for these conversions. Internal type representation ============================ -As mentioned earlier, the built-in ``$`` (stringify) operator turns any basic -type into a string, which you can then print to the screen with the ``echo`` -proc. However, advanced types, or types you may define yourself won't work with -the ``$`` operator until you define one for them. Sometimes you just want to -debug the current value of a complex type without having to write its ``$`` -operator. You can use then the ``repr`` proc which works with any type and -even complex data graphs with cycles. The following example shows that even for -basic types there is a difference between the ``$`` and ``repr`` outputs: +As mentioned earlier, the built-in `$ `_ (stringify) operator +turns any basic type into a string, which you can then print to the screen +with the ``echo`` proc. However, advanced types, or types you may define +yourself won't work with the ``$`` operator until you define one for them. +Sometimes you just want to debug the current value of a complex type without +having to write its ``$`` operator. You can use then the `repr +`_ proc which works with any type and even complex data +graphs with cycles. The following example shows that even for basic types +there is a difference between the ``$`` and ``repr`` outputs: .. code-block:: nimrod var @@ -1087,9 +1093,10 @@ Operation Comment ``pred(x, n)`` returns the `n`'th predecessor of `x` ----------------- -------------------------------------------------------- -The ``inc dec succ pred`` operations can fail by raising an `EOutOfRange` or -`EOverflow` exception. (If the code has been compiled with the proper runtime -checks turned on.) +The `inc `_, `dec `_, `succ +`_ and `pred `_ operations can fail by +raising an `EOutOfRange` or `EOverflow` exception. (If the code has been +compiled with the proper runtime checks turned on.) Subranges @@ -1107,57 +1114,18 @@ to 5. Assigning any other value to a variable of type ``TSubrange`` is a compile-time or runtime error. Assignments from the base type to one of its subrange types (and vice versa) are allowed. -The ``system`` module defines the important ``natural`` type as -``range[0..high(int)]`` (``high`` returns the maximal value). Other programming -languages mandate the usage of unsigned integers for natural numbers. This is -often **wrong**: you don't want unsigned arithmetic (which wraps around) just -because the numbers cannot be negative. Nimrod's ``natural`` type helps to -avoid this common programming error. +The ``system`` module defines the important `Natural `_ +type as ``range[0..high(int)]`` (`high `_ returns the +maximal value). Other programming languages mandate the usage of unsigned +integers for natural numbers. This is often **wrong**: you don't want unsigned +arithmetic (which wraps around) just because the numbers cannot be negative. +Nimrod's ``Natural`` type helps to avoid this common programming error. Sets ---- -The set type models the mathematical notion of a set. The set's -basetype can only be an ordinal type. The reason is that sets are implemented -as high performance bit vectors. - -Sets can be constructed via the set constructor: ``{}`` is the empty set. The -empty set is type compatible with any concrete set type. The constructor -can also be used to include elements (and ranges of elements): - -.. code-block:: nimrod - type - TCharSet = set[char] - var - x: TCharSet - x = {'a'..'z', '0'..'9'} # This constructs a set that contains the - # letters from 'a' to 'z' and the digits - # from '0' to '9' - -These operations are supported by sets: - -================== ======================================================== -operation meaning -================== ======================================================== -``A + B`` union of two sets -``A * B`` intersection of two sets -``A - B`` difference of two sets (A without B's elements) -``A == B`` set equality -``A <= B`` subset relation (A is subset of B or equal to B) -``A < B`` strong subset relation (A is a real subset of B) -``e in A`` set membership (A contains element e) -``e notin A`` A does not contain element e -``contains(A, e)`` A contains element e -``A -+- B`` symmetric set difference (= (A - B) + (B - A)) -``card(A)`` the cardinality of A (number of elements in A) -``incl(A, elem)`` same as ``A = A + {elem}`` -``excl(A, elem)`` same as ``A = A - {elem}`` -================== ======================================================== - -Sets are often used to define a type for the *flags* of a procedure. This is -a much cleaner (and type safe) solution than just defining integer -constants that should be ``or``'ed together. +.. include:: sets_fragment.txt Arrays ------ @@ -1184,8 +1152,9 @@ checks can be disabled via pragmas or invoking the compiler with the Arrays are value types, like any other Nimrod type. The assignment operator copies the whole array contents. -The built-in ``len`` proc returns the array's length. ``low(a)`` returns the -lowest valid index for the array `a` and ``high(a)`` the highest valid index. +The built-in `len `_ proc returns the array's +length. `low(a) `_ returns the lowest valid index for the +array `a` and `high(a) `_ the highest valid index. .. code-block:: nimrod type @@ -1257,13 +1226,14 @@ Sequences are similar to arrays but of dynamic length which may change during runtime (like strings). Since sequences are resizable they are always allocated on the heap and garbage collected. -Sequences are always indexed with an ``int`` starting at position 0. -The ``len``, ``low`` and ``high`` operations are available for sequences too. -The notation ``x[i]`` can be used to access the i-th element of ``x``. +Sequences are always indexed with an ``int`` starting at position 0. The `len +`_, `low `_ and `high +`_ operations are available for sequences too. The notation +``x[i]`` can be used to access the i-th element of ``x``. Sequences can be constructed by the array constructor ``[]`` in conjunction with the array to sequence operator ``@``. Another way to allocate space for -a sequence is to call the built-in ``newSeq`` procedure. +a sequence is to call the built-in `newSeq `_ procedure. A sequence may be passed to an openarray parameter. @@ -1284,10 +1254,11 @@ object on the heap, so there is a trade-off to be made here. The ``for`` statement can be used with one or two variables when used with a sequence. When you use the one variable form, the variable will hold the value provided by the sequence. The ``for`` statement is looping over the results -from the ``items()`` iterator from the `system `_ module. But if -you use the two variable form, the first variable will hold the index position -and the second variable will hold the value. Here the ``for`` statement is -looping over the results from the ``pairs()`` iterator from the `system +from the `items() `_ iterator from the `system +`_ module. But if you use the two variable form, the first +variable will hold the index position and the second variable will hold the +value. Here the ``for`` statement is looping over the results from the +`pairs() `_ iterator from the `system `_ module. Examples: .. code-block:: nimrod @@ -1308,12 +1279,13 @@ Open arrays ----------- **Note**: Openarrays can only be used for parameters. -Often fixed size arrays turn out to be too inflexible; procedures should -be able to deal with arrays of different sizes. The `openarray`:idx: type -allows this. Openarrays are always indexed with an ``int`` starting at -position 0. The ``len``, ``low`` and ``high`` operations are available -for open arrays too. Any array with a compatible base type can be passed to -an openarray parameter, the index type does not matter. +Often fixed size arrays turn out to be too inflexible; procedures should be +able to deal with arrays of different sizes. The `openarray`:idx: type allows +this. Openarrays are always indexed with an ``int`` starting at position 0. +The `len `_, `low `_ and `high +`_ operations are available for open arrays too. Any array +with a compatible base type can be passed to an openarray parameter, the index +type does not matter. The openarray type cannot be nested: multidimensional openarrays are not supported because this is seldom needed and cannot be done efficiently. @@ -1351,8 +1323,9 @@ type conversions in this context: # is transformed by the compiler to: myWriteln(stdout, [$123, $"def", $4.0]) -In this example ``$`` is applied to any argument that is passed to the -parameter ``a``. Note that ``$`` applied to strings is a nop. +In this example `$ `_ is applied to any argument that is passed +to the parameter ``a``. Note that `$ `_ applied to strings is a +nop. Slices @@ -1431,11 +1404,12 @@ having the same field types. Tuples can be *unpacked* during variable assignment (and only then!). This can be handy to assign directly the fields of the tuples to individually named -variables. An example of this is the ``splitFile`` proc from the `os module -`_ which returns the directory, name and extension of a path at the -same time. For tuple unpacking to work you have to use parenthesis around the -values you want to assign the unpacking to, otherwise you will be assigning the -same value to all the individual variables! Example: +variables. An example of this is the `splitFile `_ proc +from the `os module `_ which returns the directory, name and +extension of a path at the same time. For tuple unpacking to work you have to +use parenthesis around the values you want to assign the unpacking to, +otherwise you will be assigning the same value to all the individual +variables! Example: .. code-block:: nimrod diff --git a/doc/tut2.txt b/doc/tut2.txt index 1e23618e08..582a6b3e4d 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -23,11 +23,13 @@ features.** Pragmas ======= + Pragmas are Nimrod's method to give the compiler additional information/ -commands without introducing a massive number of new keywords. Pragmas are -enclosed in the special ``{.`` and ``.}`` curly dot brackets. This tutorial -does not cover pragmas. See the `manual `_ -or `user guide `_ for a description of the available pragmas. +commands without introducing a massive number of new keywords. Pragmas are +enclosed in the special ``{.`` and ``.}`` curly dot brackets. This tutorial +does not cover pragmas. See the `manual `_ or `user guide +`_ for a description of the available +pragmas. Object Oriented Programming @@ -421,9 +423,10 @@ the rest of the procedure - that is not within a ``finally`` clause - is not executed (if an exception occurs). If you need to *access* the actual exception object or message inside an -``except`` branch you can use the getCurrentException() and -getCurrentExceptionMsg() procs from the `system `_ module. -Example: +``except`` branch you can use the `getCurrentException() +`_ and `getCurrentExceptionMsg() +`_ procs from the `system `_ +module. Example: .. code-block:: nimrod try: @@ -435,48 +438,6 @@ Example: echo "Got exception ", repr(e), " with message ", msg -Exception hierarchy -------------------- - -If you want to create your own exceptions you can inherit from E_Base, but you -can also inherit from one of the existing exceptions if they fit your purpose. -The exception tree is:: - - * E_Base - * EAsynch - * EControlC - * ESynch - * ESystem - * EIO - * EOS - * EInvalidLibrary - * EResourceExhausted - * EOutOfMemory - * EStackOverflow - * EArithmetic - * EDivByZero - * EOverflow - * EAccessViolation - * EAssertionFailed - * EInvalidValue - * EInvalidKey - * EInvalidIndex - * EInvalidField - * EOutOfRange - * ENoExceptionToReraise - * EInvalidObjectAssignment - * EInvalidObjectConversion - * EFloatingPoint - * EFloatInvalidOp - * EFloatDivByZero - * EFloatOverflow - * EFloatUnderflow - * EFloatInexact - * EDeadThread - -See the `system `_ module for a description of each exception. - - Annotating procs with raised exceptions --------------------------------------- @@ -663,8 +624,8 @@ statement: declareInNewScope(b, int) b = 42 # does not work, `b` is unknown -(The manual explains why the ``immediate`` pragma is needed for these -templates.) +(The `manual explains `_ why the +``immediate`` pragma is needed for these templates.) If there is a ``stmt`` parameter it should be the last in the template declaration. The reason is that statements can be passed to a template diff --git a/examples/0mq/client.nim b/examples/0mq/client.nim deleted file mode 100644 index e75e5c7a2d..0000000000 --- a/examples/0mq/client.nim +++ /dev/null @@ -1,14 +0,0 @@ -import zmq - -var connection = zmq.open("tcp://localhost:5555", server=false) - -echo("Connecting...") - -for i in 0..10: - echo("Sending hello...", i) - send(connection, "Hello") - - var reply = receive(connection) - echo("Received ...", reply) - -close(connection) diff --git a/examples/0mq/server.nim b/examples/0mq/server.nim deleted file mode 100644 index 0fadf8b97f..0000000000 --- a/examples/0mq/server.nim +++ /dev/null @@ -1,11 +0,0 @@ -import zmq - -var connection = zmq.open("tcp://*:5555", server=true) - -while True: - var request = receive(connection) - echo("Received: ", request) - send(connection, "World") - -close(connection) - diff --git a/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj b/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj index 36b43d31bf..71cebc18a9 100644 --- a/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj +++ b/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj @@ -13,7 +13,7 @@ D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424A15BC87B6005EFF20 /* AppDelegate.m */; }; D531424E15BC87B6005EFF20 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424B15BC87B6005EFF20 /* main.m */; }; D531427215BC94B1005EFF20 /* backend.m in Sources */ = {isa = PBXBuildFile; fileRef = D531426F15BC94B1005EFF20 /* backend.m */; }; - D531427415BC94B1005EFF20 /* system.m in Sources */ = {isa = PBXBuildFile; fileRef = D531427115BC94B1005EFF20 /* system.m */; }; + D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */ = {isa = PBXBuildFile; fileRef = D531427115BC94B1005EFF20 /* stdlib_system.m */; }; D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5B6F94615FA8D4C0084A85B /* NRViewController.m */; }; /* End PBXBuildFile section */ @@ -30,7 +30,7 @@ D531426715BC91EF005EFF20 /* tags.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = tags.sh; path = scripts/tags.sh; sourceTree = ""; }; D531426815BC91EF005EFF20 /* xcode_prebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = xcode_prebuild.sh; path = scripts/xcode_prebuild.sh; sourceTree = ""; }; D531426F15BC94B1005EFF20 /* backend.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = backend.m; path = build/nimcache/backend.m; sourceTree = ""; }; - D531427115BC94B1005EFF20 /* system.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = system.m; path = build/nimcache/system.m; sourceTree = ""; }; + D531427115BC94B1005EFF20 /* stdlib_system.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = stdlib_system.m; path = build/nimcache/stdlib_system.m; sourceTree = ""; }; D592E19015C7120F005258EA /* backend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = backend.h; path = build/nimcache/backend.h; sourceTree = ""; }; D592E19115C71415005258EA /* nimbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nimbase.h; path = build/nimcache/nimbase.h; sourceTree = ""; }; D5B6F94515FA8D4C0084A85B /* NRViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NRViewController.h; path = src/NRViewController.h; sourceTree = ""; }; @@ -135,7 +135,7 @@ D592E19015C7120F005258EA /* backend.h */, D531426F15BC94B1005EFF20 /* backend.m */, D592E19115C71415005258EA /* nimbase.h */, - D531427115BC94B1005EFF20 /* system.m */, + D531427115BC94B1005EFF20 /* stdlib_system.m */, ); name = nimrod; sourceTree = ""; @@ -229,7 +229,7 @@ D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */, D531424E15BC87B6005EFF20 /* main.m in Sources */, D531427215BC94B1005EFF20 /* backend.m in Sources */, - D531427415BC94B1005EFF20 /* system.m in Sources */, + D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */, D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -259,11 +259,7 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - OTHER_LDFLAGS = ( - "-weak_library", - /usr/lib/libSystem.B.dylib, - ); + IPHONEOS_DEPLOYMENT_TARGET = 4.3; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -284,12 +280,8 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; - OTHER_LDFLAGS = ( - "-weak_library", - /usr/lib/libSystem.B.dylib, - ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; diff --git a/examples/cross_calculator/ios/scripts/xcode_prebuild.sh b/examples/cross_calculator/ios/scripts/xcode_prebuild.sh index c6d38f1641..90bafd74e4 100644 --- a/examples/cross_calculator/ios/scripts/xcode_prebuild.sh +++ b/examples/cross_calculator/ios/scripts/xcode_prebuild.sh @@ -22,7 +22,7 @@ DEST_NIMBASE=build/nimcache/nimbase.h if [ -d src ] then $PATH_TO_NIMROD objc --noMain --app:lib \ - --nimcache:build/nimcache --compileOnly \ + --nimcache:./build/nimcache --compileOnly \ --header --cpu:i386 ../nimrod_backend/backend.nim if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ] then diff --git a/install.txt b/install.txt index 2883c8495d..4543e4ecee 100644 --- a/install.txt +++ b/install.txt @@ -58,8 +58,6 @@ Currently, the following C compilers are supported under Windows: | http://www.mingw.org/download.shtml - | LLVM with Clang or GNU C/C++ frontend | http://llvm.org/releases/download.html -- | Digital Mars C++ - | http://www.digitalmars.com/download/freecompiler.html However, most testing is done with GCC. diff --git a/koch.nim b/koch.nim index 15ee3732de..8385ac84e9 100644 --- a/koch.nim +++ b/koch.nim @@ -43,7 +43,7 @@ Possible Commands: web generates the website csource [options] builds the C sources for installation zip builds the installation ZIP package - inno [options] builds the Inno Setup installer (for Windows) + nsis [options] builds the NSIS Setup installer (for Windows) tests [options] run the testsuite update updates nimrod to the latest version from github (compile koch with -d:withUpdate to enable) @@ -77,6 +77,14 @@ proc tryExec(cmd: string): bool = echo(cmd) result = execShellCmd(cmd) == 0 +proc safeRemove(filename: string) = + if existsFile(filename): removeFile(filename) + +proc copyExe(source, dest: string) = + safeRemove(dest) + copyFile(dest=dest, source=source) + inclFilePermissions(dest, {fpUserExec}) + const compileNimInst = "-d:useLibzipSrc tools/niminst/niminst" @@ -84,21 +92,25 @@ proc csource(args: string) = exec("$4 cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" % [args, NimrodVersion, compileNimInst, findNim()]) -proc zip(args: string) = - exec("$3 cc -r $2 --var:version=$1 zip compiler/nimrod.ini" % +proc zip(args: string) = + exec("$3 cc -r $2 --var:version=$1 --var:mingw=mingw32 scripts compiler/nimrod.ini" % [NimrodVersion, compileNimInst, findNim()]) + exec("$# --var:version=$# --var:mingw=mingw32 zip compiler/nimrod.ini" % + ["tools/niminst/niminst".exe, NimrodVersion]) proc buildTool(toolname, args: string) = exec("$# cc $# $#" % [findNim(), args, toolname]) copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe) -proc inno(args: string) = - # make sure we have generated the c2nim and niminst executables: +proc nsis(args: string) = + # 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) + # produce 'nimrod_debug.exe': + exec "nimrod c compiler" / "nimrod.nim" + copyExe("compiler/nimrod".exe, "bin/nimrod_debug".exe) + exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw32" & + " nsis compiler/nimrod") % NimrodVersion) proc install(args: string) = exec("$# cc -r $# --var:version=$# scripts compiler/nimrod.ini" % @@ -136,16 +148,8 @@ proc findStartNimrod: string = echo("Found no nimrod compiler and every attempt to build one failed!") quit("FAILURE") -proc safeRemove(filename: string) = - if existsFile(filename): removeFile(filename) - proc thVersion(i: int): string = result = ("compiler" / "nimrod" & $i).exe - -proc copyExe(source, dest: string) = - safeRemove(dest) - copyFile(dest=dest, source=source) - inclFilePermissions(dest, {fpUserExec}) proc boot(args: string) = var output = "compiler" / "nimrod".exe @@ -303,7 +307,7 @@ of cmdArgument: of "web": web(op.cmdLineRest) of "csource", "csources": csource(op.cmdLineRest) of "zip": zip(op.cmdLineRest) - of "inno": inno(op.cmdLineRest) + of "nsis": nsis(op.cmdLineRest) of "install": install(op.cmdLineRest) of "test", "tests": tests(op.cmdLineRest) of "update": diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 334a4b8c76..e290cce329 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -627,7 +627,7 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} = case node.kind of nnkIdent: result = $node.ident - of nnkStrLit: + of nnkStrLit..nnkTripleStrLit: result = node.strVal else: badNodeKind node.kind, "$" diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim index edb4d11885..8df1b3dfbe 100644 --- a/lib/core/typeinfo.nim +++ b/lib/core/typeinfo.nim @@ -102,7 +102,7 @@ proc newAny(value: pointer, rawType: PNimType): TAny = result.value = value result.rawType = rawType -when defined(system.TVarSlot): +when declared(system.TVarSlot): proc toAny*(x: TVarSlot): TAny {.inline.} = ## constructs a ``TAny`` object from a variable slot ``x``. ## This captures `x`'s address, so `x` can be modified with its @@ -420,6 +420,59 @@ proc setBiggestInt*(x: TAny, y: biggestInt) = of tyUInt32: cast[ptr uint32](x.value)[] = uint32(y) else: assert false +proc getUInt*(x: TAny): uint = + ## retrieve the uint value out of `x`, `x` needs to represent an uint. + assert skipRange(x.rawtype).kind == tyUInt + result = cast[ptr uint](x.value)[] + +proc getUInt8*(x: TAny): uint8 = + ## retrieve the uint8 value out of `x`, `x` needs to represent an + ## uint8. + assert skipRange(x.rawtype).kind == tyUInt8 + result = cast[ptr uint8](x.value)[] + +proc getUInt16*(x: TAny): uint16 = + ## retrieve the uint16 value out of `x`, `x` needs to represent an + ## uint16. + assert skipRange(x.rawtype).kind == tyUInt16 + result = cast[ptr uint16](x.value)[] + +proc getUInt32*(x: TAny): uint32 = + ## retrieve the uint32 value out of `x`, `x` needs to represent an + ## uint32. + assert skipRange(x.rawtype).kind == tyUInt32 + result = cast[ptr uint32](x.value)[] + +proc getUInt64*(x: TAny): uint64 = + ## retrieve the uint64 value out of `x`, `x` needs to represent an + ## uint64. + assert skipRange(x.rawtype).kind == tyUInt64 + result = cast[ptr uint64](x.value)[] + +proc getBiggestUint*(x: TAny): uint64 = + ## retrieve the unsigned integer value out of `x`. `x` needs to + ## represent an unsigned integer. + var t = skipRange(x.rawtype) + case t.kind + of tyUInt: result = uint64(cast[ptr uint](x.value)[]) + of tyUInt8: result = uint64(cast[ptr uint8](x.value)[]) + of tyUInt16: result = uint64(cast[ptr uint16](x.value)[]) + of tyUInt32: result = uint64(cast[ptr uint32](x.value)[]) + of tyUInt64: result = uint64(cast[ptr uint64](x.value)[]) + else: assert false + +proc setBiggestUint*(x: TAny; y: uint64) = + ## sets the unsigned integer value of `c`. `c` needs to represent an + ## unsigned integer. + var t = skipRange(x.rawtype) + case t.kind: + of tyUInt: cast[ptr uint](x.value)[] = uint(y) + of tyUInt8: cast[ptr uint8](x.value)[] = uint8(y) + of tyUInt16: cast[ptr uint16](x.value)[] = uint16(y) + of tyUInt32: cast[ptr uint32](x.value)[] = uint32(y) + of tyUInt64: cast[ptr uint64](x.value)[] = uint64(y) + else: assert false + proc getChar*(x: TAny): char = ## retrieve the char value out of `x`. `x` needs to represent a char. var t = skipRange(x.rawtype) diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index f6ae933030..c375d91910 100644 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -19,12 +19,13 @@ type EDb* = object of EIO ## exception that is raised if a database error occurs TSqlQuery* = distinct string ## an SQL query string + TSqlPrepared* = distinct string ## a identifier for the prepared queries FDb* = object of FIO ## effect that denotes a database operation FReadDb* = object of FDB ## effect that denotes a read operation FWriteDb* = object of FDB ## effect that denotes a write operation - -proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} = + +proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} = ## constructs a TSqlQuery from the string `query`. This is supposed to be ## used as a raw-string-literal modifier: ## ``sql"update user set counter = counter + 1"`` @@ -33,14 +34,14 @@ proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} = ## on, later versions will check the string for valid syntax. result = TSqlQuery(query) -proc dbError(db: TDbConn) {.noreturn.} = +proc dbError*(db: TDbConn) {.noreturn.} = ## raises an EDb exception. var e: ref EDb new(e) e.msg = $PQerrorMessage(db) raise e -proc dbError*(msg: string) {.noreturn.} = +proc dbError*(msg: string) {.noreturn.} = ## raises an EDb exception with message `msg`. var e: ref EDb new(e) @@ -61,41 +62,70 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string = if c == '?': add(result, dbQuote(args[a])) inc(a) - else: + else: add(result, c) -proc tryExec*(db: TDbConn, query: TSqlQuery, +proc tryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} = ## tries to execute the query and returns true if successful, false otherwise. - var q = dbFormat(query, args) - var res = PQExec(db, q) + var arr = allocCStringArray(args) + var res = PQexecParams(db, query.string, int32(args.len), nil, arr, + nil, nil, 0) + deallocCStringArray(arr) result = PQresultStatus(res) == PGRES_COMMAND_OK PQclear(res) proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {. tags: [FReadDB, FWriteDb].} = ## executes the query and raises EDB if not successful. - var q = dbFormat(query, args) - var res = PQExec(db, q) + var arr = allocCStringArray(args) + var res = PQexecParams(db, query.string, int32(args.len), nil, arr, + nil, nil, 0) + deallocCStringArray(arr) if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db) PQclear(res) - + +proc exec*(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string]) {.tags: [FReadDB, FWriteDb].} = + var arr = allocCStringArray(args) + var res = PQexecPrepared(db, stmtName.string, int32(args.len), arr, + nil, nil, 0) + deallocCStringArray(arr) + if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db) + PQclear(res) + proc newRow(L: int): TRow = newSeq(result, L) for i in 0..L-1: result[i] = "" -proc setupQuery(db: TDbConn, query: TSqlQuery, - args: varargs[string]): PPGresult = - var q = dbFormat(query, args) - result = PQExec(db, q) - if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db) - +proc setupQuery(db: TDbConn, query: TSqlQuery, + args: varargs[string]): PPGresult = + var arr = allocCStringArray(args) + result = PQexecParams(db, query.string, int32(args.len), nil, arr, + nil, nil, 0) + deallocCStringArray(arr) + if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db) + +proc setupQuery(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string]): PPGresult = + var arr = allocCStringArray(args) + result = PQexecPrepared(db, stmtName.string, int32(args.len), arr, + nil, nil, 0) + deallocCStringArray(arr) + if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db) + +proc prepare*(db: TDbConn; stmtName: string, query: TSqlQuery; + nParams: int): TSqlPrepared = + var res = PQprepare(db, stmtName, query.string, int32(nParams), nil) + if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db) + return TSqlPrepared(stmtName) + proc setRow(res: PPGresult, r: var TRow, line, cols: int32) = for col in 0..cols-1: setLen(r[col], 0) var x = PQgetvalue(res, line, col) add(r[col], x) - + iterator fastRows*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = ## executes the query and iterates over the result dataset. This is very @@ -109,6 +139,17 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery, yield result PQclear(res) +iterator fastRows*(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = + ## executes the prepared query and iterates over the result dataset. + var res = setupQuery(db, stmtName, args) + var L = PQnfields(res) + var result = newRow(L) + for i in 0..PQntuples(res)-1: + setRow(res, result, i, L) + yield result + PQclear(res) + proc getRow*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = ## retrieves a single row. If the query doesn't return any rows, this proc @@ -119,40 +160,55 @@ proc getRow*(db: TDbConn, query: TSqlQuery, setRow(res, result, 0, L) PQclear(res) -proc getAllRows*(db: TDbConn, query: TSqlQuery, +proc getRow*(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = + var res = setupQuery(db, stmtName, args) + var L = PQnfields(res) + result = newRow(L) + setRow(res, result, 0, L) + PQclear(res) + +proc getAllRows*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} = ## executes the query and returns the whole result dataset. result = @[] for r in FastRows(db, query, args): result.add(r) -iterator rows*(db: TDbConn, query: TSqlQuery, +proc getAllRows*(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} = + ## executes the prepared query and returns the whole result dataset. + result = @[] + for r in FastRows(db, stmtName, args): + result.add(r) + +iterator rows*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = ## same as `FastRows`, but slower and safe. for r in items(GetAllRows(db, query, args)): yield r -proc getValue*(db: TDbConn, query: TSqlQuery, - args: varargs[string, `$`]): string {.tags: [FReadDB].} = +proc getValue*(db: TDbConn, query: TSqlQuery, + args: varargs[string, `$`]): string {.tags: [FReadDB].} = ## executes the query and returns the first column of the first row of the ## result dataset. Returns "" if the dataset contains no rows or the database ## value is NULL. var x = PQgetvalue(setupQuery(db, query, args), 0, 0) result = if isNil(x): "" else: $x -proc tryInsertID*(db: TDbConn, query: TSqlQuery, +proc tryInsertID*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb].}= ## executes the query (typically "INSERT") and returns the ## generated ID for the row or -1 in case of an error. For Postgre this adds ## ``RETURNING id`` to the query, so it only works if your primary key is ## named ``id``. - var x = PQgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"), + var x = PQgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"), args), 0, 0) if not isNil(x): result = ParseBiggestInt($x) else: result = -1 -proc insertID*(db: TDbConn, query: TSqlQuery, +proc insertID*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = ## executes the query (typically "INSERT") and returns the ## generated ID for the row. For Postgre this adds @@ -161,9 +217,9 @@ proc insertID*(db: TDbConn, query: TSqlQuery, result = TryInsertID(db, query, args) if result < 0: dbError(db) -proc execAffectedRows*(db: TDbConn, query: TSqlQuery, +proc execAffectedRows*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): int64 {.tags: [ - FReadDB, FWriteDb].} = + FReadDB, FWriteDb].} = ## executes the query (typically "UPDATE") and returns the ## number of affected rows. var q = dbFormat(query, args) @@ -172,7 +228,7 @@ proc execAffectedRows*(db: TDbConn, query: TSqlQuery, result = parseBiggestInt($PQcmdTuples(res)) PQclear(res) -proc close*(db: TDbConn) {.tags: [FDb].} = +proc close*(db: TDbConn) {.tags: [FDb].} = ## closes the database connection. if db != nil: PQfinish(db) diff --git a/lib/impure/re.nim b/lib/impure/re.nim index f6511dab4a..ac07b2d6ba 100644 --- a/lib/impure/re.nim +++ b/lib/impure/re.nim @@ -243,7 +243,7 @@ template `=~` *(s: string, pattern: TRegex): expr = ## echo("syntax error") ## bind maxSubPatterns - when not definedInScope(matches): + when not declaredInScope(matches): var matches {.inject.}: array[0..MaxSubpatterns-1, string] match(s, pattern, matches) diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim index 1726449d8a..b9f89dda08 100644 --- a/lib/impure/zipfiles.nim +++ b/lib/impure/zipfiles.nim @@ -56,6 +56,8 @@ proc addFile*(z: var TZipArchive, dest, src: string) = ## Adds the file `src` to the archive `z` with the name `dest`. `dest` ## may contain a path that will be created. assert(z.mode != fmRead) + if not fileExists(src): + raise newException(EIO, "File '" & src & "' does not exist") var zipsrc = zip_source_file(z.w, src, 0, -1) if zipsrc == nil: #echo("Dest: " & dest) diff --git a/lib/nimbase.h b/lib/nimbase.h index cfd33dca18..b430942270 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -328,7 +328,8 @@ struct TFrame { NCSTRING procname; NI line; NCSTRING filename; - NI len; + NI16 len; + NI16 calldepth; }; #define nimfr(proc, file) \ diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim index 80fbf3a51b..ff371f4e17 100644 --- a/lib/packages/docutils/highlite.nim +++ b/lib/packages/docutils/highlite.nim @@ -50,7 +50,7 @@ const "break", "case", "cast", "const", "continue", "converter", "discard", "distinct", "div", "do", "elif", "else", "end", "enum", "except", "export", "finally", "for", "from", "generic", "if", "import", "in", "include", - "interface", "is", "isnot", "iterator", "lambda", "let", "macro", "method", + "interface", "is", "isnot", "iterator", "let", "macro", "method", "mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "static", "template", "try", "tuple", "type", "using", "var", "when", "while", "with", diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index fdbca4ca84..e9bae69b55 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -775,7 +775,7 @@ proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) = dispA(d.target, result, "
", "\\begin{rstpre}\n", [])
   if lang == langNone:
     d.msgHandler(d.filename, 1, 0, mwUnsupportedLanguage, langstr)
-    result.add(m.text)
+    for letter in m.text: escChar(d.target, result, letter)
   else:
     var g: TGeneralTokenizer
     initGeneralTokenizer(g, m.text)
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index 8e66336c2e..e1bcd9dfcb 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -90,7 +90,7 @@ type
     d_ino*: Tino  ## File serial number.
     d_name*: array [0..255, char] ## Name of entry.
 
-  Tflock* {.importc: "flock", final, pure,
+  Tflock* {.importc: "struct flock", final, pure,
             header: "".} = object ## flock type
     l_type*: cshort   ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK.
     l_whence*: cshort ## Flag for starting offset.
@@ -1579,6 +1579,16 @@ var
   MSG_OOB* {.importc, header: "".}: cint
     ## Out-of-band data.
 
+
+when defined(linux):
+  var
+    MAP_POPULATE* {.importc, header: "".}: cint
+      ## Populate (prefault) page tables for a mapping.
+else:
+  var
+    MAP_POPULATE*: cint = 0
+
+
 when defined(macosx):
   var
     MSG_HAVEMORE* {.importc, header: "".}: cint
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 86d329763e..89c83a8a43 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -34,6 +34,20 @@ proc reverse*[T](a: var openArray[T]) =
   ## reverses the array `a`.
   reverse(a, 0, a.high)
 
+proc reversed*[T](a: openArray[T], first, last: int): seq[T] =
+  ## returns the reverse of the array `a[first..last]`.
+  result = newSeq[T](last - first + 1)
+  var x = first
+  var y = last
+  while x <= last:
+    result[x] = a[y]
+    dec(y)
+    inc(x)
+
+proc reversed*[T](a: openArray[T]): seq[T] =
+  ## returns the reverse of the array `a`.
+  reversed(a, 0, a.high)
+
 proc binarySearch*[T](a: openArray[T], key: T): int =
   ## binary search for `key` in `a`. Returns -1 if not found.
   var b = len(a)
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index d410f8ce16..0ea8ef43b2 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -9,7 +9,7 @@
 
 include "system/inclrtl"
 
-import os, oids, tables, strutils, macros
+import os, oids, tables, strutils, macros, times
 
 import rawsockets, net
 
@@ -27,12 +27,12 @@ export TPort, TSocketFlags
 ## **Note:** This module is still largely experimental.
 
 
-# TODO: Discarded void PFutures need to be checked for exception.
 # TODO: ``except`` statement (without `try`) does not work.
 # TODO: Multiple exception names in a ``except`` don't work.
 # TODO: The effect system (raises: []) has trouble with my try transformation.
 # TODO: Can't await in a 'except' body
 # TODO: getCurrentException(Msg) don't work
+# TODO: Check if yielded future is nil and throw a more meaningful exception
 
 # -- Futures
 
@@ -41,27 +41,41 @@ type
     cb: proc () {.closure,gcsafe.}
     finished: bool
     error*: ref EBase
-    stackTrace: string ## For debugging purposes only.
+    errorStackTrace*: string
+    when not defined(release):
+      stackTrace: string ## For debugging purposes only.
+      id: int
+      fromProc: string
 
   PFuture*[T] = ref object of PFutureBase
     value: T
 
-proc newFuture*[T](): PFuture[T] =
+var currentID* = 0
+proc newFuture*[T](fromProc: string = "unspecified"): PFuture[T] =
   ## Creates a new future.
+  ##
+  ## Specifying ``fromProc``, which is a string specifying the name of the proc
+  ## that this future belongs to, is a good habit as it helps with debugging.
   new(result)
   result.finished = false
-  result.stackTrace = getStackTrace()
+  when not defined(release):
+    result.stackTrace = getStackTrace()
+    result.id = currentID
+    result.fromProc = fromProc
+    currentID.inc()
 
 proc checkFinished[T](future: PFuture[T]) =
-  if future.finished:
-    echo("<----->")
-    echo(future.stackTrace)
-    echo("-----")
-    when T is string:
-      echo("Contents: ", future.value.repr)
-    echo("<----->")
-    echo("Future already finished, cannot finish twice.")
-    assert false
+  when not defined(release):
+    if future.finished:
+      echo("<-----> ", future.id, " ", future.fromProc)
+      echo(future.stackTrace)
+      echo("-----")
+      when T is string:
+        echo("Contents: ", future.value.repr)
+      echo("<----->")
+      echo("Future already finished, cannot finish twice.")
+      echo getStackTrace()
+      assert false
 
 proc complete*[T](future: PFuture[T], val: T) =
   ## Completes ``future`` with value ``val``.
@@ -88,6 +102,8 @@ proc fail*[T](future: PFuture[T], error: ref EBase) =
   checkFinished(future)
   future.finished = true
   future.error = error
+  future.errorStackTrace =
+    if getStackTrace(error) == "": getStackTrace() else: getStackTrace(error)
   if future.cb != nil:
     future.cb()
   else:
@@ -115,13 +131,24 @@ proc `callback=`*[T](future: PFuture[T],
   ## If future has already completed then ``cb`` will be called immediately.
   future.callback = proc () = cb(future)
 
+proc echoOriginalStackTrace[T](future: PFuture[T]) =
+  # TODO: Come up with something better.
+  when not defined(release):
+    echo("Original stack trace in ", future.fromProc, ":")
+    if not future.errorStackTrace.isNil() and future.errorStackTrace != "":
+      echo(future.errorStackTrace)
+    else:
+      echo("Empty or nil stack trace.")
+
 proc read*[T](future: PFuture[T]): T =
   ## Retrieves the value of ``future``. Future must be finished otherwise
   ## this function will fail with a ``EInvalidValue`` exception.
   ##
   ## If the result of the future is an error then that error will be raised.
   if future.finished:
-    if future.error != nil: raise future.error
+    if future.error != nil:
+      echoOriginalStackTrace(future)
+      raise future.error
     when T isnot void:
       return future.value
   else:
@@ -150,7 +177,44 @@ proc asyncCheck*[T](future: PFuture[T]) =
   ## This should be used instead of ``discard`` to discard void futures.
   future.callback =
     proc () =
-      if future.failed: raise future.error
+      if future.failed:
+        echoOriginalStackTrace(future)
+        raise future.error
+
+proc `and`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] =
+  ## Returns a future which will complete once both ``fut1`` and ``fut2``
+  ## complete.
+  var retFuture = newFuture[void]("asyncdispatch.`and`")
+  fut1.callback =
+    proc () =
+      if fut2.finished: retFuture.complete()
+  fut2.callback =
+    proc () =
+      if fut1.finished: retFuture.complete()
+  return retFuture
+
+proc `or`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] =
+  ## Returns a future which will complete once either ``fut1`` or ``fut2``
+  ## complete.
+  var retFuture = newFuture[void]("asyncdispatch.`or`")
+  proc cb() =
+    if not retFuture.finished: retFuture.complete()
+  fut1.callback = cb
+  fut2.callback = cb
+  return retFuture
+
+type
+  PDispatcherBase = ref object of PObject
+    timers: seq[tuple[finishAt: float, fut: PFuture[void]]]
+
+proc processTimers(p: PDispatcherBase) =
+  var oldTimers = p.timers
+  p.timers = @[]
+  for t in oldTimers:
+    if epochTime() >= t.finishAt:
+      t.fut.complete()
+    else:
+      p.timers.add(t)
 
 when defined(windows) or defined(nimdoc):
   import winlean, sets, hashes
@@ -162,7 +226,7 @@ when defined(windows) or defined(nimdoc):
       cb: proc (sock: TAsyncFD, bytesTransferred: DWORD,
                 errcode: TOSErrorCode) {.closure,gcsafe.}
 
-    PDispatcher* = ref object
+    PDispatcher* = ref object of PDispatcherBase
       ioPort: THandle
       handles: TSet[TAsyncFD]
 
@@ -181,6 +245,7 @@ when defined(windows) or defined(nimdoc):
     new result
     result.ioPort = CreateIOCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1)
     result.handles = initSet[TAsyncFD]()
+    result.timers = @[]
 
   var gDisp{.threadvar.}: PDispatcher ## Global dispatcher
   proc getGlobalDispatcher*(): PDispatcher =
@@ -207,8 +272,9 @@ when defined(windows) or defined(nimdoc):
   proc poll*(timeout = 500) =
     ## Waits for completion events and processes them.
     let p = getGlobalDispatcher()
-    if p.handles.len == 0:
-      raise newException(EInvalidValue, "No handles registered in dispatcher.")
+    if p.handles.len == 0 and p.timers.len == 0:
+      raise newException(EInvalidValue,
+        "No handles or timers registered in dispatcher.")
     
     let llTimeout =
       if timeout ==  -1: winlean.INFINITE
@@ -242,6 +308,9 @@ when defined(windows) or defined(nimdoc):
           discard
         else: osError(errCode)
 
+    # Timer processing.
+    processTimers(p)
+
   var connectExPtr: pointer = nil
   var acceptExPtr: pointer = nil
   var getAcceptExSockAddrsPtr: pointer = nil
@@ -314,7 +383,7 @@ when defined(windows) or defined(nimdoc):
     ## Returns a ``PFuture`` which will complete when the connection succeeds
     ## or an error occurs.
     verifyPresence(socket)
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("connect")
     # Apparently ``ConnectEx`` expects the socket to be initially bound:
     var saddr: Tsockaddr_in
     saddr.sin_family = int16(toInt(af))
@@ -384,7 +453,7 @@ when defined(windows) or defined(nimdoc):
     #     '\0' in the message currently signifies a socket disconnect. Who
     #     knows what will happen when someone sends that to our socket.
     verifyPresence(socket)
-    var retFuture = newFuture[string]()    
+    var retFuture = newFuture[string]("recv")
     var dataBuf: TWSABuf
     dataBuf.buf = cast[cstring](alloc0(size))
     dataBuf.len = size
@@ -405,7 +474,10 @@ when defined(windows) or defined(nimdoc):
               copyMem(addr data[0], addr dataBuf.buf[0], bytesCount)
               retFuture.complete($data)
           else:
-            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+            if flags.isDisconnectionError(errcode):
+              retFuture.complete("")
+            else:
+              retFuture.fail(newException(EOS, osErrorMsg(errcode)))
         if dataBuf.buf != nil:
           dealloc dataBuf.buf
           dataBuf.buf = nil
@@ -459,7 +531,7 @@ when defined(windows) or defined(nimdoc):
     ## Sends ``data`` to ``socket``. The returned future will complete once all
     ## data has been sent.
     verifyPresence(socket)
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("send")
 
     var dataBuf: TWSABuf
     dataBuf.buf = data # since this is not used in a callback, this is fine
@@ -474,7 +546,10 @@ when defined(windows) or defined(nimdoc):
           if errcode == TOSErrorCode(-1):
             retFuture.complete()
           else:
-            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+            if flags.isDisconnectionError(errcode):
+              retFuture.complete()
+            else:
+              retFuture.fail(newException(EOS, osErrorMsg(errcode)))
     )
 
     let ret = WSASend(socket.TSocketHandle, addr dataBuf, 1, addr bytesReceived,
@@ -494,15 +569,21 @@ when defined(windows) or defined(nimdoc):
       # free ``ol``.
     return retFuture
 
-  proc acceptAddr*(socket: TAsyncFD): 
+  proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}):
       PFuture[tuple[address: string, client: TAsyncFD]] =
     ## Accepts a new connection. Returns a future containing the client socket
     ## corresponding to that connection and the remote address of the client.
     ## The future will complete when the connection is successfully accepted.
     ##
-    ## The resulting client socket is automatically registered to dispatcher.
+    ## The resulting client socket is automatically registered to the
+    ## dispatcher.
+    ##
+    ## The ``accept`` call may result in an error if the connecting socket
+    ## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
+    ## flag is specified then this error will not be raised and instead
+    ## accept will be called again.
     verifyPresence(socket)
-    var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]()
+    var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]("acceptAddr")
 
     var clientSock = newRawSocket()
     if clientSock == osInvalidSocket: osError(osLastError())
@@ -534,6 +615,18 @@ when defined(windows) or defined(nimdoc):
          client: clientSock.TAsyncFD)
       )
 
+    template failAccept(errcode): stmt =
+      if flags.isDisconnectionError(errcode):
+        var newAcceptFut = acceptAddr(socket, flags)
+        newAcceptFut.callback =
+          proc () =
+            if newAcceptFut.failed:
+              retFuture.fail(newAcceptFut.readError)
+            else:
+              retFuture.complete(newAcceptFut.read)
+      else:
+        retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+
     var ol = PCustomOverlapped()
     GC_ref(ol)
     ol.data = TCompletionData(sock: socket, cb:
@@ -542,7 +635,7 @@ when defined(windows) or defined(nimdoc):
           if errcode == TOSErrorCode(-1):
             completeAccept()
           else:
-            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+            failAccept(errcode)
     )
 
     # http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
@@ -555,7 +648,7 @@ when defined(windows) or defined(nimdoc):
     if not ret:
       let err = osLastError()
       if err.int32 != ERROR_IO_PENDING:
-        retFuture.fail(newException(EOS, osErrorMsg(err)))
+        failAccept(err)
         GC_unref(ol)
     else:
       completeAccept()
@@ -606,7 +699,7 @@ else:
       readCBs: seq[TCallback]
       writeCBs: seq[TCallback]
 
-    PDispatcher* = ref object
+    PDispatcher* = ref object of PDispatcherBase
       selector: PSelector
 
   proc `==`*(x, y: TAsyncFD): bool {.borrow.}
@@ -614,6 +707,7 @@ else:
   proc newDispatcher*(): PDispatcher =
     new result
     result.selector = newSelector()
+    result.timers = @[]
 
   var gDisp{.threadvar.}: PDispatcher ## Global dispatcher
   proc getGlobalDispatcher*(): PDispatcher =
@@ -693,10 +787,12 @@ else:
       else:
         # FD no longer a part of the selector. Likely been closed
         # (e.g. socket disconnected).
+
+    processTimers(p)
   
   proc connect*(socket: TAsyncFD, address: string, port: TPort,
     af = AF_INET): PFuture[void] =
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("connect")
     
     proc cb(sock: TAsyncFD): bool =
       # We have connected.
@@ -731,7 +827,7 @@ else:
 
   proc recv*(socket: TAsyncFD, size: int,
              flags = {TSocketFlags.SafeDisconn}): PFuture[string] =
-    var retFuture = newFuture[string]()
+    var retFuture = newFuture[string]("recv")
     
     var readBuffer = newString(size)
 
@@ -762,7 +858,7 @@ else:
 
   proc send*(socket: TAsyncFD, data: string,
              flags = {TSocketFlags.SafeDisconn}): PFuture[void] =
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("send")
     
     var written = 0
     
@@ -792,9 +888,10 @@ else:
     addWrite(socket, cb)
     return retFuture
 
-  proc acceptAddr*(socket: TAsyncFD): 
+  proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}):
       PFuture[tuple[address: string, client: TAsyncFD]] =
-    var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]()
+    var retFuture = newFuture[tuple[address: string,
+        client: TAsyncFD]]("acceptAddr")
     proc cb(sock: TAsyncFD): bool =
       result = true
       var sockAddress: Tsockaddr_in
@@ -807,19 +904,31 @@ else:
         if lastError.int32 == EINTR:
           return false
         else:
-          retFuture.fail(newException(EOS, osErrorMsg(lastError)))
+          if flags.isDisconnectionError(lastError):
+            return false
+          else:
+            retFuture.fail(newException(EOS, osErrorMsg(lastError)))
       else:
         register(client.TAsyncFD)
         retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client.TAsyncFD))
     addRead(socket, cb)
     return retFuture
 
-proc accept*(socket: TAsyncFD): PFuture[TAsyncFD] =
+proc sleepAsync*(ms: int): PFuture[void] =
+  ## Suspends the execution of the current async procedure for the next
+  ## ``ms`` miliseconds.
+  var retFuture = newFuture[void]("sleepAsync")
+  let p = getGlobalDispatcher()
+  p.timers.add((epochTime() + (ms / 1000), retFuture))
+  return retFuture
+
+proc accept*(socket: TAsyncFD,
+    flags = {TSocketFlags.SafeDisconn}): PFuture[TAsyncFD] =
   ## Accepts a new connection. Returns a future containing the client socket
   ## corresponding to that connection.
   ## The future will complete when the connection is successfully accepted.
-  var retFut = newFuture[TAsyncFD]()
-  var fut = acceptAddr(socket)
+  var retFut = newFuture[TAsyncFD]("accept")
+  var fut = acceptAddr(socket, flags)
   fut.callback =
     proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
       assert future.finished
@@ -845,11 +954,16 @@ template createCb*(retFutureSym, iteratorNameSym,
         else:
           next.callback = cb
     except:
-      retFutureSym.fail(getCurrentException())
+      if retFutureSym.finished:
+        # Take a look at tasyncexceptions for the bug which this fixes.
+        # That test explains it better than I can here.
+        raise
+      else:
+        retFutureSym.fail(getCurrentException())
   cb()
   #{.pop.}
 proc generateExceptionCheck(futSym,
-    exceptBranch, rootReceiver: PNimrodNode): PNimrodNode {.compileTime.} =
+    exceptBranch, rootReceiver, fromNode: PNimrodNode): PNimrodNode {.compileTime.} =
   if exceptBranch == nil:
     result = rootReceiver
   else:
@@ -869,20 +983,21 @@ proc generateExceptionCheck(futSym,
            )
          )
       )
-    let elseNode = newNimNode(nnkElse)
-    elseNode.add newNimNode(nnkStmtList)
+    let elseNode = newNimNode(nnkElse, fromNode)
+    elseNode.add newNimNode(nnkStmtList, fromNode)
     elseNode[0].add rootReceiver
     result.add elseNode
 
 template createVar(result: var PNimrodNode, futSymName: string,
                    asyncProc: PNimrodNode,
-                   valueReceiver, rootReceiver: expr) =
-  result = newNimNode(nnkStmtList)
+                   valueReceiver, rootReceiver: expr,
+                   fromNode: PNimrodNode) =
+  result = newNimNode(nnkStmtList, fromNode)
   var futSym = genSym(nskVar, "future")
   result.add newVarStmt(futSym, asyncProc) # -> var future = y
-  result.add newNimNode(nnkYieldStmt).add(futSym) # -> yield future
+  result.add newNimNode(nnkYieldStmt, fromNode).add(futSym) # -> yield future
   valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future.read
-  result.add generateExceptionCheck(futSym, exceptBranch, rootReceiver)
+  result.add generateExceptionCheck(futSym, exceptBranch, rootReceiver, fromNode)
 
 proc processBody(node, retFutureSym: PNimrodNode,
                  subTypeIsVoid: bool,
@@ -891,7 +1006,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
   result = node
   case node.kind
   of nnkReturnStmt:
-    result = newNimNode(nnkStmtList)
+    result = newNimNode(nnkStmtList, node)
     if node[0].kind == nnkEmpty:
       if not subtypeIsVoid:
         result.add newCall(newIdentNode("complete"), retFutureSym,
@@ -902,36 +1017,36 @@ proc processBody(node, retFutureSym: PNimrodNode,
       result.add newCall(newIdentNode("complete"), retFutureSym,
         node[0].processBody(retFutureSym, subtypeIsVoid, exceptBranch))
 
-    result.add newNimNode(nnkReturnStmt).add(newNilLit())
+    result.add newNimNode(nnkReturnStmt, node).add(newNilLit())
     return # Don't process the children of this return stmt
-  of nnkCommand:
+  of nnkCommand, nnkCall:
     if node[0].kind == nnkIdent and node[0].ident == !"await":
       case node[1].kind
-      of nnkIdent:
+      of nnkIdent, nnkInfix:
         # await x
-        result = newNimNode(nnkYieldStmt).add(node[1]) # -> yield x
-      of nnkCall:
+        result = newNimNode(nnkYieldStmt, node).add(node[1]) # -> yield x
+      of nnkCall, nnkCommand:
         # await foo(p, x)
         var futureValue: PNimrodNode
         result.createVar("future" & $node[1][0].toStrLit, node[1], futureValue,
-                  futureValue)
+                  futureValue, node)
       else:
         error("Invalid node kind in 'await', got: " & $node[1].kind)
-    elif node[1].kind == nnkCommand and node[1][0].kind == nnkIdent and
-         node[1][0].ident == !"await":
+    elif node.len > 1 and node[1].kind == nnkCommand and
+         node[1][0].kind == nnkIdent and node[1][0].ident == !"await":
       # foo await x
       var newCommand = node
       result.createVar("future" & $node[0].toStrLit, node[1][1], newCommand[1],
-                newCommand)
+                newCommand, node)
 
   of nnkVarSection, nnkLetSection:
     case node[0][2].kind
     of nnkCommand:
-      if node[0][2][0].ident == !"await":
+      if node[0][2][0].kind == nnkIdent and node[0][2][0].ident == !"await":
         # var x = await y
         var newVarSection = node # TODO: Should this use copyNimNode?
         result.createVar("future" & $node[0][0].ident, node[0][2][1],
-          newVarSection[0][2], newVarSection)
+          newVarSection[0][2], newVarSection, node)
     else: discard
   of nnkAsgn:
     case node[1].kind
@@ -939,7 +1054,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
       if node[1][0].ident == !"await":
         # x = await y
         var newAsgn = node
-        result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn)
+        result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn, node)
     else: discard
   of nnkDiscardStmt:
     # discard await x
@@ -947,10 +1062,10 @@ proc processBody(node, retFutureSym: PNimrodNode,
           node[0][0].ident == !"await":
       var newDiscard = node
       result.createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1],
-                newDiscard[0], newDiscard)
+                newDiscard[0], newDiscard, node)
   of nnkTryStmt:
     # try: await x; except: ...
-    result = newNimNode(nnkStmtList)
+    result = newNimNode(nnkStmtList, node)
     proc processForTry(n: PNimrodNode, i: var int,
                        res: PNimrodNode): bool {.compileTime.} =
       result = false
@@ -1009,7 +1124,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
         (returnType.kind == nnkBracketExpr and
          returnType[1].kind == nnkIdent and returnType[1].ident == !"void")
 
-  var outerProcBody = newNimNode(nnkStmtList)
+  var outerProcBody = newNimNode(nnkStmtList, prc[6])
 
   # -> var retFuture = newFuture[T]()
   var retFutureSym = genSym(nskVar, "retFuture")
@@ -1019,9 +1134,10 @@ macro async*(prc: stmt): stmt {.immediate.} =
   outerProcBody.add(
     newVarStmt(retFutureSym, 
       newCall(
-        newNimNode(nnkBracketExpr).add(
+        newNimNode(nnkBracketExpr, prc[6]).add(
           newIdentNode(!"newFuture"), # TODO: Strange bug here? Remove the `!`.
-          subRetType)))) # Get type from return type of this proc
+          subRetType),
+      newLit(prc[0].getName)))) # Get type from return type of this proc
   
   # -> iterator nameIter(): PFutureBase {.closure.} = 
   # ->   var result: T
@@ -1030,7 +1146,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   var iteratorNameSym = genSym(nskIterator, $prc[0].getName & "Iter")
   var procBody = prc[6].processBody(retFutureSym, subtypeIsVoid, nil)
   if not subtypeIsVoid:
-    procBody.insert(0, newNimNode(nnkVarSection).add(
+    procBody.insert(0, newNimNode(nnkVarSection, prc[6]).add(
       newIdentDefs(newIdentNode("result"), returnType[1]))) # -> var result: T
     procBody.add(
       newCall(newIdentNode("complete"),
@@ -1041,7 +1157,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   
   var closureIterator = newProc(iteratorNameSym, [newIdentNode("PFutureBase")],
                                 procBody, nnkIteratorDef)
-  closureIterator[4] = newNimNode(nnkPragma).add(newIdentNode("closure"))
+  closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure"))
   outerProcBody.add(closureIterator)
 
   # -> createCb(retFuture)
@@ -1051,7 +1167,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   outerProcBody.add procCb
 
   # -> return retFuture
-  outerProcBody.add newNimNode(nnkReturnStmt).add(retFutureSym)
+  outerProcBody.add newNimNode(nnkReturnStmt, prc[6][prc[6].len-1]).add(retFutureSym)
   
   result = prc
 
@@ -1068,8 +1184,8 @@ macro async*(prc: stmt): stmt {.immediate.} =
   result[6] = outerProcBody
 
   #echo(treeRepr(result))
-  #if prc[0].getName == "routeReq":
-  #echo(toStrLit(result))
+  #if prc[0].getName == "getFile":
+  #  echo(toStrLit(result))
 
 proc recvLine*(socket: TAsyncFD): PFuture[string] {.async.} =
   ## Reads a line of data from ``socket``. Returned future will complete once
@@ -1110,3 +1226,11 @@ proc runForever*() =
   ## Begins a never ending global dispatcher poll loop.
   while true:
     poll()
+
+proc waitFor*[T](fut: PFuture[T]) =
+  ## **Blocks** the current thread until the specified future completes.
+  while not fut.finished:
+    poll()
+
+  if fut.failed:
+    raise fut.error
diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim
new file mode 100644
index 0000000000..f1b1d14006
--- /dev/null
+++ b/lib/pure/asyncftpclient.nim
@@ -0,0 +1,295 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Dominik Picheta
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+import asyncdispatch, asyncnet, strutils, parseutils, os, times
+
+from ftpclient import TFtpBase, EInvalidReply, TFtpEvent
+from net import bufferSize
+
+type
+  TAsyncFtpClient* = TFtpBase[PAsyncSocket]
+  PAsyncFtpClient* = ref TAsyncFtpClient
+
+  ProgressChangedProc* =
+    proc (total, progress: BiggestInt, speed: float):
+      PFuture[void] {.closure, gcsafe.}
+
+proc expectReply(ftp: PAsyncFtpClient): PFuture[TaintedString] =
+  result = ftp.csock.recvLine()
+
+proc send*(ftp: PAsyncFtpClient, m: string): PFuture[TaintedString] {.async.} =
+  ## Send a message to the server, and wait for a primary reply.
+  ## ``\c\L`` is added for you.
+  await ftp.csock.send(m & "\c\L")
+  return await ftp.expectReply()
+
+proc assertReply(received: TaintedString, expected: varargs[string]) =
+  for i in items(expected):
+    if received.string.startsWith(i): return
+  raise newException(EInvalidReply,
+                     "Expected reply '$1' got: $2" %
+                     [expected.join("' or '"), received.string])
+
+proc pasv(ftp: PAsyncFtpClient) {.async.} =
+  ## Negotiate a data connection.
+  ftp.dsock = newAsyncSocket()
+
+  var pasvMsg = (await ftp.send("PASV")).string.strip.TaintedString
+  assertReply(pasvMsg, "227")
+  var betweenParens = captureBetween(pasvMsg.string, '(', ')')
+  var nums = betweenParens.split(',')
+  var ip = nums[0.. -3]
+  var port = nums[-2.. -1]
+  var properPort = port[0].parseInt()*256+port[1].parseInt()
+  await ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
+  ftp.dsockConnected = True
+
+proc normalizePathSep(path: string): string =
+  return replace(path, '\\', '/')
+
+proc connect*(ftp: PAsyncFtpClient) {.async.} =
+  ## Connect to the FTP server specified by ``ftp``.
+  await ftp.csock.connect(ftp.address, ftp.port)
+
+  var reply = await ftp.expectReply()
+  if reply.startsWith("120"):
+    # 120 Service ready in nnn minutes.
+    # We wait until we receive 220.
+    reply = await ftp.expectReply()
+  assertReply(reply, "220")
+
+  if ftp.user != "":
+    assertReply(await(ftp.send("USER " & ftp.user)), "230", "331")
+
+  if ftp.pass != "":
+    assertReply(await(ftp.send("PASS " & ftp.pass)), "230")
+
+proc pwd*(ftp: PAsyncFtpClient): PFuture[TaintedString] {.async.} =
+  ## Returns the current working directory.
+  let wd = await ftp.send("PWD")
+  assertReply wd, "257"
+  return wd.string.captureBetween('"').TaintedString # "
+
+proc cd*(ftp: PAsyncFtpClient, dir: string) {.async.} =
+  ## Changes the current directory on the remote FTP server to ``dir``.
+  assertReply(await(ftp.send("CWD " & dir.normalizePathSep)), "250")
+
+proc cdup*(ftp: PAsyncFtpClient) {.async.} =
+  ## Changes the current directory to the parent of the current directory.
+  assertReply(await(ftp.send("CDUP")), "200")
+
+proc getLines(ftp: PAsyncFtpClient): PFuture[string] {.async.} =
+  ## Downloads text data in ASCII mode
+  result = ""
+  assert ftp.dsockConnected
+  while ftp.dsockConnected:
+    let r = await ftp.dsock.recvLine()
+    if r.string == "":
+      ftp.dsockConnected = false
+    else:
+      result.add(r.string & "\n")
+
+  assertReply(await(ftp.expectReply()), "226")
+
+proc listDirs*(ftp: PAsyncFtpClient, dir = ""): PFuture[seq[string]] {.async.} =
+  ## Returns a list of filenames in the given directory. If ``dir`` is "",
+  ## the current directory is used. If ``async`` is true, this
+  ## function will return immediately and it will be your job to
+  ## use asyncio's ``poll`` to progress this operation.
+  await ftp.pasv()
+
+  assertReply(await(ftp.send("NLST " & dir.normalizePathSep)), ["125", "150"])
+
+  result = splitLines(await ftp.getLines())
+
+proc existsFile*(ftp: PAsyncFtpClient, file: string): PFuture[bool] {.async.} =
+  ## Determines whether ``file`` exists.
+  var files = await ftp.listDirs()
+  for f in items(files):
+    if f.normalizePathSep == file.normalizePathSep: return true
+
+proc createDir*(ftp: PAsyncFtpClient, dir: string, recursive = false){.async.} =
+  ## Creates a directory ``dir``. If ``recursive`` is true, the topmost
+  ## subdirectory of ``dir`` will be created first, following the secondmost...
+  ## etc. this allows you to give a full path as the ``dir`` without worrying
+  ## about subdirectories not existing.
+  if not recursive:
+    assertReply(await(ftp.send("MKD " & dir.normalizePathSep)), "257")
+  else:
+    var reply = TaintedString""
+    var previousDirs = ""
+    for p in split(dir, {os.dirSep, os.altSep}):
+      if p != "":
+        previousDirs.add(p)
+        reply = await ftp.send("MKD " & previousDirs)
+        previousDirs.add('/')
+    assertReply reply, "257"
+
+proc chmod*(ftp: PAsyncFtpClient, path: string,
+            permissions: set[TFilePermission]) {.async.} =
+  ## Changes permission of ``path`` to ``permissions``.
+  var userOctal = 0
+  var groupOctal = 0
+  var otherOctal = 0
+  for i in items(permissions):
+    case i
+    of fpUserExec: userOctal.inc(1)
+    of fpUserWrite: userOctal.inc(2)
+    of fpUserRead: userOctal.inc(4)
+    of fpGroupExec: groupOctal.inc(1)
+    of fpGroupWrite: groupOctal.inc(2)
+    of fpGroupRead: groupOctal.inc(4)
+    of fpOthersExec: otherOctal.inc(1)
+    of fpOthersWrite: otherOctal.inc(2)
+    of fpOthersRead: otherOctal.inc(4)
+
+  var perm = $userOctal & $groupOctal & $otherOctal
+  assertReply(await(ftp.send("SITE CHMOD " & perm &
+                    " " & path.normalizePathSep)), "200")
+
+proc list*(ftp: PAsyncFtpClient, dir = ""): PFuture[string] {.async.} =
+  ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current
+  ## working directory.
+  await ftp.pasv()
+
+  let reply = await ftp.send("LIST" & " " & dir.normalizePathSep)
+  assertReply(reply, ["125", "150"])
+
+  result = await ftp.getLines()
+
+proc retrText*(ftp: PAsyncFtpClient, file: string): PFuture[string] {.async.} =
+  ## Retrieves ``file``. File must be ASCII text.
+  await ftp.pasv()
+  let reply = await ftp.send("RETR " & file.normalizePathSep)
+  assertReply(reply, ["125", "150"])
+
+  result = await ftp.getLines()
+
+proc getFile(ftp: PAsyncFtpClient, file: TFile, total: BiggestInt,
+             onProgressChanged: ProgressChangedProc) {.async.} =
+  assert ftp.dsockConnected
+  var progress = 0
+  var progressInSecond = 0
+  var countdownFut = sleepAsync(1000)
+  var dataFut = ftp.dsock.recv(bufferSize)
+  while ftp.dsockConnected:
+    await dataFut or countdownFut
+    if countdownFut.finished:
+      asyncCheck onProgressChanged(total, progress,
+          progressInSecond.float)
+      progressInSecond = 0
+      countdownFut = sleepAsync(1000)
+
+    if dataFut.finished:
+      let data = dataFut.read
+      if data != "":
+        progress.inc(data.len)
+        progressInSecond.inc(data.len)
+        file.write(data)
+        dataFut = ftp.dsock.recv(bufferSize)
+      else:
+        ftp.dsockConnected = False
+
+  assertReply(await(ftp.expectReply()), "226")
+
+proc defaultOnProgressChanged*(total, progress: BiggestInt,
+    speed: float): PFuture[void] {.nimcall,gcsafe.} =
+  ## Default FTP ``onProgressChanged`` handler. Does nothing.
+  result = newFuture[void]()
+  #echo(total, " ", progress, " ", speed)
+  result.complete()
+
+proc retrFile*(ftp: PAsyncFtpClient, file, dest: string,
+               onProgressChanged = defaultOnProgressChanged) {.async.} =
+  ## Downloads ``file`` and saves it to ``dest``.
+  ## The ``EvRetr`` event is passed to the specified ``handleEvent`` function
+  ## when the download is finished. The event's ``filename`` field will be equal
+  ## to ``file``.
+  var destFile = open(dest, mode = fmWrite)
+  await ftp.pasv()
+  var reply = await ftp.send("RETR " & file.normalizePathSep)
+  assertReply reply, ["125", "150"]
+  if {'(', ')'} notin reply.string:
+    raise newException(EInvalidReply, "Reply has no file size.")
+  var fileSize: biggestInt
+  if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0:
+    raise newException(EInvalidReply, "Reply has no file size.")
+
+  await getFile(ftp, destFile, fileSize, onProgressChanged)
+
+proc doUpload(ftp: PAsyncFtpClient, file: TFile,
+              onProgressChanged: ProgressChangedProc) {.async.} =
+  assert ftp.dsockConnected
+
+  let total = file.getFileSize()
+  var data = newStringOfCap(4000)
+  var progress = 0
+  var progressInSecond = 0
+  var countdownFut = sleepAsync(1000)
+  var sendFut: PFuture[void] = nil
+  while ftp.dsockConnected:
+    if sendFut == nil or sendFut.finished:
+      progress.inc(data.len)
+      progressInSecond.inc(data.len)
+      # TODO: Async file reading.
+      let len = file.readBuffer(addr(data[0]), 4000)
+      setLen(data, len)
+      if len == 0:
+        # File finished uploading.
+        ftp.dsock.close()
+        ftp.dsockConnected = false
+
+        assertReply(await(ftp.expectReply()), "226")
+      else:
+        sendFut = ftp.dsock.send(data)
+
+    if countdownFut.finished:
+      asyncCheck onProgressChanged(total, progress, progressInSecond.float)
+      progressInSecond = 0
+      countdownFut = sleepAsync(1000)
+
+    await countdownFut or sendFut
+
+proc storeFile*(ftp: PAsyncFtpClient, file, dest: string,
+            onProgressChanged = defaultOnProgressChanged) {.async.} =
+  ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this
+  ## function asynchronously is recommended to view the progress of
+  ## the download.
+  ## The ``EvStore`` event is passed to the specified ``handleEvent`` function
+  ## when the upload is finished, and the ``filename`` field will be
+  ## equal to ``file``.
+  var destFile = open(file)
+  await ftp.pasv()
+
+  let reply = await ftp.send("STOR " & dest.normalizePathSep)
+  assertReply reply, ["125", "150"]
+
+  await doUpload(ftp, destFile, onProgressChanged)
+
+proc newAsyncFtpClient*(address: string, port = TPort(21),
+    user, pass = ""): PAsyncFtpClient =
+  ## Creates a new ``PAsyncFtpClient`` object.
+  new result
+  result.user = user
+  result.pass = pass
+  result.address = address
+  result.port = port
+  result.dsockConnected = false
+  result.csock = newAsyncSocket()
+
+when isMainModule:
+  var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
+  proc main(ftp: PAsyncFtpClient) {.async.} =
+    await ftp.connect()
+    echo await ftp.pwd()
+    echo await ftp.listDirs()
+    await ftp.storeFile("payload.jpg", "payload.jpg")
+    await ftp.retrFile("payload.jpg", "payload2.jpg")
+    echo("Finished")
+
+  waitFor main(ftp)
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index ee6658fd1f..c8bd5cfc13 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -11,14 +11,14 @@
 ##
 ## **Note:** This module is still largely experimental.
 
-import strtabs, asyncnet, asyncdispatch, parseutils, parseurl, strutils
+import strtabs, asyncnet, asyncdispatch, parseutils, uri, strutils
 type
   TRequest* = object
     client*: PAsyncSocket # TODO: Separate this into a Response object?
     reqMethod*: string
     headers*: PStringTable
     protocol*: tuple[orig: string, major, minor: int]
-    url*: TURL
+    url*: TUri
     hostname*: string ## The hostname of the client that made the request.
     body*: string
 
@@ -97,7 +97,8 @@ proc sendStatus(client: PAsyncSocket, status: string): PFuture[void] =
   client.send("HTTP/1.1 " & status & "\c\L")
 
 proc processClient(client: PAsyncSocket, address: string,
-                 callback: proc (request: TRequest): PFuture[void]) {.async.} =
+                   callback: proc (request: TRequest):
+                      PFuture[void] {.closure, gcsafe.}) {.async.} =
   while true:
     # GET /path HTTP/1.1
     # Header: val
@@ -135,7 +136,7 @@ proc processClient(client: PAsyncSocket, address: string,
       request.headers[kv.key] = kv.value
 
     request.reqMethod = reqMethod
-    request.url = parseUrl(path)
+    request.url = parseUri(path)
     try:
       request.protocol = protocol.parseProtocol()
     except EInvalidValue:
@@ -184,7 +185,7 @@ proc processClient(client: PAsyncSocket, address: string,
       break
 
 proc serve*(server: PAsyncHttpServer, port: TPort,
-            callback: proc (request: TRequest): PFuture[void],
+            callback: proc (request: TRequest): PFuture[void] {.closure,gcsafe.},
             address = "") {.async.} =
   ## Starts the process of listening for incoming HTTP connections on the
   ## specified address and port.
@@ -199,19 +200,23 @@ proc serve*(server: PAsyncHttpServer, port: TPort,
     #var (address, client) = await server.socket.acceptAddr()
     var fut = await server.socket.acceptAddr()
     asyncCheck processClient(fut.client, fut.address, callback)
+    #echo(f.isNil)
+    #echo(f.repr)
 
 proc close*(server: PAsyncHttpServer) =
   ## Terminates the async http server instance.
   server.socket.close()
 
 when isMainModule:
-  var server = newAsyncHttpServer()
-  proc cb(req: TRequest) {.async.} =
-    #echo(req.reqMethod, " ", req.url)
-    #echo(req.headers)
-    let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT",
-        "Content-type": "text/plain; charset=utf-8"}
-    await req.respond(Http200, "Hello World", headers.newStringTable())
+  proc main =
+    var server = newAsyncHttpServer()
+    proc cb(req: TRequest) {.async.} =
+      #echo(req.reqMethod, " ", req.url)
+      #echo(req.headers)
+      let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT",
+          "Content-type": "text/plain; charset=utf-8"}
+      await req.respond(Http200, "Hello World", headers.newStringTable())
 
-  asyncCheck server.serve(TPort(5555), cb)
-  runForever()
+    asyncCheck server.serve(TPort(5555), cb)
+    runForever()
+  main()
diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim
index c68ca4350e..6b67bf4b5a 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/pure/asyncio.nim
@@ -671,25 +671,26 @@ when isMainModule:
         testRead(s, 2)
     disp.register(client)
 
-  var d = newDispatcher()
-  
-  var s = AsyncSocket()
-  s.connect("amber.tenthbit.net", TPort(6667))
-  s.handleConnect = 
-    proc (s: PAsyncSocket) =
-      testConnect(s, 1)
-  s.handleRead = 
-    proc (s: PAsyncSocket) =
-      testRead(s, 1)
-  d.register(s)
-  
-  var server = AsyncSocket()
-  server.handleAccept =
-    proc (s: PAsyncSocket) = 
-      testAccept(s, d, 78)
-  server.bindAddr(TPort(5555))
-  server.listen()
-  d.register(server)
-  
-  while d.poll(-1): discard
+  proc main =
+    var d = newDispatcher()
     
+    var s = AsyncSocket()
+    s.connect("amber.tenthbit.net", TPort(6667))
+    s.handleConnect = 
+      proc (s: PAsyncSocket) =
+        testConnect(s, 1)
+    s.handleRead = 
+      proc (s: PAsyncSocket) =
+        testRead(s, 1)
+    d.register(s)
+    
+    var server = AsyncSocket()
+    server.handleAccept =
+      proc (s: PAsyncSocket) = 
+        testAccept(s, d, 78)
+    server.bindAddr(TPort(5555))
+    server.listen()
+    d.register(server)
+    
+    while d.poll(-1): discard
+  main()
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index 374ac77e31..5095d94613 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -36,9 +36,9 @@
 ##       let client = await server.accept()
 ##       clients.add client
 ##
-##       processClient(client)
+##       asyncCheck processClient(client)
 ##
-##   serve()
+##   asyncCheck serve()
 ##   runForever()
 ##
 ##
@@ -135,13 +135,13 @@ proc send*(socket: PAsyncSocket, data: string,
   assert socket != nil
   result = send(socket.fd.TAsyncFD, data, flags)
 
-proc acceptAddr*(socket: PAsyncSocket): 
+proc acceptAddr*(socket: PAsyncSocket, flags = {TSocketFlags.SafeDisconn}):
       PFuture[tuple[address: string, client: PAsyncSocket]] =
   ## Accepts a new connection. Returns a future containing the client socket
   ## corresponding to that connection and the remote address of the client.
   ## The future will complete when the connection is successfully accepted.
-  var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]()
-  var fut = acceptAddr(socket.fd.TAsyncFD)
+  var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]("asyncnet.acceptAddr")
+  var fut = acceptAddr(socket.fd.TAsyncFD, flags)
   fut.callback =
     proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
       assert future.finished
@@ -153,12 +153,13 @@ proc acceptAddr*(socket: PAsyncSocket):
         retFuture.complete(resultTup)
   return retFuture
 
-proc accept*(socket: PAsyncSocket): PFuture[PAsyncSocket] =
+proc accept*(socket: PAsyncSocket,
+    flags = {TSocketFlags.SafeDisconn}): PFuture[PAsyncSocket] =
   ## Accepts a new connection. Returns a future containing the client socket
   ## corresponding to that connection.
   ## The future will complete when the connection is successfully accepted.
-  var retFut = newFuture[PAsyncSocket]()
-  var fut = acceptAddr(socket)
+  var retFut = newFuture[PAsyncSocket]("asyncnet.accept")
+  var fut = acceptAddr(socket, flags)
   fut.callback =
     proc (future: PFuture[tuple[address: string, client: PAsyncSocket]]) =
       assert future.finished
diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim
index 4e59a6ca63..7b3b0e6f5a 100644
--- a/lib/pure/base64.nim
+++ b/lib/pure/base64.nim
@@ -58,7 +58,7 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat
     if r+4 != result.len:
       setLen(result, r+4)
   else:
-    assert(r == result.len)
+    #assert(r == result.len)
 
 proc encode*[T:TInteger|char](s: openarray[T], lineLen = 75, newLine="\13\10"): string = 
   ## encodes `s` into base64 representation. After `lineLen` characters, a 
diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim
index 40a02b6511..1fde1f4193 100644
--- a/lib/pure/collections/critbits.nim
+++ b/lib/pure/collections/critbits.nim
@@ -131,7 +131,7 @@ proc `[]=`*[T](c: var TCritBitTree[T], key: string, val: T) =
   var n = rawInsert(c, key)
   n.val = val
 
-proc `[]`*[T](c: var TCritBitTree[T], key: string): T {.inline.} =
+proc `[]`*[T](c: TCritBitTree[T], key: string): T {.inline.} =
   ## retrieves the value at ``c[key]``. If `key` is not in `t`,
   ## default empty value for the type `B` is returned
   ## and no exception is raised. One can check with ``hasKey`` whether the key
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index e760c5e02b..2629e9f407 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -186,7 +186,7 @@ proc keepIf*[T](seq1: var seq[T], pred: proc(item: T): bool {.closure.}) =
   ##
   ## .. code-block:: nimrod
   ##   var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1]
-  ##   filter(floats, proc(x: float): bool = x > 10)
+  ##   keepIf(floats, proc(x: float): bool = x > 10)
   ##   assert floats == @[13.0, 12.5, 10.1]
   var pos = 0
   for i in 0 .. `_. Sets allow you to store any value that can be
+## `hashed `_ and they don't contain duplicate entries.
+##
 ## **Note**: The data types declared here have *value semantics*: This means
 ## that ``=`` performs a copy of the set.
 
@@ -23,20 +27,69 @@ type
   TSlotEnum = enum seEmpty, seFilled, seDeleted
   TKeyValuePair[A] = tuple[slot: TSlotEnum, key: A]
   TKeyValuePairSeq[A] = seq[TKeyValuePair[A]]
-  TSet* {.final, myShallow.}[A] = object ## a generic hash set
+  TSet* {.final, myShallow.}[A] = object ## \
+    ## A generic hash set.
+    ##
+    ## Use `init() <#init,TSet[A],int>`_ or `initSet[type]() <#initSet>`_
+    ## before calling other procs on it.
     data: TKeyValuePairSeq[A]
     counter: int
 
+proc isValid*[A](s: TSet[A]): bool =
+  ## Returns `true` if the set has been initialized with `initSet <#initSet>`_.
+  ##
+  ## Most operations over an uninitialized set will crash at runtime and
+  ## `assert `_ in debug builds. You can use this proc in
+  ## your own procs to verify that sets passed to your procs are correctly
+  ## initialized. Example:
+  ##
+  ## .. code-block :: nimrod
+  ##   proc savePreferences(options: TSet[string]) =
+  ##     assert options.isValid, "Pass an initialized set!"
+  ##     # Do stuff here, may crash in release builds!
+  result = not s.data.isNil
+
 proc len*[A](s: TSet[A]): int =
-  ## returns the number of keys in `s`.
+  ## Returns the number of keys in `s`.
+  ##
+  ## Due to an implementation detail you can call this proc on variables which
+  ## have not been initialized yet. The proc will return zero as the length
+  ## then. Example:
+  ##
+  ## .. code-block::
+  ##
+  ##   var values: TSet[int]
+  ##   assert(not values.isValid)
+  ##   assert values.len == 0
   result = s.counter
 
 proc card*[A](s: TSet[A]): int =
-  ## alias for `len`.
+  ## Alias for `len() <#len,TSet[A]>`_.
+  ##
+  ## Card stands for the `cardinality
+  ## `_ of a set.
   result = s.counter
 
 iterator items*[A](s: TSet[A]): A =
-  ## iterates over any key in the table `t`.
+  ## Iterates over keys in the set `s`.
+  ##
+  ## If you need a sequence with the keys you can use `sequtils.toSeq()
+  ## `_ on the iterator. Usage example:
+  ##
+  ## .. code-block::
+  ##   type
+  ##     pair = tuple[a, b: int]
+  ##   var
+  ##     a, b = initSet[pair]()
+  ##   a.incl((2, 3))
+  ##   a.incl((3, 2))
+  ##   a.incl((2, 3))
+  ##   for x, y in a.items:
+  ##     b.incl((x - 2, y + 1))
+  ##   assert a.len == 2
+  ##   echo b
+  ##   # --> {(a: 1, b: 3), (a: 0, b: 4)}
+  assert s.isValid, "The set needs to be initialized."
   for h in 0..high(s.data):
     if s.data[h].slot == seFilled: yield s.data[h].key
 
@@ -73,12 +126,24 @@ proc mget*[A](s: var TSet[A], key: A): var A =
   ## value as 'key' or raises the ``EInvalidKey`` exception. This is useful
   ## when one overloaded 'hash' and '==' but still needs reference semantics
   ## for sharing.
+  assert s.isValid, "The set needs to be initialized."
   var index = rawGet(s, key)
-  if index >= 0: result = t.data[index].key
+  if index >= 0: result = s.data[index].key
   else: raise newException(EInvalidKey, "key not found: " & $key)
 
 proc contains*[A](s: TSet[A], key: A): bool =
-  ## returns true iff `key` is in `s`.
+  ## Returns true iff `key` is in `s`.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var values = initSet[int]()
+  ##   assert(not values.contains(2))
+  ##   values.incl(2)
+  ##   assert values.contains(2)
+  ##   values.excl(2)
+  ##   assert(not values.contains(2))
+  assert s.isValid, "The set needs to be initialized."
   var index = rawGet(s, key)
   result = index >= 0
 
@@ -109,38 +174,124 @@ template containsOrInclImpl() {.dirty.} =
     inc(s.counter)
 
 proc incl*[A](s: var TSet[A], key: A) =
-  ## includes an element `key` in `s`.
+  ## Includes an element `key` in `s`.
+  ##
+  ## This doesn't do anything if `key` is already in `s`. Example:
+  ##
+  ## .. code-block::
+  ##   var values = initSet[int]()
+  ##   values.incl(2)
+  ##   values.incl(2)
+  ##   assert values.len == 1
+  assert s.isValid, "The set needs to be initialized."
   inclImpl()
 
 proc incl*[A](s: var TSet[A], other: TSet[A]) =
-  ## includes everything in `other` in `s`
+  ## Includes all elements from `other` into `s`.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var values = initSet[int]()
+  ##   values.incl(2)
+  ##   var others = toSet([6, 7])
+  ##   values.incl(others)
+  ##   assert values.len == 3
+  assert s.isValid, "The set `s` needs to be initialized."
+  assert other.isValid, "The set `other` needs to be initialized."
   for item in other: incl(s, item)
 
 proc excl*[A](s: var TSet[A], key: A) =
-  ## excludes `key` from the set `s`.
+  ## Excludes `key` from the set `s`.
+  ##
+  ## This doesn't do anything if `key` is not found in `s`. Example:
+  ##
+  ## .. code-block::
+  ##   var s = toSet([2, 3, 6, 7])
+  ##   s.excl(2)
+  ##   s.excl(2)
+  ##   assert s.len == 3
+  assert s.isValid, "The set needs to be initialized."
   var index = rawGet(s, key)
   if index >= 0:
     s.data[index].slot = seDeleted
     dec(s.counter)
 
 proc excl*[A](s: var TSet[A], other: TSet[A]) =
-  ## excludes everything in `other` from `s`.
+  ## Excludes everything in `other` from `s`.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var
+  ##     numbers = toSet([1, 2, 3, 4, 5])
+  ##     even = toSet([2, 4, 6, 8])
+  ##   numbers.excl(even)
+  ##   echo numbers
+  ##   # --> {1, 3, 5}
+  assert s.isValid, "The set `s` needs to be initialized."
+  assert other.isValid, "The set `other` needs to be initialized."
   for item in other: excl(s, item)
 
 proc containsOrIncl*[A](s: var TSet[A], key: A): bool =
-  ## returns true if `s` contains `key`, otherwise `key` is included in `s`
-  ## and false is returned.
+  ## Includes `key` in the set `s` and tells if `key` was added to `s`.
+  ##
+  ## The difference with regards to the `incl() <#incl,TSet[A],A>`_ proc is
+  ## that this proc returns `true` if `key` was already present in `s`. The
+  ## proc will return false if `key` was added as a new value to `s` during
+  ## this call. Example:
+  ##
+  ## .. code-block::
+  ##   var values = initSet[int]()
+  ##   assert values.containsOrIncl(2) == false
+  ##   assert values.containsOrIncl(2) == true
+  assert s.isValid, "The set needs to be initialized."
   containsOrInclImpl()
 
-proc initSet*[A](initialSize=64): TSet[A] =
-  ## creates a new hash set that is empty. `initialSize` needs to be
-  ## a power of two.
+proc init*[A](s: var TSet[A], initialSize=64) =
+  ## Initializes a hash set.
+  ##
+  ## The `initialSize` parameter needs to be a power of too. You can use
+  ## `math.nextPowerOfTwo() `_ to guarantee that at
+  ## runtime. All set variables have to be initialized before you can use them
+  ## with other procs from this module with the exception of `isValid()
+  ## <#isValid,TSet[A]>`_ and `len() <#len,TSet[A]>`_.
+  ##
+  ## You can call this proc on a previously initialized hash set, which will
+  ## discard all its values. This might be more convenient than iterating over
+  ## existing values and calling `excl() <#excl,TSet[A],A>`_ on them. Example:
+  ##
+  ## .. code-block ::
+  ##   var a: TSet[int]
+  ##   a.init(4)
+  ##   a.incl(2)
+  ##   a.init
+  ##   assert a.len == 0 and a.isValid
   assert isPowerOfTwo(initialSize)
-  result.counter = 0
-  newSeq(result.data, initialSize)
+  s.counter = 0
+  newSeq(s.data, initialSize)
+
+proc initSet*[A](initialSize=64): TSet[A] =
+  ## Wrapper around `init() <#init,TSet[A],int>`_ for initialization of hash
+  ## sets.
+  ##
+  ## Returns an empty hash set you can assign directly in ``var`` blocks in a
+  ## single line. Example:
+  ##
+  ## .. code-block ::
+  ##   var a = initSet[int](4)
+  ##   a.incl(2)
+  result.init(initialSize)
 
 proc toSet*[A](keys: openArray[A]): TSet[A] =
-  ## creates a new hash set that contains the given `keys`.
+  ## Creates a new hash set that contains the given `keys`.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var numbers = toSet([1, 2, 3, 4, 5])
+  ##   assert numbers.contains(2)
+  ##   assert numbers.contains(4)
   result = initSet[A](nextPowerOfTwo(keys.len+10))
   for key in items(keys): result.incl(key)
 
@@ -152,46 +303,190 @@ template dollarImpl(): stmt {.dirty.} =
   result.add("}")
 
 proc `$`*[A](s: TSet[A]): string =
-  ## The `$` operator for hash sets.
+  ## Converts the set `s` to a string, mostly for logging purposes.
+  ##
+  ## Don't use this proc for serialization, the representation may change at
+  ## any moment and values are not escaped. Example:
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   echo toSet([2, 4, 5])
+  ##   # --> {2, 4, 5}
+  ##   echo toSet(["no", "esc'aping", "is \" provided"])
+  ##   # --> {no, esc'aping, is " provided}
+  assert s.isValid, "The set needs to be initialized."
   dollarImpl()
 
 proc union*[A](s1, s2: TSet[A]): TSet[A] =
-  ## returns a new set of all items that are contained in at
-  ## least one of `s1` and `s2`
+  ## Returns the union of the sets `s1` and `s2`.
+  ##
+  ## The union of two sets is represented mathematically as *A ∪ B* and is the
+  ## set of all objects that are members of `s1`, `s2` or both. Example:
+  ##
+  ## .. code-block::
+  ##   var
+  ##     a = toSet(["a", "b"])
+  ##     b = toSet(["b", "c"])
+  ##     c = union(a, b)
+  ##   assert c == toSet(["a", "b", "c"])
+  assert s1.isValid, "The set `s1` needs to be initialized."
+  assert s2.isValid, "The set `s2` needs to be initialized."
   result = s1
   incl(result, s2)
 
 proc intersection*[A](s1, s2: TSet[A]): TSet[A] =
-  ## returns a new set of all items that are contained in both `s1` and `s2`
+  ## Returns the intersection of the sets `s1` and `s2`.
+  ##
+  ## The intersection of two sets is represented mathematically as *A ∩ B* and
+  ## is the set of all objects that are members of `s1` and `s2` at the same
+  ## time. Example:
+  ##
+  ## .. code-block::
+  ##   var
+  ##     a = toSet(["a", "b"])
+  ##     b = toSet(["b", "c"])
+  ##     c = intersection(a, b)
+  ##   assert c == toSet(["b"])
+  assert s1.isValid, "The set `s1` needs to be initialized."
+  assert s2.isValid, "The set `s2` needs to be initialized."
   result = initSet[A](min(s1.data.len, s2.data.len))
   for item in s1:
     if item in s2: incl(result, item)
 
+proc difference*[A](s1, s2: TSet[A]): TSet[A] =
+  ## Returns the difference of the sets `s1` and `s2`.
+  ##
+  ## The difference of two sets is represented mathematically as *A \ B* and is
+  ## the set of all objects that are members of `s1` and not members of `s2`.
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var
+  ##     a = toSet(["a", "b"])
+  ##     b = toSet(["b", "c"])
+  ##     c = difference(a, b)
+  ##   assert c == toSet(["a"])
+  assert s1.isValid, "The set `s1` needs to be initialized."
+  assert s2.isValid, "The set `s2` needs to be initialized."
+  result = initSet[A]()
+  for item in s1:
+    if not contains(s2, item):
+      incl(result, item)
+
 proc symmetricDifference*[A](s1, s2: TSet[A]): TSet[A] =
-  ## returns a new set of all items that are contained in either
-  ## `s1` or `s2`, but not both
+  ## Returns the symmetric difference of the sets `s1` and `s2`.
+  ##
+  ## The symmetric difference of two sets is represented mathematically as *A â–³
+  ## B* or *A ⊖ B* and is the set of all objects that are members of `s1` or
+  ## `s2` but not both at the same time. Example:
+  ##
+  ## .. code-block::
+  ##   var
+  ##     a = toSet(["a", "b"])
+  ##     b = toSet(["b", "c"])
+  ##     c = symmetricDifference(a, b)
+  ##   assert c == toSet(["a", "c"])
+  assert s1.isValid, "The set `s1` needs to be initialized."
+  assert s2.isValid, "The set `s2` needs to be initialized."
   result = s1
   for item in s2:
     if containsOrIncl(result, item): excl(result, item)
 
 proc `+`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} =
-  ## alias for `union`
+  ## Alias for `union(s1, s2) <#union>`_.
   result = union(s1, s2)
 
 proc `*`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} =
-  ## alias for `intersection`
+  ## Alias for `intersection(s1, s2) <#intersection>`_.
   result = intersection(s1, s2)
 
+proc `-`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} =
+  ## Alias for `difference(s1, s2) <#difference>`_.
+  result = difference(s1, s2)
+
 proc `-+-`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} =
-  ## alias for `symmetricDifference`
+  ## Alias for `symmetricDifference(s1, s2) <#symmetricDifference>`_.
   result = symmetricDifference(s1, s2)
 
 proc disjoint*[A](s1, s2: TSet[A]): bool =
-  ## returns true iff `s1` and `s2` have no items in common
+  ## Returns true iff the sets `s1` and `s2` have no items in common.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var
+  ##     a = toSet(["a", "b"])
+  ##     b = toSet(["b", "c"])
+  ##   assert disjoint(a, b) == false
+  ##   assert disjoint(a, b - a) == true
+  assert s1.isValid, "The set `s1` needs to be initialized."
+  assert s2.isValid, "The set `s2` needs to be initialized."
   for item in s1:
     if item in s2: return false
   return true
 
+proc `<`*[A](s, t: TSet[A]): bool =
+  ## Returns true if `s` is a strict or proper subset of `t`.
+  ##
+  ## A strict or proper subset `s` has all of its members in `t` but `t` has
+  ## more elements than `s`. Example:
+  ##
+  ## .. code-block::
+  ##   var
+  ##     a = toSet(["a", "b"])
+  ##     b = toSet(["b", "c"])
+  ##     c = intersection(a, b)
+  ##   assert c < a and c < b
+  ##   assert((a < a) == false)
+  s.counter != t.counter and s <= t
+
+proc `<=`*[A](s, t: TSet[A]): bool =
+  ## Returns true if `s` is subset of `t`.
+  ##
+  ## A subset `s` has all of its members in `t` and `t` doesn't necessarily
+  ## have more members than `s`. That is, `s` can be equal to `t`. Example:
+  ##
+  ## .. code-block::
+  ##   var
+  ##     a = toSet(["a", "b"])
+  ##     b = toSet(["b", "c"])
+  ##     c = intersection(a, b)
+  ##   assert c <= a and c <= b
+  ##   assert((a <= a))
+  result = false
+  if s.counter > t.counter: return
+  result = true
+  for item in s:
+    if not(t.contains(item)):
+      result = false
+      return
+
+proc `==`*[A](s, t: TSet[A]): bool =
+  ## Returns true if both `s` and `t` have the same members and set size.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var
+  ##     a = toSet([1, 2])
+  ##     b = toSet([1])
+  ##   b.incl(2)
+  ##   assert a == b
+  s.counter == t.counter and s <= t
+
+proc map*[A, B](data: TSet[A], op: proc (x: A): B {.closure.}): TSet[B] =
+  ## Returns a new set after applying `op` on each of the elements of `data`.
+  ##
+  ## You can use this proc to transform the elements from a set. Example:
+  ##
+  ## .. code-block::
+  ##   var a = toSet([1, 2, 3])
+  ##   var b = a.map(proc (x: int): string = $x)
+  ##   assert b == toSet(["1", "2", "3"])
+  result = initSet[B]()
+  for item in data: result.incl(op(item))
+
 # ------------------------------ ordered set ------------------------------
 
 type
@@ -199,16 +494,48 @@ type
     slot: TSlotEnum, next: int, key: A]
   TOrderedKeyValuePairSeq[A] = seq[TOrderedKeyValuePair[A]]
   TOrderedSet* {.
-      final, myShallow.}[A] = object ## set that remembers insertion order
+      final, myShallow.}[A] = object ## \
+    ## A generic hash set that remembers insertion order.
+    ##
+    ## Use `init() <#init,TOrderedSet[A],int>`_ or `initOrderedSet[type]()
+    ## <#initOrderedSet>`_ before calling other procs on it.
     data: TOrderedKeyValuePairSeq[A]
     counter, first, last: int
 
+proc isValid*[A](s: TOrderedSet[A]): bool =
+  ## Returns `true` if the ordered set has been initialized with `initSet
+  ## <#initOrderedSet>`_.
+  ##
+  ## Most operations over an uninitialized ordered set will crash at runtime
+  ## and `assert `_ in debug builds. You can use this proc
+  ## in your own procs to verify that ordered sets passed to your procs are
+  ## correctly initialized. Example:
+  ##
+  ## .. code-block :: nimrod
+  ##   proc saveTarotCards(cards: TOrderedSet[int]) =
+  ##     assert cards.isValid, "Pass an initialized set!"
+  ##     # Do stuff here, may crash in release builds!
+  result = not s.data.isNil
+
 proc len*[A](s: TOrderedSet[A]): int {.inline.} =
-  ## returns the number of keys in `s`.
+  ## Returns the number of keys in `s`.
+  ##
+  ## Due to an implementation detail you can call this proc on variables which
+  ## have not been initialized yet. The proc will return zero as the length
+  ## then. Example:
+  ##
+  ## .. code-block::
+  ##
+  ##   var values: TOrderedSet[int]
+  ##   assert(not values.isValid)
+  ##   assert values.len == 0
   result = s.counter
 
 proc card*[A](s: TOrderedSet[A]): int {.inline.} =
-  ## alias for `len`.
+  ## Alias for `len() <#len,TOrderedSet[A]>`_.
+  ##
+  ## Card stands for the `cardinality
+  ## `_ of a set.
   result = s.counter
 
 template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
@@ -219,7 +546,24 @@ template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
     h = nxt
 
 iterator items*[A](s: TOrderedSet[A]): A =
-  ## iterates over any key in the set `s` in insertion order.
+  ## Iterates over keys in the ordered set `s` in insertion order.
+  ##
+  ## If you need a sequence with the keys you can use `sequtils.toSeq()
+  ## `_ on the iterator. Usage example:
+  ##
+  ## .. code-block::
+  ##   var a = initOrderedSet[int]()
+  ##   for value in [9, 2, 1, 5, 1, 8, 4, 2]:
+  ##     a.incl(value)
+  ##   for value in a.items:
+  ##     echo "Got ", value
+  ##   # --> Got 9
+  ##   # --> Got 2
+  ##   # --> Got 1
+  ##   # --> Got 5
+  ##   # --> Got 8
+  ##   # --> Got 4
+  assert s.isValid, "The set needs to be initialized."
   forAllOrderedPairs:
     yield s.data[h].key
 
@@ -227,7 +571,16 @@ proc rawGet[A](s: TOrderedSet[A], key: A): int =
   rawGetImpl()
 
 proc contains*[A](s: TOrderedSet[A], key: A): bool =
-  ## returns true iff `key` is in `s`.
+  ## Returns true iff `key` is in `s`.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var values = initOrderedSet[int]()
+  ##   assert(not values.contains(2))
+  ##   values.incl(2)
+  ##   assert values.contains(2)
+  assert s.isValid, "The set needs to be initialized."
   var index = rawGet(s, key)
   result = index >= 0
 
@@ -253,53 +606,297 @@ proc enlarge[A](s: var TOrderedSet[A]) =
   swap(s.data, n)
 
 proc incl*[A](s: var TOrderedSet[A], key: A) =
-  ## includes an element `key` in `s`.
+  ## Includes an element `key` in `s`.
+  ##
+  ## This doesn't do anything if `key` is already in `s`. Example:
+  ##
+  ## .. code-block::
+  ##   var values = initOrderedSet[int]()
+  ##   values.incl(2)
+  ##   values.incl(2)
+  ##   assert values.len == 1
+  assert s.isValid, "The set needs to be initialized."
   inclImpl()
 
 proc incl*[A](s: var TSet[A], other: TOrderedSet[A]) =
-  ## includes everything in `other` in `s`
+  ## Includes all elements from `other` into `s`.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var values = initOrderedSet[int]()
+  ##   values.incl(2)
+  ##   var others = toOrderedSet([6, 7])
+  ##   values.incl(others)
+  ##   assert values.len == 3
+  assert s.isValid, "The set `s` needs to be initialized."
+  assert other.isValid, "The set `other` needs to be initialized."
   for item in other: incl(s, item)
 
 proc containsOrIncl*[A](s: var TOrderedSet[A], key: A): bool =
-  ## returns true if `s` contains `key`, otherwise `key` is included in `s`
-  ## and false is returned.
+  ## Includes `key` in the set `s` and tells if `key` was added to `s`.
+  ##
+  ## The difference with regards to the `incl() <#incl,TOrderedSet[A],A>`_ proc
+  ## is that this proc returns `true` if `key` was already present in `s`. The
+  ## proc will return false if `key` was added as a new value to `s` during
+  ## this call. Example:
+  ##
+  ## .. code-block::
+  ##   var values = initOrderedSet[int]()
+  ##   assert values.containsOrIncl(2) == false
+  ##   assert values.containsOrIncl(2) == true
+  assert s.isValid, "The set needs to be initialized."
   containsOrInclImpl()
 
-proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] =
-  ## creates a new ordered hash set that is empty. `initialSize` needs to be
-  ## a power of two.
+proc init*[A](s: var TOrderedSet[A], initialSize=64) =
+  ## Initializes an ordered hash set.
+  ##
+  ## The `initialSize` parameter needs to be a power of too. You can use
+  ## `math.nextPowerOfTwo() `_ to guarantee that at
+  ## runtime. All set variables have to be initialized before you can use them
+  ## with other procs from this module with the exception of `isValid()
+  ## <#isValid,TOrderedSet[A]>`_ and `len() <#len,TOrderedSet[A]>`_.
+  ##
+  ## You can call this proc on a previously initialized ordered hash set to
+  ## discard its values. At the moment this is the only proc to remove elements
+  ## from an ordered hash set. Example:
+  ##
+  ## .. code-block ::
+  ##   var a: TOrderedSet[int]
+  ##   a.init(4)
+  ##   a.incl(2)
+  ##   a.init
+  ##   assert a.len == 0 and a.isValid
   assert isPowerOfTwo(initialSize)
-  result.counter = 0
-  result.first = -1
-  result.last = -1
-  newSeq(result.data, initialSize)
+  s.counter = 0
+  s.first = -1
+  s.last = -1
+  newSeq(s.data, initialSize)
+
+proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] =
+  ## Wrapper around `init() <#init,TOrderedSet[A],int>`_ for initialization of
+  ## ordered hash sets.
+  ##
+  ## Returns an empty ordered hash set you can assign directly in ``var``
+  ## blocks in a single line. Example:
+  ##
+  ## .. code-block ::
+  ##   var a = initOrderedSet[int](4)
+  ##   a.incl(2)
+  result.init(initialSize)
 
 proc toOrderedSet*[A](keys: openArray[A]): TOrderedSet[A] =
-  ## creates a new ordered hash set that contains the given `keys`.
+  ## Creates a new ordered hash set that contains the given `keys`.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   var numbers = toOrderedSet([1, 2, 3, 4, 5])
+  ##   assert numbers.contains(2)
+  ##   assert numbers.contains(4)
   result = initOrderedSet[A](nextPowerOfTwo(keys.len+10))
   for key in items(keys): result.incl(key)
 
 proc `$`*[A](s: TOrderedSet[A]): string =
-  ## The `$` operator for ordered hash sets.
+  ## Converts the ordered hash set `s` to a string, mostly for logging purposes.
+  ##
+  ## Don't use this proc for serialization, the representation may change at
+  ## any moment and values are not escaped. Example:
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   echo toOrderedSet([2, 4, 5])
+  ##   # --> {2, 4, 5}
+  ##   echo toOrderedSet(["no", "esc'aping", "is \" provided"])
+  ##   # --> {no, esc'aping, is " provided}
+  assert s.isValid, "The set needs to be initialized."
   dollarImpl()
 
-proc `<`*[A](s, t: TSet[A]): bool =
-  ## Is s a strict subset of t?
-  s.counter != t.counter and s <= t
+proc `==`*[A](s, t: TOrderedSet[A]): bool =
+  ## Equality for ordered sets.
+  if s.counter != t.counter: return false
+  var h = s.first
+  var g = s.first
+  var compared = 0
+  while h >= 0 and g >= 0:
+    var nxh = s.data[h].next
+    var nxg = t.data[g].next
+    if s.data[h].slot == seFilled and s.data[g].slot == seFilled:
+      if s.data[h].key == s.data[g].key:
+        inc compared
+      else:
+        return false
+    h = nxh
+    g = nxg
+  result = compared == s.counter
 
-proc `<=`*[A](s, t: TSet[A]): bool =
-  ## Is s a subset of t?
-  result = false
-  if s.counter > t.counter: return
-  result = true
-  for item in s:
-    if not(t.contains(item)):
-      result = false
-      return
-      
-proc `==`*[A](s, t: TSet[A]): bool =
-  s.counter == t.counter and s <= t
+proc testModule() =
+  ## Internal micro test to validate docstrings and such.
+  block isValidTest:
+    var options: TSet[string]
+    proc savePreferences(options: TSet[string]) =
+      assert options.isValid, "Pass an initialized set!"
+    options = initSet[string]()
+    options.savePreferences
 
-proc map*[A, B](data: TSet[A], op: proc (x: A): B {.closure.}): TSet[B] =
-  result = initSet[B]()
-  for item in data: result.incl(op(item))
+  block lenTest:
+    var values: TSet[int]
+    assert(not values.isValid)
+    assert values.len == 0
+    assert values.card == 0
+
+  block setIterator:
+    type pair = tuple[a, b: int]
+    var a, b = initSet[pair]()
+    a.incl((2, 3))
+    a.incl((3, 2))
+    a.incl((2, 3))
+    for x, y in a.items:
+      b.incl((x - 2, y + 1))
+    assert a.len == b.card
+    assert a.len == 2
+    #echo b
+
+  block setContains:
+    var values = initSet[int]()
+    assert(not values.contains(2))
+    values.incl(2)
+    assert values.contains(2)
+    values.excl(2)
+    assert(not values.contains(2))
+
+    values.incl(4)
+    var others = toSet([6, 7])
+    values.incl(others)
+    assert values.len == 3
+
+    values.init
+    assert values.containsOrIncl(2) == false
+    assert values.containsOrIncl(2) == true
+    var
+      a = toSet([1, 2])
+      b = toSet([1])
+    b.incl(2)
+    assert a == b
+
+  block exclusions:
+    var s = toSet([2, 3, 6, 7])
+    s.excl(2)
+    s.excl(2)
+    assert s.len == 3
+
+    var
+      numbers = toSet([1, 2, 3, 4, 5])
+      even = toSet([2, 4, 6, 8])
+    numbers.excl(even)
+    #echo numbers
+    # --> {1, 3, 5}
+
+  block toSeqAndString:
+    var a = toSet([2, 4, 5])
+    var b = initSet[int]()
+    for x in [2, 4, 5]: b.incl(x)
+    assert($a == $b)
+    #echo a
+    #echo toSet(["no", "esc'aping", "is \" provided"])
+
+  #block orderedToSeqAndString:
+  #  echo toOrderedSet([2, 4, 5])
+  #  echo toOrderedSet(["no", "esc'aping", "is \" provided"])
+
+  block setOperations:
+    var
+      a = toSet(["a", "b"])
+      b = toSet(["b", "c"])
+      c = union(a, b)
+    assert c == toSet(["a", "b", "c"])
+    var d = intersection(a, b)
+    assert d == toSet(["b"])
+    var e = difference(a, b)
+    assert e == toSet(["a"])
+    var f = symmetricDifference(a, b)
+    assert f == toSet(["a", "c"])
+    assert d < a and d < b
+    assert((a < a) == false)
+    assert d <= a and d <= b
+    assert((a <= a))
+    # Alias test.
+    assert a + b == toSet(["a", "b", "c"])
+    assert a * b == toSet(["b"])
+    assert a - b == toSet(["a"])
+    assert a -+- b == toSet(["a", "c"])
+    assert disjoint(a, b) == false
+    assert disjoint(a, b - a) == true
+
+  block mapSet:
+    var a = toSet([1, 2, 3])
+    var b = a.map(proc (x: int): string = $x)
+    assert b == toSet(["1", "2", "3"])
+
+  block isValidTest:
+    var cards: TOrderedSet[string]
+    proc saveTarotCards(cards: TOrderedSet[string]) =
+      assert cards.isValid, "Pass an initialized set!"
+    cards = initOrderedSet[string]()
+    cards.saveTarotCards
+
+  block lenTest:
+    var values: TOrderedSet[int]
+    assert(not values.isValid)
+    assert values.len == 0
+    assert values.card == 0
+
+  block setIterator:
+    type pair = tuple[a, b: int]
+    var a, b = initOrderedSet[pair]()
+    a.incl((2, 3))
+    a.incl((3, 2))
+    a.incl((2, 3))
+    for x, y in a.items:
+      b.incl((x - 2, y + 1))
+    assert a.len == b.card
+    assert a.len == 2
+
+  #block orderedSetIterator:
+  #  var a = initOrderedSet[int]()
+  #  for value in [9, 2, 1, 5, 1, 8, 4, 2]:
+  #    a.incl(value)
+  #  for value in a.items:
+  #    echo "Got ", value
+
+  block setContains:
+    var values = initOrderedSet[int]()
+    assert(not values.contains(2))
+    values.incl(2)
+    assert values.contains(2)
+
+  block toSeqAndString:
+    var a = toOrderedSet([2, 4, 5])
+    var b = initOrderedSet[int]()
+    for x in [2, 4, 5]: b.incl(x)
+    assert($a == $b)
+    assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
+
+  block initBlocks:
+    var a: TOrderedSet[int]
+    a.init(4)
+    a.incl(2)
+    a.init
+    assert a.len == 0 and a.isValid
+    a = initOrderedSet[int](4)
+    a.incl(2)
+    assert a.len == 1
+
+    var b: TSet[int]
+    b.init(4)
+    b.incl(2)
+    b.init
+    assert b.len == 0 and b.isValid
+    b = initSet[int](4)
+    b.incl(2)
+    assert b.len == 1
+
+  echo "Micro tests run successfully."
+
+when isMainModule and not defined(release): testModule()
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index ce9df09e10..dcf2ab4811 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -246,7 +246,8 @@ template equalsImpl() =
     # different insertion orders mean different 'data' seqs, so we have
     # to use the slow route here:
     for key, val in s:
-      if not hasKey(t, key): return false
+      # prefix notation leads to automatic dereference in case of PTable
+      if not t.hasKey(key): return false
       if t[key] != val: return false
     return true
   
@@ -332,7 +333,9 @@ proc `$`*[A, B](t: PTable[A, B]): string =
   dollarImpl()
 
 proc `==`*[A, B](s, t: PTable[A, B]): bool =
-  equalsImpl()
+  if isNil(s): result = isNil(t)
+  elif isNil(t): result = false
+  else: result = equalsImpl()
 
 proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): PTable[C, B] =
   ## Index the collection with the proc provided.
diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim
index df08ace723..1392b73aa5 100644
--- a/lib/pure/complex.nim
+++ b/lib/pure/complex.nim
@@ -113,6 +113,45 @@ proc `*` *(x: TComplex, y: float): TComplex =
   result.im = x.im * y
 
 
+proc `+=` *(x: var TComplex, y: TComplex) =
+  ## Add `y` to `x`.
+  x.re += y.re
+  x.im += y.im
+
+proc `+=` *(x: var TComplex, y: float) =
+  ## Add `y` to the complex number `x`.
+  x.re += y
+
+proc `-=` *(x: var TComplex, y: TComplex) =
+  ## Subtract `y` from `x`.
+  x.re -= y.re
+  x.im -= y.im
+
+proc `-=` *(x: var TComplex, y: float) =
+  ## Subtract `y` from the complex number `x`.
+  x.re -= y
+
+proc `*=` *(x: var TComplex, y: TComplex) =
+  ## Multiply `y` to `x`.
+  let im = x.im * y.re + x.re * y.im
+  x.re = x.re * y.re - x.im * y.im
+  x.im = im
+
+proc `*=` *(x: var TComplex, y: float) =
+  ## Multiply `y` to the complex number `x`.
+  x.re *= y
+  x.im *= y
+
+proc `/=` *(x: var TComplex, y: TComplex) =
+  ## Divide `x` by `y` in place.
+  x = x / y
+
+proc `/=` *(x : var TComplex, y: float) =
+  ## Divide complex `x` by float `y` in place.
+  x.re /= y
+  x.im /= y
+
+
 proc abs*(z: TComplex): float =
   ## Return the distance from (0,0) to `z`.
 
diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim
index dfa819f646..8d7f28f8ef 100644
--- a/lib/pure/concurrency/cpuinfo.nim
+++ b/lib/pure/concurrency/cpuinfo.nim
@@ -18,15 +18,24 @@ when not defined(windows):
 
 when defined(linux):
   import linux
+  
+when defined(freebsd) or defined(macosx):
+  {.emit:"#include ".}
+
+when defined(openbsd) or defined(netbsd):
+  {.emit:"#include ".}
 
 when defined(macosx) or defined(bsd):
+  # we HAVE to emit param.h before sysctl.h so we cannot use .header here
+  # either. The amount of archaic bullshit in Poonix based OSes is just insane.
+  {.emit:"#include ".}
   const
     CTL_HW = 6
     HW_AVAILCPU = 25
     HW_NCPU = 3
   proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer,
               a: var csize, b: pointer, c: int): cint {.
-             importc: "sysctl", header: "".}
+              importc: "sysctl", nodecl.}
 
 proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
   ## returns the numer of the processors/cores the machine has.
diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim
index fd1041918d..f46822d941 100644
--- a/lib/pure/concurrency/threadpool.nim
+++ b/lib/pure/concurrency/threadpool.nim
@@ -9,6 +9,9 @@
 
 ## Implements Nimrod's 'spawn'.
 
+when not compileOption("threads"):
+  {.error: "Threadpool requires --threads:on option.".}
+
 import cpuinfo, cpuload, locks
 
 {.push stackTrace:off.}
@@ -92,7 +95,7 @@ type
 
   FlowVarBase* = ref FlowVarBaseObj ## untyped base class for 'FlowVar[T]'
   FlowVarBaseObj = object of TObject
-    ready, usesCondVar: bool
+    ready, usesCondVar, awaited: bool
     cv: CondVar #\
     # for 'awaitAny' support
     ai: ptr AwaitInfo
@@ -126,15 +129,15 @@ type
 proc await*(fv: FlowVarBase) =
   ## waits until the value for the flowVar arrives. Usually it is not necessary
   ## to call this explicitly.
-  if fv.usesCondVar:
-    fv.usesCondVar = false
+  if fv.usesCondVar and not fv.awaited:
+    fv.awaited = true
     await(fv.cv)
     destroyCondVar(fv.cv)
 
 proc finished(fv: FlowVarBase) =
   doAssert fv.ai.isNil, "flowVar is still attached to an 'awaitAny'"
   # we have to protect against the rare cases where the owner of the flowVar
-  # simply disregards the flowVar and yet the "flowVarr" has not yet written
+  # simply disregards the flowVar and yet the "flowVar" has not yet written
   # anything to it:
   await(fv)
   if fv.data.isNil: return
@@ -207,6 +210,7 @@ proc `^`*[T](fv: FlowVar[T]): T =
   ## blocks until the value is available and then returns this value.
   await(fv)
   when T is string or T is seq:
+    # XXX closures? deepCopy?
     result = cast[T](fv.data)
   else:
     result = fv.blob
@@ -264,6 +268,10 @@ proc slave(w: ptr Worker) {.thread.} =
       w.shutdown = false
       atomicDec currentPoolSize
 
+var
+  workers: array[MaxThreadPoolSize, TThread[ptr Worker]]
+  workersData: array[MaxThreadPoolSize, Worker]
+
 proc setMinPoolSize*(size: range[1..MaxThreadPoolSize]) =
   ## sets the minimal thread pool size. The default value of this is 4.
   minPoolSize = size
@@ -272,10 +280,10 @@ proc setMaxPoolSize*(size: range[1..MaxThreadPoolSize]) =
   ## sets the minimal thread pool size. The default value of this
   ## is ``MaxThreadPoolSize``.
   maxPoolSize = size
-
-var
-  workers: array[MaxThreadPoolSize, TThread[ptr Worker]]
-  workersData: array[MaxThreadPoolSize, Worker]
+  if currentPoolSize > maxPoolSize:
+    for i in maxPoolSize..currentPoolSize-1:
+      let w = addr(workersData[i])
+      w.shutdown = true
 
 proc activateThread(i: int) {.noinline.} =
   workersData[i].taskArrived = createCondVar()
diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim
index d1cf36a871..49bf929807 100644
--- a/lib/pure/cookies.nim
+++ b/lib/pure/cookies.nim
@@ -28,8 +28,9 @@ proc parseCookies*(s: string): PStringTable =
     if s[i] == '\0': break
     inc(i) # skip ';'
 
-proc setCookie*(key, value: string, domain = "", path = "", 
-                expires = "", noName = false): string =
+proc setCookie*(key, value: string, domain = "", path = "",
+                expires = "", noName = false,
+                secure = false, httpOnly = false): string =
   ## Creates a command in the format of 
   ## ``Set-Cookie: key=value; Domain=...; ...``
   result = ""
@@ -38,16 +39,20 @@ proc setCookie*(key, value: string, domain = "", path = "",
   if domain != "": result.add("; Domain=" & domain)
   if path != "": result.add("; Path=" & path)
   if expires != "": result.add("; Expires=" & expires)
+  if secure: result.add("; secure")
+  if httpOnly: result.add("; HttpOnly")
 
 proc setCookie*(key, value: string, expires: TTimeInfo,
-                domain = "", path = "", noName = false): string =
+                domain = "", path = "", noName = false,
+                secure = false, httpOnly = false): string =
   ## Creates a command in the format of 
   ## ``Set-Cookie: key=value; Domain=...; ...``
   ##
   ## **Note:** UTC is assumed as the timezone for ``expires``.
   
   return setCookie(key, value, domain, path,
-            format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), noname)
+                   format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"),
+                   noname, secure, httpOnly)
   
 when isMainModule:
   var tim = TTime(int(getTime()) + 76 * (60 * 60 * 24))
@@ -55,5 +60,3 @@ when isMainModule:
   echo(setCookie("test", "value", tim.getGMTime()))
   
   echo parseCookies("uid=1; kp=2")
-  
-                
\ No newline at end of file
diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim
index 94d21ed4ee..633ea60205 100644
--- a/lib/pure/encodings.nim
+++ b/lib/pure/encodings.nim
@@ -41,6 +41,7 @@ when defined(windows):
 
   const 
     winEncodings = [
+      (1,   "OEMCP"), # current OEM codepage
       (037, "IBM037"), # IBM EBCDIC US-Canada 
       (437, "IBM437"), # OEM United States 
       (500, "IBM500"), # IBM EBCDIC International 
diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim
index 53f6688b9b..e8d3f762ee 100644
--- a/lib/pure/ftpclient.nim
+++ b/lib/pure/ftpclient.nim
@@ -10,6 +10,10 @@ include "system/inclrtl"
 
 import sockets, strutils, parseutils, times, os, asyncio
 
+from asyncnet import nil
+from rawsockets import nil
+from asyncdispatch import PFuture
+
 ## This module **partially** implements an FTP client as specified
 ## by `RFC 959 `_. 
 ## 
@@ -34,34 +38,32 @@ import sockets, strutils, parseutils, times, os, asyncio
 
 
 type
-  TFTPClient* = object of TObject
-    case isAsync: bool
-    of false:
-      csock: TSocket # Command connection socket
-      dsock: TSocket # Data connection socket
-    else:
-      dummyA, dummyB: pointer # workaround a Nimrod API issue
-      asyncCSock: PAsyncSocket
-      asyncDSock: PAsyncSocket
+  PFtpBase*[SockType] = ref TFtpBase[SockType]
+  TFtpBase*[SockType] = object
+    csock*: SockType
+    dsock*: SockType
+    when SockType is asyncio.PAsyncSocket:
       handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent){.closure,gcsafe.}
       disp: PDispatcher
       asyncDSockID: PDelegate
-    user, pass: string
-    address: string
-    port: TPort
+    user*, pass*: string
+    address*: string
+    when SockType is asyncnet.PAsyncSocket:
+      port*: rawsockets.TPort
+    else:
+      port*: TPort
     
-    jobInProgress: bool
-    job: ref TFTPJob
+    jobInProgress*: bool
+    job*: PFTPJob[SockType]
 
-    dsockConnected: bool
-
-  PFTPClient* = ref TFTPClient
+    dsockConnected*: bool
 
   FTPJobType* = enum
     JRetrText, JRetr, JStore
 
-  TFTPJob = object
-    prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall, gcsafe.}
+  PFtpJob[T] = ref TFtpJob[T]
+  TFTPJob[T] = object
+    prc: proc (ftp: PFTPBase[T], async: bool): bool {.nimcall, gcsafe.}
     case typ*: FTPJobType
     of JRetrText:
       lines: string
@@ -75,8 +77,11 @@ type
       toStore: string # Data left to upload (Only used with async)
     else: nil
 
+  TFtpClient* = TFtpBase[TSocket]
+  PFtpClient* = ref TFTPClient
+
   PAsyncFTPClient* = ref TAsyncFTPClient ## Async alternative to TFTPClient.
-  TAsyncFTPClient* = object of TFTPClient
+  TAsyncFTPClient* = TFtpBase[asyncio.PAsyncSocket]
 
   FTPEventType* = enum
     EvTransferProgress, EvLines, EvRetr, EvStore
@@ -106,30 +111,30 @@ proc ftpClient*(address: string, port = TPort(21),
   result.address = address
   result.port = port
 
-  result.isAsync = false
   result.dsockConnected = false
   result.csock = socket()
   if result.csock == InvalidSocket: osError(osLastError())
 
-proc getDSock(ftp: PFTPClient): TSocket =
-  if ftp.isAsync: return ftp.asyncDSock else: return ftp.dsock
+proc getDSock[T](ftp: PFTPBase[T]): TSocket =
+  return ftp.dsock
 
-proc getCSock(ftp: PFTPClient): TSocket =
-  if ftp.isAsync: return ftp.asyncCSock else: return ftp.csock
+proc getCSock[T](ftp: PFTPBase[T]): TSocket =
+  return ftp.csock
 
 template blockingOperation(sock: TSocket, body: stmt) {.immediate.} =
-  if ftp.isAsync:
-    sock.setBlocking(true)
   body
-  if ftp.isAsync:
-    sock.setBlocking(false)
 
-proc expectReply(ftp: PFTPClient): TaintedString =
+template blockingOperation(sock: asyncio.PAsyncSocket, body: stmt) {.immediate.} =
+  sock.setBlocking(true)
+  body
+  sock.setBlocking(false)
+
+proc expectReply[T](ftp: PFtpBase[T]): TaintedString =
   result = TaintedString""
   blockingOperation(ftp.getCSock()):
     ftp.getCSock().readLine(result)
 
-proc send*(ftp: PFTPClient, m: string): TaintedString =
+proc send*[T](ftp: PFtpBase[T], m: string): TaintedString =
   ## Send a message to the server, and wait for a primary reply.
   ## ``\c\L`` is added for you.
   blockingOperation(ftp.getCSock()):
@@ -149,8 +154,8 @@ proc assertReply(received: TaintedString, expected: varargs[string]) =
                      "Expected reply '$1' got: $2" %
                      [expected.join("' or '"), received.string])
 
-proc createJob(ftp: PFTPClient,
-               prc: proc (ftp: PFTPClient, async: bool): bool {.
+proc createJob[T](ftp: PFtpBase[T],
+               prc: proc (ftp: PFtpBase[T], async: bool): bool {.
                           nimcall,gcsafe.},
                cmd: FTPJobType) =
   if ftp.jobInProgress:
@@ -165,7 +170,7 @@ proc createJob(ftp: PFTPClient,
   of JRetr, JStore:
     ftp.job.toStore = ""
 
-proc deleteJob(ftp: PFTPClient) =
+proc deleteJob[T](ftp: PFtpBase[T]) =
   assert ftp.jobInProgress
   ftp.jobInProgress = false
   case ftp.job.typ
@@ -173,12 +178,9 @@ proc deleteJob(ftp: PFTPClient) =
     ftp.job.lines = ""
   of JRetr, JStore:
     ftp.job.file.close()
-  if ftp.isAsync:
-    ftp.asyncDSock.close()
-  else:
-    ftp.dsock.close()
+  ftp.dsock.close()
 
-proc handleTask(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleTask(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   if ftp.jobInProgress:
     if ftp.job.typ in {JRetr, JStore}:
       if epochTime() - ftp.job.lastProgressReport >= 1.0:
@@ -193,12 +195,12 @@ proc handleTask(s: PAsyncSocket, ftp: PFTPClient) =
         ftp.job.oneSecond = 0
         ftp.handleEvent(PAsyncFTPClient(ftp), r)
 
-proc handleWrite(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleWrite(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   if ftp.jobInProgress:
     if ftp.job.typ == JStore:
       assert (not ftp.job.prc(ftp, true))
 
-proc handleConnect(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleConnect(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   ftp.dsockConnected = true
   assert(ftp.jobInProgress)
   if ftp.job.typ == JStore:
@@ -206,30 +208,32 @@ proc handleConnect(s: PAsyncSocket, ftp: PFTPClient) =
   else:
     s.delHandleWrite()
 
-proc handleRead(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   assert ftp.jobInProgress
   assert ftp.job.typ != JStore
   # This can never return true, because it shouldn't check for code 
   # 226 from csock.
   assert(not ftp.job.prc(ftp, true))
 
-proc pasv(ftp: PFTPClient) =
+proc pasv[T](ftp: PFtpBase[T]) =
   ## Negotiate a data connection.
-  if not ftp.isAsync:
+  when T is TSocket:
     ftp.dsock = socket()
     if ftp.dsock == InvalidSocket: osError(osLastError())
-  else:
-    ftp.asyncDSock = AsyncSocket()
-    ftp.asyncDSock.handleRead =
+  elif T is PAsyncSocket:
+    ftp.dsock = AsyncSocket()
+    ftp.dsock.handleRead =
       proc (s: PAsyncSocket) =
         handleRead(s, ftp)
-    ftp.asyncDSock.handleConnect =
+    ftp.dsock.handleConnect =
       proc (s: PAsyncSocket) =
         handleConnect(s, ftp)
-    ftp.asyncDSock.handleTask =
+    ftp.dsock.handleTask =
       proc (s: PAsyncSocket) =
         handleTask(s, ftp)
-    ftp.disp.register(ftp.asyncDSock)
+    ftp.disp.register(ftp.dsock)
+  else:
+    {.fatal: "Incorrect socket instantiation".}
   
   var pasvMsg = ftp.send("PASV").string.strip.TaintedString
   assertReply(pasvMsg, "227")
@@ -238,23 +242,24 @@ proc pasv(ftp: PFTPClient) =
   var ip = nums[0.. -3]
   var port = nums[-2.. -1]
   var properPort = port[0].parseInt()*256+port[1].parseInt()
-  if ftp.isAsync:
-    ftp.asyncDSock.connect(ip.join("."), TPort(properPort.toU16))
+  ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
+  when T is PAsyncSocket:
     ftp.dsockConnected = False
   else:
-    ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
     ftp.dsockConnected = True
 
 proc normalizePathSep(path: string): string =
   return replace(path, '\\', '/')
 
-proc connect*(ftp: PFTPClient) =
+proc connect*[T](ftp: PFtpBase[T]) =
   ## Connect to the FTP server specified by ``ftp``.
-  if ftp.isAsync:
-    blockingOperation(ftp.asyncCSock):
-      ftp.asyncCSock.connect(ftp.address, ftp.port)
-  else:
+  when T is PAsyncSocket:
+    blockingOperation(ftp.csock):
+      ftp.csock.connect(ftp.address, ftp.port)
+  elif T is TSocket:
     ftp.csock.connect(ftp.address, ftp.port)
+  else:
+    {.fatal: "Incorrect socket instantiation".}
 
   # TODO: Handle 120? or let user handle it.
   assertReply ftp.expectReply(), "220"
@@ -279,25 +284,27 @@ proc cdup*(ftp: PFTPClient) =
   ## Changes the current directory to the parent of the current directory.
   assertReply ftp.send("CDUP"), "200"
 
-proc getLines(ftp: PFTPClient, async: bool = false): bool =
+proc getLines[T](ftp: PFtpBase[T], async: bool = false): bool =
   ## Downloads text data in ASCII mode
   ## Returns true if the download is complete.
   ## It doesn't if `async` is true, because it doesn't check for 226 then.
   if ftp.dsockConnected:
     var r = TaintedString""
-    if ftp.isAsync:
+    when T is PAsyncSocket:
       if ftp.asyncDSock.readLine(r):
         if r.string == "":
           ftp.dsockConnected = false
         else:
           ftp.job.lines.add(r.string & "\n")
-    else:
+    elif T is TSocket:
       assert(not async)
       ftp.dsock.readLine(r)
       if r.string == "":
         ftp.dsockConnected = false
       else:
         ftp.job.lines.add(r.string & "\n")
+    else:
+      {.fatal: "Incorrect socket instantiation".}
   
   if not async:
     var readSocks: seq[TSocket] = @[ftp.getCSock()]
@@ -307,14 +314,14 @@ proc getLines(ftp: PFTPClient, async: bool = false): bool =
         assertReply ftp.expectReply(), "226"
         return true
 
-proc listDirs*(ftp: PFTPClient, dir: string = "",
+proc listDirs*[T](ftp: PFtpBase[T], dir: string = "",
                async = false): seq[string] =
   ## Returns a list of filenames in the given directory. If ``dir`` is "",
   ## the current directory is used. If ``async`` is true, this
   ## function will return immediately and it will be your job to
   ## use asyncio's ``poll`` to progress this operation.
 
-  ftp.createJob(getLines, JRetrText)
+  ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
 
   assertReply ftp.send("NLST " & dir.normalizePathSep), ["125", "150"]
@@ -384,12 +391,12 @@ proc chmod*(ftp: PFTPClient, path: string,
   assertReply ftp.send("SITE CHMOD " & perm &
                        " " & path.normalizePathSep), "200"
 
-proc list*(ftp: PFTPClient, dir: string = "", async = false): string =
+proc list*[T](ftp: PFtpBase[T], dir: string = "", async = false): string =
   ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current
   ## working directory. If ``async`` is true, this function will return
   ## immediately and it will be your job to call asyncio's 
   ## ``poll`` to progress this operation.
-  ftp.createJob(getLines, JRetrText)
+  ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
 
   assertReply(ftp.send("LIST" & " " & dir.normalizePathSep), ["125", "150"])
@@ -401,11 +408,11 @@ proc list*(ftp: PFTPClient, dir: string = "", async = false): string =
   else:
     return ""
 
-proc retrText*(ftp: PFTPClient, file: string, async = false): string =
+proc retrText*[T](ftp: PFtpBase[T], file: string, async = false): string =
   ## Retrieves ``file``. File must be ASCII text.
   ## If ``async`` is true, this function will return immediately and
   ## it will be your job to call asyncio's ``poll`` to progress this operation.
-  ftp.createJob(getLines, JRetrText)
+  ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
   assertReply ftp.send("RETR " & file.normalizePathSep), ["125", "150"]
   
@@ -416,15 +423,17 @@ proc retrText*(ftp: PFTPClient, file: string, async = false): string =
   else:
     return ""
 
-proc getFile(ftp: PFTPClient, async = false): bool =
+proc getFile[T](ftp: PFtpBase[T], async = false): bool =
   if ftp.dsockConnected:
     var r = "".TaintedString
     var bytesRead = 0
     var returned = false
     if async:
-      if not ftp.isAsync: raise newException(EFTP, "FTPClient must be async.")
-      bytesRead = ftp.AsyncDSock.recvAsync(r, BufferSize)
-      returned = bytesRead != -1
+      when T is TSocket:
+        raise newException(EFTP, "FTPClient must be async.")
+      else:
+        bytesRead = ftp.dsock.recvAsync(r, BufferSize)
+        returned = bytesRead != -1
     else: 
       bytesRead = getDSock(ftp).recv(r, BufferSize)
       returned = true
@@ -443,13 +452,13 @@ proc getFile(ftp: PFTPClient, async = false): bool =
         assertReply ftp.expectReply(), "226"
         return true
 
-proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) =
+proc retrFile*[T](ftp: PFtpBase[T], file, dest: string, async = false) =
   ## Downloads ``file`` and saves it to ``dest``. Usage of this function
   ## asynchronously is recommended to view the progress of the download.
   ## The ``EvRetr`` event is passed to the specified ``handleEvent`` function 
   ## when the download is finished, and the ``filename`` field will be equal
   ## to ``file``.
-  ftp.createJob(getFile, JRetr)
+  ftp.createJob(getFile[T], JRetr)
   ftp.job.file = open(dest, mode = fmWrite)
   ftp.pasv()
   var reply = ftp.send("RETR " & file.normalizePathSep)
@@ -468,11 +477,11 @@ proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) =
     while not ftp.job.prc(ftp, false): discard
     ftp.deleteJob()
 
-proc doUpload(ftp: PFTPClient, async = false): bool =
+proc doUpload[T](ftp: PFtpBase[T], async = false): bool =
   if ftp.dsockConnected:
     if ftp.job.toStore.len() > 0:
       assert(async)
-      let bytesSent = ftp.asyncDSock.sendAsync(ftp.job.toStore)
+      let bytesSent = ftp.dsock.sendAsync(ftp.job.toStore)
       if bytesSent == ftp.job.toStore.len:
         ftp.job.toStore = ""
       elif bytesSent != ftp.job.toStore.len and bytesSent != 0:
@@ -485,7 +494,7 @@ proc doUpload(ftp: PFTPClient, async = false): bool =
       setLen(s, len)
       if len == 0:
         # File finished uploading.
-        if ftp.isAsync: ftp.asyncDSock.close() else: ftp.dsock.close()
+        ftp.dsock.close()
         ftp.dsockConnected = false
   
         if not async:
@@ -496,7 +505,7 @@ proc doUpload(ftp: PFTPClient, async = false): bool =
       if not async:
         getDSock(ftp).send(s)
       else:
-        let bytesSent = ftp.asyncDSock.sendAsync(s)
+        let bytesSent = ftp.dsock.sendAsync(s)
         if bytesSent == 0:
           ftp.job.toStore.add(s)
         elif bytesSent != s.len:
@@ -506,14 +515,14 @@ proc doUpload(ftp: PFTPClient, async = false): bool =
       ftp.job.progress.inc(len)
       ftp.job.oneSecond.inc(len)
 
-proc store*(ftp: PFTPClient, file, dest: string, async = false) =
+proc store*[T](ftp: PFtpBase[T], file, dest: string, async = false) =
   ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this
   ## function asynchronously is recommended to view the progress of
   ## the download.
   ## The ``EvStore`` event is passed to the specified ``handleEvent`` function 
   ## when the upload is finished, and the ``filename`` field will be 
   ## equal to ``file``.
-  ftp.createJob(doUpload, JStore)
+  ftp.createJob(doUpload[T], JStore)
   ftp.job.file = open(file)
   ftp.job.total = ftp.job.file.getFileSize()
   ftp.job.lastProgressReport = epochTime()
@@ -526,16 +535,12 @@ proc store*(ftp: PFTPClient, file, dest: string, async = false) =
     while not ftp.job.prc(ftp, false): discard
     ftp.deleteJob()
 
-proc close*(ftp: PFTPClient) =
+proc close*[T](ftp: PFTPBase[T]) =
   ## Terminates the connection to the server.
   assertReply ftp.send("QUIT"), "221"
   if ftp.jobInProgress: ftp.deleteJob()
-  if ftp.isAsync:
-    ftp.asyncCSock.close()
-    ftp.asyncDSock.close()
-  else:
-    ftp.csock.close()
-    ftp.dsock.close()
+  ftp.csock.close()
+  ftp.dsock.close()
 
 proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   if ftp.jobInProgress:
@@ -572,66 +577,65 @@ proc asyncFTPClient*(address: string, port = TPort(21),
   dres.pass = pass
   dres.address = address
   dres.port = port
-  dres.isAsync = true
   dres.dsockConnected = false
   dres.handleEvent = handleEvent
-  dres.asyncCSock = AsyncSocket()
-  dres.asyncCSock.handleRead =
+  dres.csock = AsyncSocket()
+  dres.csock.handleRead =
     proc (s: PAsyncSocket) =
       csockHandleRead(s, dres)
   result = dres
 
 proc register*(d: PDispatcher, ftp: PAsyncFTPClient): PDelegate {.discardable.} =
   ## Registers ``ftp`` with dispatcher ``d``.
-  assert ftp.isAsync
   ftp.disp = d
-  return ftp.disp.register(ftp.asyncCSock)
+  return ftp.disp.register(ftp.csock)
 
 when isMainModule:
-  var d = newDispatcher()
-  let hev =
-    proc (ftp: PAsyncFTPClient, event: TFTPEvent) =
-      case event.typ
-      of EvStore:
-        echo("Upload finished!")
-        ftp.retrFile("payload.JPG", "payload2.JPG", async = true)
-      of EvTransferProgress:
-        var time: int64 = -1
-        if event.speed != 0:
-          time = (event.bytesTotal - event.bytesFinished) div event.speed
-        echo(event.currentJob)
-        echo(event.speed div 1000, " kb/s. - ",
-             event.bytesFinished, "/", event.bytesTotal,
-             " - ", time, " seconds")
-        echo(d.len)
-      of EvRetr:
-        echo("Download finished!")
-        ftp.close()
-        echo d.len
-      else: assert(false)
-  var ftp = asyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev)
-  
-  d.register(ftp)
-  d.len.echo()
-  ftp.connect()
-  echo "connected"
-  ftp.store("payload.JPG", "payload.JPG", async = true)
-  d.len.echo()
-  echo "uploading..."
-  while true:
-    if not d.poll(): break
-
+  proc main =
+    var d = newDispatcher()
+    let hev =
+      proc (ftp: PAsyncFTPClient, event: TFTPEvent) =
+        case event.typ
+        of EvStore:
+          echo("Upload finished!")
+          ftp.retrFile("payload.jpg", "payload2.jpg", async = true)
+        of EvTransferProgress:
+          var time: int64 = -1
+          if event.speed != 0:
+            time = (event.bytesTotal - event.bytesFinished) div event.speed
+          echo(event.currentJob)
+          echo(event.speed div 1000, " kb/s. - ",
+               event.bytesFinished, "/", event.bytesTotal,
+               " - ", time, " seconds")
+          echo(d.len)
+        of EvRetr:
+          echo("Download finished!")
+          ftp.close()
+          echo d.len
+        else: assert(false)
+    var ftp = asyncFTPClient("example.com", user = "foo", pass = "bar", handleEvent = hev)
+    
+    d.register(ftp)
+    d.len.echo()
+    ftp.connect()
+    echo "connected"
+    ftp.store("payload.jpg", "payload.jpg", async = true)
+    d.len.echo()
+    echo "uploading..."
+    while true:
+      if not d.poll(): break
+  main()
 
 when isMainModule and false:
-  var ftp = ftpClient("picheta.me", user = "asdasd", pass = "asfwq")
+  var ftp = ftpClient("example.com", user = "foo", pass = "bar")
   ftp.connect()
   echo ftp.pwd()
   echo ftp.list()
   echo("uploading")
-  ftp.store("payload.JPG", "payload.JPG", async = false)
+  ftp.store("payload.jpg", "payload.jpg", async = false)
 
   echo("Upload complete")
-  ftp.retrFile("payload.JPG", "payload2.JPG", async = false)
+  ftp.retrFile("payload.jpg", "payload2.jpg", async = false)
 
   echo("Download complete")
   sleep(5000)
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 9bacc80d62..4db6ac6ed2 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -654,8 +654,7 @@ when isMainModule:
       resp = await client.request("http://nimrod-lang.org/download.html")
       echo("Got response: ", resp.status)
 
-    asyncCheck main()
-    runForever()
+    waitFor main()
 
   else:
     #downloadFile("http://force7.de/nimrod/index.html", "nimrodindex.html")
diff --git a/lib/pure/irc.nim b/lib/pure/irc.nim
deleted file mode 100644
index 49d9a9a34e..0000000000
--- a/lib/pure/irc.nim
+++ /dev/null
@@ -1,503 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2012 Dominik Picheta
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module implements an asynchronous IRC client.
-## 
-## Currently this module requires at least some knowledge of the IRC protocol.
-## It provides a function for sending raw messages to the IRC server, together
-## with some basic functions like sending a message to a channel. 
-## It automizes the process of keeping the connection alive, so you don't
-## need to reply to PING messages. In fact, the server is also PING'ed to check 
-## the amount of lag.
-##
-## .. code-block:: Nimrod
-##
-##   var client = irc("picheta.me", joinChans = @["#bots"])
-##   client.connect()
-##   while True:
-##     var event: TIRCEvent
-##     if client.poll(event):
-##       case event.typ
-##       of EvConnected: nil
-##       of EvDisconnected:
-##         client.reconnect()
-##       of EvMsg:
-##         # Write your message reading code here.
-## 
-## **Warning:** The API of this module is unstable, and therefore is subject
-## to change.
-
-include "system/inclrtl"
-
-import sockets, strutils, parseutils, times, asyncio, os
-
-type
-  TIRC* = object of TObject
-    address: string
-    port: TPort
-    nick, user, realname, serverPass: string
-    case isAsync: bool
-    of true:
-      handleEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure, gcsafe.}
-      asyncSock: PAsyncSocket
-      myDispatcher: PDispatcher
-    of false:
-      dummyA: pointer
-      dummyB: pointer # workaround a Nimrod API issue
-      dummyC: pointer
-      sock: TSocket
-    status: TInfo
-    lastPing: float
-    lastPong: float
-    lag: float
-    channelsToJoin: seq[string]
-    msgLimit: bool
-    messageBuffer: seq[tuple[timeToSend: float, m: string]]
-    lastReconnect: float
-
-  PIRC* = ref TIRC
-
-  PAsyncIRC* = ref TAsyncIRC
-  TAsyncIRC* = object of TIRC
-
-  TIRCMType* = enum
-    MUnknown,
-    MNumeric,
-    MPrivMsg,
-    MJoin,
-    MPart,
-    MMode,
-    MTopic,
-    MInvite,
-    MKick,
-    MQuit,
-    MNick,
-    MNotice,
-    MPing,
-    MPong,
-    MError
-  
-  TIRCEventType* = enum
-    EvMsg, EvConnected, EvDisconnected
-  TIRCEvent* = object ## IRC Event
-    case typ*: TIRCEventType
-    of EvConnected:
-      ## Connected to server.
-      ## Only occurs with AsyncIRC.
-      nil
-    of EvDisconnected: 
-      ## Disconnected from the server
-      nil
-    of EvMsg:              ## Message from the server
-      cmd*: TIRCMType      ## Command (e.g. PRIVMSG)
-      nick*, user*, host*, servername*: string
-      numeric*: string     ## Only applies to ``MNumeric``
-      params*: seq[string] ## Parameters of the IRC message
-      origin*: string      ## The channel/user that this msg originated from
-      raw*: string         ## Raw IRC message
-      timestamp*: TTime    ## UNIX epoch time the message was received
-  
-proc send*(irc: PIRC, message: string, sendImmediately = false) =
-  ## Sends ``message`` as a raw command. It adds ``\c\L`` for you.
-  var sendMsg = true
-  if irc.msgLimit and not sendImmediately:
-    var timeToSend = epochTime()
-    if irc.messageBuffer.len() >= 3:
-      timeToSend = (irc.messageBuffer[irc.messageBuffer.len()-1][0] + 2.0)
-
-    irc.messageBuffer.add((timeToSend, message))
-    sendMsg = false
-
-  if sendMsg:
-    try:
-      if irc.isAsync:
-        irc.asyncSock.send(message & "\c\L")
-      else:
-        irc.sock.send(message & "\c\L")
-    except EOS:
-      # Assuming disconnection of every EOS could be bad,
-      # but I can't exactly check for EBrokenPipe.
-      irc.status = SockClosed
-
-proc privmsg*(irc: PIRC, target, message: string) =
-  ## Sends ``message`` to ``target``. ``Target`` can be a channel, or a user.
-  irc.send("PRIVMSG $1 :$2" % [target, message])
-
-proc notice*(irc: PIRC, target, message: string) =
-  ## Sends ``notice`` to ``target``. ``Target`` can be a channel, or a user. 
-  irc.send("NOTICE $1 :$2" % [target, message])
-
-proc join*(irc: PIRC, channel: string, key = "") =
-  ## Joins ``channel``.
-  ## 
-  ## If key is not ``""``, then channel is assumed to be key protected and this
-  ## function will join the channel using ``key``.
-  if key == "":
-    irc.send("JOIN " & channel)
-  else:
-    irc.send("JOIN " & channel & " " & key)
-
-proc part*(irc: PIRC, channel, message: string) =
-  ## Leaves ``channel`` with ``message``.
-  irc.send("PART " & channel & " :" & message)
-
-proc close*(irc: PIRC) =
-  ## Closes connection to an IRC server.
-  ##
-  ## **Warning:** This procedure does not send a ``QUIT`` message to the server.
-  irc.status = SockClosed
-  if irc.isAsync:
-    irc.asyncSock.close()
-  else:
-    irc.sock.close()
-
-proc isNumber(s: string): bool =
-  ## Checks if `s` contains only numbers.
-  var i = 0
-  while s[i] in {'0'..'9'}: inc(i)
-  result = i == s.len and s.len > 0
-
-proc parseMessage(msg: string): TIRCEvent =
-  result.typ       = EvMsg
-  result.cmd       = MUnknown
-  result.raw       = msg
-  result.timestamp = times.getTime()
-  var i = 0
-  # Process the prefix
-  if msg[i] == ':':
-    inc(i) # Skip `:`
-    var nick = ""
-    i.inc msg.parseUntil(nick, {'!', ' '}, i)
-    result.nick = ""
-    result.serverName = ""
-    if msg[i] == '!':
-      result.nick = nick
-      inc(i) # Skip `!`
-      i.inc msg.parseUntil(result.user, {'@'}, i)
-      inc(i) # Skip `@`
-      i.inc msg.parseUntil(result.host, {' '}, i)
-      inc(i) # Skip ` `
-    else:
-      result.serverName = nick
-      inc(i) # Skip ` `
-  
-  # Process command
-  var cmd = ""
-  i.inc msg.parseUntil(cmd, {' '}, i)
-
-  if cmd.isNumber:
-    result.cmd = MNumeric
-    result.numeric = cmd
-  else:
-    case cmd
-    of "PRIVMSG": result.cmd = MPrivMsg
-    of "JOIN": result.cmd = MJoin
-    of "PART": result.cmd = MPart
-    of "PONG": result.cmd = MPong
-    of "PING": result.cmd = MPing
-    of "MODE": result.cmd = MMode
-    of "TOPIC": result.cmd = MTopic
-    of "INVITE": result.cmd = MInvite
-    of "KICK": result.cmd = MKick
-    of "QUIT": result.cmd = MQuit
-    of "NICK": result.cmd = MNick
-    of "NOTICE": result.cmd = MNotice
-    of "ERROR": result.cmd = MError
-    else: result.cmd = MUnknown
-  
-  # Don't skip space here. It is skipped in the following While loop.
-  
-  # Params
-  result.params = @[]
-  var param = ""
-  while msg[i] != '\0' and msg[i] != ':':
-    inc(i) # Skip ` `.
-    i.inc msg.parseUntil(param, {' ', ':', '\0'}, i)
-    if param != "":
-      result.params.add(param)
-      param.setlen(0)
-  
-  if msg[i] == ':':
-    inc(i) # Skip `:`.
-    result.params.add(msg[i..msg.len-1])
-
-proc connect*(irc: PIRC) =
-  ## Connects to an IRC server as specified by ``irc``.
-  assert(irc.address != "")
-  assert(irc.port != TPort(0))
-  
-  irc.sock.connect(irc.address, irc.port)
- 
-  irc.status = SockConnected
-  
-  # Greet the server :)
-  if irc.serverPass != "": irc.send("PASS " & irc.serverPass, true)
-  irc.send("NICK " & irc.nick, true)
-  irc.send("USER $1 * 0 :$2" % [irc.user, irc.realname], true)
-
-proc reconnect*(irc: PIRC, timeout = 5000) =
-  ## Reconnects to an IRC server.
-  ##
-  ## ``Timeout`` specifies the time to wait in miliseconds between multiple
-  ## consecutive reconnections.
-  ##
-  ## This should be used when an ``EvDisconnected`` event occurs.
-  let secSinceReconnect = int(epochTime() - irc.lastReconnect)
-  if secSinceReconnect < timeout:
-    sleep(timeout - secSinceReconnect)
-  irc.sock = socket()
-  if irc.sock == InvalidSocket: osError(osLastError())
-  irc.connect()
-  irc.lastReconnect = epochTime()
-
-proc irc*(address: string, port: TPort = 6667.TPort,
-         nick = "NimrodBot",
-         user = "NimrodBot",
-         realname = "NimrodBot", serverPass = "",
-         joinChans: seq[string] = @[],
-         msgLimit: bool = true): PIRC =
-  ## Creates a ``TIRC`` object.
-  new(result)
-  result.address = address
-  result.port = port
-  result.nick = nick
-  result.user = user
-  result.realname = realname
-  result.serverPass = serverPass
-  result.lastPing = epochTime()
-  result.lastPong = -1.0
-  result.lag = -1.0
-  result.channelsToJoin = joinChans
-  result.msgLimit = msgLimit
-  result.messageBuffer = @[]
-  result.status = SockIdle
-  result.sock = socket()
-  if result.sock == InvalidSocket: osError(osLastError())
-
-proc processLine(irc: PIRC, line: string): TIRCEvent =
-  if line.len == 0:
-    irc.close()
-    result.typ = EvDisconnected
-  else:
-    result = parseMessage(line)
-    # Get the origin
-    result.origin = result.params[0]
-    if result.origin == irc.nick and
-       result.nick != "": result.origin = result.nick
-
-    if result.cmd == MError:
-      irc.close()
-      result.typ = EvDisconnected
-      return
-
-    if result.cmd == MPing:
-      irc.send("PONG " & result.params[0])
-    if result.cmd == MPong:
-      irc.lag = epochTime() - parseFloat(result.params[result.params.high])
-      irc.lastPong = epochTime()
-    if result.cmd == MNumeric:
-      if result.numeric == "001":
-        # Check the nickname.
-        if irc.nick != result.params[0]:
-          assert ' ' notin result.params[0]
-          irc.nick = result.params[0]
-        for chan in items(irc.channelsToJoin):
-          irc.join(chan)
-    if result.cmd == MNick:
-      if result.nick == irc.nick:
-        irc.nick = result.params[0]
-    
-proc processOther(irc: PIRC, ev: var TIRCEvent): bool =
-  result = false
-  if epochTime() - irc.lastPing >= 20.0:
-    irc.lastPing = epochTime()
-    irc.send("PING :" & formatFloat(irc.lastPing), true)
-
-  if epochTime() - irc.lastPong >= 120.0 and irc.lastPong != -1.0:
-    irc.close()
-    ev.typ = EvDisconnected # TODO: EvTimeout?
-    return true
-  
-  for i in 0..irc.messageBuffer.len-1:
-    if epochTime() >= irc.messageBuffer[0][0]:
-      irc.send(irc.messageBuffer[0].m, true)
-      irc.messageBuffer.delete(0)
-    else:
-      break # messageBuffer is guaranteed to be from the quickest to the
-            # later-est.
-
-proc poll*(irc: PIRC, ev: var TIRCEvent,
-           timeout: int = 500): bool =
-  ## This function parses a single message from the IRC server and returns 
-  ## a TIRCEvent.
-  ##
-  ## This function should be called often as it also handles pinging
-  ## the server.
-  ##
-  ## This function provides a somewhat asynchronous IRC implementation, although
-  ## it should only be used for simple things for example an IRC bot which does
-  ## not need to be running many time critical tasks in the background. If you
-  ## require this, use the asyncio implementation.
-  
-  if not (irc.status == SockConnected):
-    # Do not close the socket here, it is already closed!
-    ev.typ = EvDisconnected
-  var line = TaintedString""
-  var socks = @[irc.sock]
-  var ret = socks.select(timeout)
-  if ret == -1: osError(osLastError())
-  if socks.len() != 0 and ret != 0:
-    irc.sock.readLine(line)
-    ev = irc.processLine(line.string)
-    result = true
-
-  if processOther(irc, ev): result = true
-
-proc getLag*(irc: PIRC): float =
-  ## Returns the latency between this client and the IRC server in seconds.
-  ## 
-  ## If latency is unknown, returns -1.0.
-  return irc.lag
-
-proc isConnected*(irc: PIRC): bool =
-  ## Returns whether this IRC client is connected to an IRC server.
-  return irc.status == SockConnected
-
-proc getNick*(irc: PIRC): string =
-  ## Returns the current nickname of the client.
-  return irc.nick
-
-# -- Asyncio dispatcher
-
-proc handleConnect(s: PAsyncSocket, irc: PAsyncIRC) =  
-  # Greet the server :)
-  if irc.serverPass != "": irc.send("PASS " & irc.serverPass, true)
-  irc.send("NICK " & irc.nick, true)
-  irc.send("USER $1 * 0 :$2" % [irc.user, irc.realname], true)
-  irc.status = SockConnected
-  
-  var ev: TIRCEvent
-  ev.typ = EvConnected
-  irc.handleEvent(irc, ev)
-
-proc handleRead(s: PAsyncSocket, irc: PAsyncIRC) =
-  var line = "".TaintedString
-  var ret = s.readLine(line)
-  if ret:
-    if line == "":
-      var ev: TIRCEvent
-      irc.close()
-      ev.typ = EvDisconnected
-      irc.handleEvent(irc, ev)
-    else:
-      var ev = irc.processLine(line.string)
-      irc.handleEvent(irc, ev)
-  
-proc handleTask(s: PAsyncSocket, irc: PAsyncIRC) =
-  var ev: TIRCEvent
-  if irc.processOther(ev):
-    irc.handleEvent(irc, ev)
-
-proc register*(d: PDispatcher, irc: PAsyncIRC) =
-  ## Registers ``irc`` with dispatcher ``d``.
-  irc.asyncSock.handleConnect =
-    proc (s: PAsyncSocket) =
-      handleConnect(s, irc)
-  irc.asyncSock.handleRead =
-    proc (s: PAsyncSocket) =
-      handleRead(s, irc)
-  irc.asyncSock.handleTask =
-    proc (s: PAsyncSocket) =
-      handleTask(s, irc)
-  d.register(irc.asyncSock)
-  irc.myDispatcher = d
-
-proc connect*(irc: PAsyncIRC) =
-  ## Equivalent of connect for ``TIRC`` but specifically created for asyncio.
-  assert(irc.address != "")
-  assert(irc.port != TPort(0))
-  
-  irc.asyncSock.connect(irc.address, irc.port)
-
-proc reconnect*(irc: PAsyncIRC, timeout = 5000) =
-  ## Reconnects to an IRC server.
-  ##
-  ## ``Timeout`` specifies the time to wait in miliseconds between multiple
-  ## consecutive reconnections.
-  ##
-  ## This should be used when an ``EvDisconnected`` event occurs.
-  ##
-  ## When successfully reconnected an ``EvConnected`` event will occur.
-  let secSinceReconnect = int(epochTime() - irc.lastReconnect)
-  if secSinceReconnect < timeout:
-    sleep(timeout - secSinceReconnect)
-  irc.asyncSock = AsyncSocket()
-  irc.myDispatcher.register(irc)
-  irc.connect()
-  irc.lastReconnect = epochTime()
-
-proc asyncIRC*(address: string, port: TPort = 6667.TPort,
-              nick = "NimrodBot",
-              user = "NimrodBot",
-              realname = "NimrodBot", serverPass = "",
-              joinChans: seq[string] = @[],
-              msgLimit: bool = true,
-              ircEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure,gcsafe.}
-              ): PAsyncIRC =
-  ## Use this function if you want to use asyncio's dispatcher.
-  ## 
-  ## **Note:** Do **NOT** use this if you're writing a simple IRC bot which only
-  ## requires one task to be run, i.e. this should not be used if you want a
-  ## synchronous IRC client implementation, use ``irc`` for that.
-  
-  new(result)
-  result.isAsync = true
-  result.address = address
-  result.port = port
-  result.nick = nick
-  result.user = user
-  result.realname = realname
-  result.serverPass = serverPass
-  result.lastPing = epochTime()
-  result.lastPong = -1.0
-  result.lag = -1.0
-  result.channelsToJoin = joinChans
-  result.msgLimit = msgLimit
-  result.messageBuffer = @[]
-  result.handleEvent = ircEvent
-  result.asyncSock = AsyncSocket()
-  
-when isMainModule:
-  #var m = parseMessage("ERROR :Closing Link: dom96.co.cc (Ping timeout: 252 seconds)")
-  #echo(repr(m))
-
-
-  
-  var client = irc("amber.tenthbit.net", nick="TestBot1234",
-                   joinChans = @["#flood"])
-  client.connect()
-  while true:
-    var event: TIRCEvent
-    if client.poll(event):
-      case event.typ
-      of EvConnected:
-        discard
-      of EvDisconnected:
-        break
-      of EvMsg:
-        if event.cmd == MPrivMsg:
-          var msg = event.params[event.params.high]
-          if msg == "|test": client.privmsg(event.origin, "hello")
-          if msg == "|excessFlood":
-            for i in 0..10:
-              client.privmsg(event.origin, "TEST" & $i)
-
-        #echo( repr(event) )
-      #echo("Lag: ", formatFloat(client.getLag()))
-  
-    
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 508e564c57..a45900f297 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -621,9 +621,13 @@ proc `%`*(elements: openArray[PJsonNode]): PJsonNode =
 
 proc `==`* (a,b: PJsonNode): bool =
   ## Check two nodes for equality
-  if a.kind != b.kind: false
+  if a.isNil:
+    if b.isNil: return true
+    return false
+  elif b.isNil or a.kind != b.kind: 
+    return false
   else:
-    case a.kind
+    return case a.kind
     of JString:
       a.str == b.str
     of JInt:
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 2f7a696b90..8af09114ba 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -219,7 +219,7 @@ when not defined(JS):
 
   proc randomize(seed: int) =
     srand(cint(seed))
-    when defined(srand48): srand48(seed)
+    when declared(srand48): srand48(seed)
   proc random(max: int): int =
     result = int(rand()) mod max
 
@@ -279,8 +279,13 @@ proc `mod`*(x, y: float): float =
   result = if y == 0.0: x else: x - y * (x/y).floor
 
 proc random*[T](x: TSlice[T]): T =
+  ## For a slice `a .. b` returns a value in the range `a .. b-1`.
   result = random(x.b - x.a) + x.a
-  
+
+proc random[T](a: openarray[T]): T =
+  ## returns a random element from the openarray `a`.
+  result = a[random(a.low..a.len)]
+
 type
   TRunningStat* {.pure,final.} = object  ## an accumulator for statistical data
     n*: int                              ## number of pushed data
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 31fefc6c82..ffeb0beffe 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -54,7 +54,7 @@ proc mapMem*(m: var TMemFile, mode: TFileMode = fmRead,
       nil,
       mappedSize,
       if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
-      if readonly: MAP_PRIVATE else: MAP_SHARED,
+      if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE),
       m.handle, offset)
     if result == cast[pointer](MAP_FAILED):
       osError(osLastError())
@@ -207,7 +207,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
       nil,
       result.size,
       if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
-      if readonly: MAP_PRIVATE else: MAP_SHARED,
+      if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE),
       result.handle,
       offset)
 
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index ddc2bbe2dc..6965274671 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -11,292 +11,10 @@
 
 {.deadCodeElim: on.}
 import rawsockets, os, strutils, unsigned, parseutils, times
-export TPort, `$`
+export TPort, `$`, `==`
 
 const useWinVersion = defined(Windows) or defined(nimdoc)
 
-type
-  IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address
-    IPv6, ## IPv6 address
-    IPv4  ## IPv4 address
-
-  TIpAddress* = object ## stores an arbitrary IP address    
-    case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6)
-    of IpAddressFamily.IPv6:
-      address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in
-                                       ## case of IPv6
-    of IpAddressFamily.IPv4:
-      address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
-                                      ## case of IPv4
-
-proc IPv4_any*(): TIpAddress =
-  ## Returns the IPv4 any address, which can be used to listen on all available
-  ## network adapters
-  result = TIpAddress(
-    family: IpAddressFamily.IPv4,
-    address_v4: [0'u8, 0, 0, 0])
-
-proc IPv4_loopback*(): TIpAddress =
-  ## Returns the IPv4 loopback address (127.0.0.1)
-  result = TIpAddress(
-    family: IpAddressFamily.IPv4,
-    address_v4: [127'u8, 0, 0, 1])
-
-proc IPv4_broadcast*(): TIpAddress =
-  ## Returns the IPv4 broadcast address (255.255.255.255)
-  result = TIpAddress(
-    family: IpAddressFamily.IPv4,
-    address_v4: [255'u8, 255, 255, 255])
-
-proc IPv6_any*(): TIpAddress =
-  ## Returns the IPv6 any address (::0), which can be used
-  ## to listen on all available network adapters 
-  result = TIpAddress(
-    family: IpAddressFamily.IPv6,
-    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
-
-proc IPv6_loopback*(): TIpAddress =
-  ## Returns the IPv6 loopback address (::1)
-  result = TIpAddress(
-    family: IpAddressFamily.IPv6,
-    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
-
-proc `==`*(lhs, rhs: TIpAddress): bool =
-  ## Compares two IpAddresses for Equality. Returns two if the addresses are equal
-  if lhs.family != rhs.family: return false
-  if lhs.family == IpAddressFamily.IPv4:
-    for i in low(lhs.address_v4) .. high(lhs.address_v4):
-      if lhs.address_v4[i] != rhs.address_v4[i]: return false
-  else: # IPv6
-    for i in low(lhs.address_v6) .. high(lhs.address_v6):
-      if lhs.address_v6[i] != rhs.address_v6[i]: return false
-  return true
-
-proc `$`*(address: TIpAddress): string =
-  ## Converts an TIpAddress into the textual representation
-  result = ""
-  case address.family
-  of IpAddressFamily.IPv4:
-    for i in 0 .. 3:
-      if i != 0:
-        result.add('.')
-      result.add($address.address_v4[i])
-  of IpAddressFamily.IPv6:
-    var
-      currentZeroStart = -1
-      currentZeroCount = 0
-      biggestZeroStart = -1
-      biggestZeroCount = 0
-    # Look for the largest block of zeros
-    for i in 0..7:
-      var isZero = address.address_v6[i*2] == 0 and address.address_v6[i*2+1] == 0
-      if isZero:
-        if currentZeroStart == -1:
-          currentZeroStart = i
-          currentZeroCount = 1
-        else:
-          currentZeroCount.inc()
-        if currentZeroCount > biggestZeroCount:
-          biggestZeroCount = currentZeroCount
-          biggestZeroStart = currentZeroStart
-      else:
-        currentZeroStart = -1
-
-    if biggestZeroCount == 8: # Special case ::0
-      result.add("::")
-    else: # Print address
-      var printedLastGroup = false
-      for i in 0..7:
-        var word:uint16 = (cast[uint16](address.address_v6[i*2])) shl 8
-        word = word or cast[uint16](address.address_v6[i*2+1])
-
-        if biggestZeroCount != 0 and # Check if group is in skip group
-          (i >= biggestZeroStart and i < (biggestZeroStart + biggestZeroCount)):
-          if i == biggestZeroStart: # skip start
-            result.add("::")
-          printedLastGroup = false
-        else:
-          if printedLastGroup:
-            result.add(':')
-          var
-            afterLeadingZeros = false
-            mask = 0xF000'u16
-          for j in 0'u16..3'u16:
-            var val = (mask and word) shr (4'u16*(3'u16-j))
-            if val != 0 or afterLeadingZeros:
-              if val < 0xA:
-                result.add(chr(uint16(ord('0'))+val))
-              else: # val >= 0xA
-                result.add(chr(uint16(ord('a'))+val-0xA))
-              afterLeadingZeros = true
-            mask = mask shr 4
-          printedLastGroup = true
-
-proc parseIPv4Address(address_str: string): TIpAddress =
-  ## Parses IPv4 adresses
-  ## Raises EInvalidValue on errors
-  var
-    byteCount = 0
-    currentByte:uint16 = 0
-    seperatorValid = false
-
-  result.family = IpAddressFamily.IPv4
-
-  for i in 0 .. high(address_str):
-    if address_str[i] in strutils.Digits: # Character is a number
-      currentByte = currentByte * 10 +
-        cast[uint16](ord(address_str[i]) - ord('0'))
-      if currentByte > 255'u16:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Value is out of range")
-      seperatorValid = true
-    elif address_str[i] == '.': # IPv4 address separator
-      if not seperatorValid or byteCount >= 3:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. The address consists of too many groups")
-      result.address_v4[byteCount] = cast[uint8](currentByte)
-      currentByte = 0
-      byteCount.inc
-      seperatorValid = false
-    else:
-      raise newException(EInvalidValue,
-        "Invalid IP Address. Address contains an invalid character")
-
-  if byteCount != 3 or not seperatorValid:
-    raise newException(EInvalidValue, "Invalid IP Address")
-  result.address_v4[byteCount] = cast[uint8](currentByte)
-
-proc parseIPv6Address(address_str: string): TIpAddress =
-  ## Parses IPv6 adresses
-  ## Raises EInvalidValue on errors
-  result.family = IpAddressFamily.IPv6
-  if address_str.len < 2:
-    raise newException(EInvalidValue, "Invalid IP Address")
-
-  var
-    groupCount = 0
-    currentGroupStart = 0
-    currentShort:uint32 = 0
-    seperatorValid = true
-    dualColonGroup = -1
-    lastWasColon = false
-    v4StartPos = -1
-    byteCount = 0
-
-  for i,c in address_str:
-    if c == ':':
-      if not seperatorValid:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Address contains an invalid seperator")
-      if lastWasColon:        
-        if dualColonGroup != -1:
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Address contains more than one \"::\" seperator")
-        dualColonGroup = groupCount
-        seperatorValid = false
-      elif i != 0 and i != high(address_str):
-        if groupCount >= 8:
-          raise newException(EInvalidValue,
-            "Invalid IP Address. The address consists of too many groups")
-        result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
-        result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
-        currentShort = 0
-        groupCount.inc()        
-        if dualColonGroup != -1: seperatorValid = false
-      elif i == 0: # only valid if address starts with ::
-        if address_str[1] != ':':
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Address may not start with \":\"")
-      else: # i == high(address_str) - only valid if address ends with ::
-        if address_str[high(address_str)-1] != ':': 
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Address may not end with \":\"")
-      lastWasColon = true
-      currentGroupStart = i + 1
-    elif c == '.': # Switch to parse IPv4 mode
-      if i < 3 or not seperatorValid or groupCount >= 7:
-        raise newException(EInvalidValue, "Invalid IP Address")
-      v4StartPos = currentGroupStart
-      currentShort = 0
-      seperatorValid = false
-      break
-    elif c in strutils.HexDigits:
-      if c in strutils.Digits: # Normal digit
-        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('0'))
-      elif c >= 'a' and c <= 'f': # Lower case hex
-        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10
-      else: # Upper case hex
-        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10
-      if currentShort > 65535'u32:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Value is out of range")
-      lastWasColon = false
-      seperatorValid = true
-    else:
-      raise newException(EInvalidValue,
-        "Invalid IP Address. Address contains an invalid character")
-
-
-  if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff
-    if seperatorValid: # Copy remaining data
-      if groupCount >= 8:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. The address consists of too many groups")
-      result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
-      result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
-      groupCount.inc()
-  else: # Must parse IPv4 address
-    for i,c in address_str[v4StartPos..high(address_str)]:
-      if c in strutils.Digits: # Character is a number
-        currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0'))
-        if currentShort > 255'u32:
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Value is out of range")
-        seperatorValid = true
-      elif c == '.': # IPv4 address separator
-        if not seperatorValid or byteCount >= 3:
-          raise newException(EInvalidValue, "Invalid IP Address")
-        result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
-        currentShort = 0
-        byteCount.inc()
-        seperatorValid = false
-      else: # Invalid character
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Address contains an invalid character")
-
-    if byteCount != 3 or not seperatorValid:
-      raise newException(EInvalidValue, "Invalid IP Address")
-    result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
-    groupCount += 2
-
-  # Shift and fill zeros in case of ::
-  if groupCount > 8:
-    raise newException(EInvalidValue,
-      "Invalid IP Address. The address consists of too many groups")
-  elif groupCount < 8: # must fill
-    if dualColonGroup == -1:
-      raise newException(EInvalidValue,
-        "Invalid IP Address. The address consists of too few groups")
-    var toFill = 8 - groupCount # The number of groups to fill
-    var toShift = groupCount - dualColonGroup # Nr of known groups after ::
-    for i in 0..2*toShift-1: # shift
-      result.address_v6[15-i] = result.address_v6[groupCount*2-i-1]
-    for i in 0..2*toFill-1: # fill with 0s
-      result.address_v6[dualColonGroup*2+i] = 0
-  elif dualColonGroup != -1:
-    raise newException(EInvalidValue,
-      "Invalid IP Address. The address consists of too many groups")
-
-proc parseIpAddress*(address_str: string): TIpAddress =
-  ## Parses an IP address
-  ## Raises EInvalidValue on error
-  if address_str == nil:
-    raise newException(EInvalidValue, "IP Address string is nil")
-  if address_str.contains(':'):
-    return parseIPv6Address(address_str)
-  else:
-    return parseIPv4Address(address_str)
-
 when defined(ssl):
   import openssl
 
@@ -361,7 +79,7 @@ proc isDisconnectionError*(flags: set[TSocketFlags],
   when useWinVersion:
     TSocketFlags.SafeDisconn in flags and
       lastError.int32 in {WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
-                          WSAEDISCON}
+                          WSAEDISCON, ERROR_NETNAME_DELETED}
   else:
     TSocketFlags.SafeDisconn in flags and
       lastError.int32 in {ECONNRESET, EPIPE, ENETRESET} 
@@ -569,8 +287,8 @@ proc bindAddr*(socket: PSocket, port = TPort(0), address = "") {.
       osError(osLastError())
     dealloc(aiList)
 
-proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
-  tags: [FReadIO].} =
+proc acceptAddr*(server: PSocket, client: var PSocket, address: var string,
+                 flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} =
   ## Blocks until a connection is being made from a client. When a connection
   ## is made sets ``client`` to the client socket and ``address`` to the address
   ## of the connecting client.
@@ -581,6 +299,11 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
   ##
   ## **Note**: ``client`` must be initialised (with ``new``), this function 
   ## makes no effort to initialise the ``client`` variable.
+  ##
+  ## The ``accept`` call may result in an error if the connecting socket
+  ## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
+  ## flag is specified then this error will not be raised and instead
+  ## accept will be called again.
   assert(client != nil)
   var sockAddress: Tsockaddr_in
   var addrLen = sizeof(sockAddress).TSocklen
@@ -589,6 +312,8 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
   
   if sock == osInvalidSocket:
     let err = osLastError()
+    if flags.isDisconnectionError(err):
+      acceptAddr(server, client, address, flags)
     osError(err)
   else:
     client.fd = sock
@@ -658,15 +383,20 @@ when false: #defined(ssl):
       acceptAddrPlain(AcceptNoClient, AcceptSuccess):
         doHandshake()
 
-proc accept*(server: PSocket, client: var PSocket) {.tags: [FReadIO].} =
+proc accept*(server: PSocket, client: var PSocket,
+             flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} =
   ## Equivalent to ``acceptAddr`` but doesn't return the address, only the
   ## socket.
   ## 
   ## **Note**: ``client`` must be initialised (with ``new``), this function
   ## makes no effort to initialise the ``client`` variable.
-  
+  ##
+  ## The ``accept`` call may result in an error if the connecting socket
+  ## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
+  ## flag is specified then this error will not be raised and instead
+  ## accept will be called again.
   var addrDummy = ""
-  acceptAddr(server, client, addrDummy)
+  acceptAddr(server, client, addrDummy, flags)
 
 proc close*(socket: PSocket) =
   ## Closes a socket.
@@ -1173,3 +903,285 @@ proc isSSL*(socket: PSocket): bool = return socket.isSSL
 
 proc getFD*(socket: PSocket): TSocketHandle = return socket.fd
   ## Returns the socket's file descriptor
+
+type
+  IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address
+    IPv6, ## IPv6 address
+    IPv4  ## IPv4 address
+
+  TIpAddress* = object ## stores an arbitrary IP address    
+    case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6)
+    of IpAddressFamily.IPv6:
+      address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in
+                                       ## case of IPv6
+    of IpAddressFamily.IPv4:
+      address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
+                                      ## case of IPv4
+
+proc IPv4_any*(): TIpAddress =
+  ## Returns the IPv4 any address, which can be used to listen on all available
+  ## network adapters
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [0'u8, 0, 0, 0])
+
+proc IPv4_loopback*(): TIpAddress =
+  ## Returns the IPv4 loopback address (127.0.0.1)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [127'u8, 0, 0, 1])
+
+proc IPv4_broadcast*(): TIpAddress =
+  ## Returns the IPv4 broadcast address (255.255.255.255)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [255'u8, 255, 255, 255])
+
+proc IPv6_any*(): TIpAddress =
+  ## Returns the IPv6 any address (::0), which can be used
+  ## to listen on all available network adapters 
+  result = TIpAddress(
+    family: IpAddressFamily.IPv6,
+    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+
+proc IPv6_loopback*(): TIpAddress =
+  ## Returns the IPv6 loopback address (::1)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv6,
+    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
+
+proc `==`*(lhs, rhs: TIpAddress): bool =
+  ## Compares two IpAddresses for Equality. Returns two if the addresses are equal
+  if lhs.family != rhs.family: return false
+  if lhs.family == IpAddressFamily.IPv4:
+    for i in low(lhs.address_v4) .. high(lhs.address_v4):
+      if lhs.address_v4[i] != rhs.address_v4[i]: return false
+  else: # IPv6
+    for i in low(lhs.address_v6) .. high(lhs.address_v6):
+      if lhs.address_v6[i] != rhs.address_v6[i]: return false
+  return true
+
+proc `$`*(address: TIpAddress): string =
+  ## Converts an TIpAddress into the textual representation
+  result = ""
+  case address.family
+  of IpAddressFamily.IPv4:
+    for i in 0 .. 3:
+      if i != 0:
+        result.add('.')
+      result.add($address.address_v4[i])
+  of IpAddressFamily.IPv6:
+    var
+      currentZeroStart = -1
+      currentZeroCount = 0
+      biggestZeroStart = -1
+      biggestZeroCount = 0
+    # Look for the largest block of zeros
+    for i in 0..7:
+      var isZero = address.address_v6[i*2] == 0 and address.address_v6[i*2+1] == 0
+      if isZero:
+        if currentZeroStart == -1:
+          currentZeroStart = i
+          currentZeroCount = 1
+        else:
+          currentZeroCount.inc()
+        if currentZeroCount > biggestZeroCount:
+          biggestZeroCount = currentZeroCount
+          biggestZeroStart = currentZeroStart
+      else:
+        currentZeroStart = -1
+
+    if biggestZeroCount == 8: # Special case ::0
+      result.add("::")
+    else: # Print address
+      var printedLastGroup = false
+      for i in 0..7:
+        var word:uint16 = (cast[uint16](address.address_v6[i*2])) shl 8
+        word = word or cast[uint16](address.address_v6[i*2+1])
+
+        if biggestZeroCount != 0 and # Check if group is in skip group
+          (i >= biggestZeroStart and i < (biggestZeroStart + biggestZeroCount)):
+          if i == biggestZeroStart: # skip start
+            result.add("::")
+          printedLastGroup = false
+        else:
+          if printedLastGroup:
+            result.add(':')
+          var
+            afterLeadingZeros = false
+            mask = 0xF000'u16
+          for j in 0'u16..3'u16:
+            var val = (mask and word) shr (4'u16*(3'u16-j))
+            if val != 0 or afterLeadingZeros:
+              if val < 0xA:
+                result.add(chr(uint16(ord('0'))+val))
+              else: # val >= 0xA
+                result.add(chr(uint16(ord('a'))+val-0xA))
+              afterLeadingZeros = true
+            mask = mask shr 4
+          printedLastGroup = true
+
+proc parseIPv4Address(address_str: string): TIpAddress =
+  ## Parses IPv4 adresses
+  ## Raises EInvalidValue on errors
+  var
+    byteCount = 0
+    currentByte:uint16 = 0
+    seperatorValid = false
+
+  result.family = IpAddressFamily.IPv4
+
+  for i in 0 .. high(address_str):
+    if address_str[i] in strutils.Digits: # Character is a number
+      currentByte = currentByte * 10 +
+        cast[uint16](ord(address_str[i]) - ord('0'))
+      if currentByte > 255'u16:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Value is out of range")
+      seperatorValid = true
+    elif address_str[i] == '.': # IPv4 address separator
+      if not seperatorValid or byteCount >= 3:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. The address consists of too many groups")
+      result.address_v4[byteCount] = cast[uint8](currentByte)
+      currentByte = 0
+      byteCount.inc
+      seperatorValid = false
+    else:
+      raise newException(EInvalidValue,
+        "Invalid IP Address. Address contains an invalid character")
+
+  if byteCount != 3 or not seperatorValid:
+    raise newException(EInvalidValue, "Invalid IP Address")
+  result.address_v4[byteCount] = cast[uint8](currentByte)
+
+proc parseIPv6Address(address_str: string): TIpAddress =
+  ## Parses IPv6 adresses
+  ## Raises EInvalidValue on errors
+  result.family = IpAddressFamily.IPv6
+  if address_str.len < 2:
+    raise newException(EInvalidValue, "Invalid IP Address")
+
+  var
+    groupCount = 0
+    currentGroupStart = 0
+    currentShort:uint32 = 0
+    seperatorValid = true
+    dualColonGroup = -1
+    lastWasColon = false
+    v4StartPos = -1
+    byteCount = 0
+
+  for i,c in address_str:
+    if c == ':':
+      if not seperatorValid:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Address contains an invalid seperator")
+      if lastWasColon:        
+        if dualColonGroup != -1:
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Address contains more than one \"::\" seperator")
+        dualColonGroup = groupCount
+        seperatorValid = false
+      elif i != 0 and i != high(address_str):
+        if groupCount >= 8:
+          raise newException(EInvalidValue,
+            "Invalid IP Address. The address consists of too many groups")
+        result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
+        result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
+        currentShort = 0
+        groupCount.inc()        
+        if dualColonGroup != -1: seperatorValid = false
+      elif i == 0: # only valid if address starts with ::
+        if address_str[1] != ':':
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Address may not start with \":\"")
+      else: # i == high(address_str) - only valid if address ends with ::
+        if address_str[high(address_str)-1] != ':': 
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Address may not end with \":\"")
+      lastWasColon = true
+      currentGroupStart = i + 1
+    elif c == '.': # Switch to parse IPv4 mode
+      if i < 3 or not seperatorValid or groupCount >= 7:
+        raise newException(EInvalidValue, "Invalid IP Address")
+      v4StartPos = currentGroupStart
+      currentShort = 0
+      seperatorValid = false
+      break
+    elif c in strutils.HexDigits:
+      if c in strutils.Digits: # Normal digit
+        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('0'))
+      elif c >= 'a' and c <= 'f': # Lower case hex
+        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10
+      else: # Upper case hex
+        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10
+      if currentShort > 65535'u32:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Value is out of range")
+      lastWasColon = false
+      seperatorValid = true
+    else:
+      raise newException(EInvalidValue,
+        "Invalid IP Address. Address contains an invalid character")
+
+
+  if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff
+    if seperatorValid: # Copy remaining data
+      if groupCount >= 8:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. The address consists of too many groups")
+      result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
+      result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
+      groupCount.inc()
+  else: # Must parse IPv4 address
+    for i,c in address_str[v4StartPos..high(address_str)]:
+      if c in strutils.Digits: # Character is a number
+        currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0'))
+        if currentShort > 255'u32:
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Value is out of range")
+        seperatorValid = true
+      elif c == '.': # IPv4 address separator
+        if not seperatorValid or byteCount >= 3:
+          raise newException(EInvalidValue, "Invalid IP Address")
+        result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
+        currentShort = 0
+        byteCount.inc()
+        seperatorValid = false
+      else: # Invalid character
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Address contains an invalid character")
+
+    if byteCount != 3 or not seperatorValid:
+      raise newException(EInvalidValue, "Invalid IP Address")
+    result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
+    groupCount += 2
+
+  # Shift and fill zeros in case of ::
+  if groupCount > 8:
+    raise newException(EInvalidValue,
+      "Invalid IP Address. The address consists of too many groups")
+  elif groupCount < 8: # must fill
+    if dualColonGroup == -1:
+      raise newException(EInvalidValue,
+        "Invalid IP Address. The address consists of too few groups")
+    var toFill = 8 - groupCount # The number of groups to fill
+    var toShift = groupCount - dualColonGroup # Nr of known groups after ::
+    for i in 0..2*toShift-1: # shift
+      result.address_v6[15-i] = result.address_v6[groupCount*2-i-1]
+    for i in 0..2*toFill-1: # fill with 0s
+      result.address_v6[dualColonGroup*2+i] = 0
+  elif dualColonGroup != -1:
+    raise newException(EInvalidValue,
+      "Invalid IP Address. The address consists of too many groups")
+
+proc parseIpAddress*(address_str: string): TIpAddress =
+  ## Parses an IP address
+  ## Raises EInvalidValue on error
+  if address_str == nil:
+    raise newException(EInvalidValue, "IP Address string is nil")
+  if address_str.contains(':'):
+    return parseIPv6Address(address_str)
+  else:
+    return parseIPv4Address(address_str)
diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim
index ab7cd1944d..6f94d0656a 100644
--- a/lib/pure/nimprof.nim
+++ b/lib/pure/nimprof.nim
@@ -26,7 +26,7 @@ const
   withThreads = compileOption("threads")
   tickCountCorrection = 50_000
 
-when not defined(system.TStackTrace):
+when not declared(system.TStackTrace):
   type TStackTrace = array [0..20, cstring]
 
 # We use a simple hash table of bounded size to keep track of the stack traces:
@@ -146,7 +146,7 @@ proc `//`(a, b: int): string =
   result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2))
 
 proc writeProfile() {.noconv.} =
-  when defined(system.TStackTrace):
+  when declared(system.TStackTrace):
     system.profilerHook = nil
   const filename = "profile_results.txt"
   echo "writing " & filename & "..."
@@ -189,16 +189,16 @@ var
   disabled: int
 
 proc disableProfiling*() =
-  when defined(system.TStackTrace):
+  when declared(system.TStackTrace):
     atomicDec disabled
     system.profilerHook = nil
 
 proc enableProfiling*() =
-  when defined(system.TStackTrace):
+  when declared(system.TStackTrace):
     if atomicInc(disabled) >= 0:
       system.profilerHook = hook
 
-when defined(system.TStackTrace):
+when declared(system.TStackTrace):
   system.profilerHook = hook
   addQuitProc(writeProfile)
 
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 0b4538abc7..71089494f0 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -365,8 +365,9 @@ when defined(windows):
     template getFilename(f: expr): expr = $f.cFilename
 
   proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} =
+    # Note - takes advantage of null delimiter in the cstring
     const dot = ord('.')
-    result = f.cFileName[0].int == dot and(f.cFileName[1].int == 0 or
+    result = f.cFileName[0].int == dot and (f.cFileName[1].int == 0 or
              f.cFileName[1].int == dot and f.cFileName[2].int == 0)
 
 proc existsFile*(filename: string): bool {.rtl, extern: "nos$1",
@@ -955,11 +956,12 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
   ##
   ## If this fails, `EOS` is raised. On the Windows platform this proc will
   ## copy the source file's attributes into dest. On other platforms you need
-  ## to use getFilePermissions and setFilePermissions to copy them by hand (or
-  ## use the convenience copyFileWithPermissions() proc), otherwise `dest` will
-  ## inherit the default permissions of a newly created file for the user. If
-  ## `dest` already exists, the file attributes will be preserved and the
-  ## content overwritten.
+  ## to use `getFilePermissions() <#getFilePermissions>`_ and
+  ## `setFilePermissions() <#setFilePermissions>`_ to copy them by hand (or use
+  ## the convenience `copyFileWithPermissions() <#copyFileWithPermissions>`_
+  ## proc), otherwise `dest` will inherit the default permissions of a newly
+  ## created file for the user. If `dest` already exists, the file attributes
+  ## will be preserved and the content overwritten.
   when defined(Windows):
     when useWinUnicode:
       let s = newWideCString(source)
@@ -996,7 +998,7 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
   if c_rename(source, dest) != 0'i32:
     raise newException(EOS, $strerror(errno))
 
-when not defined(ENOENT) and not defined(Windows):
+when not declared(ENOENT) and not defined(Windows):
   when NoFakeVars:
     const ENOENT = cint(2) # 2 on most systems including Solaris
   else:
@@ -1330,10 +1332,10 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
 
 proc rawCreateDir(dir: string) =
   when defined(solaris):
-    if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST and errno != ENOSYS:
+    if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST and errno != ENOSYS:
       osError(osLastError())
   elif defined(unix):
-    if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST:
+    if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST:
       osError(osLastError())
   else:
     when useWinUnicode:
@@ -1363,7 +1365,13 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
 
 proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
   tags: [FWriteIO, FReadIO].} =
-  ## Copies a directory from `source` to `dest`. If this fails, `EOS` is raised.
+  ## Copies a directory from `source` to `dest`.
+  ##
+  ## If this fails, `EOS` is raised. On the Windows platform this proc will
+  ## copy the attributes from `source` into `dest`. On other platforms created
+  ## files and directories will inherit the default permissions of a newly
+  ## created file/directory for the user. To preserve attributes recursively on
+  ## these platforms use `copyDirWithPermissions() <#copyDirWithPermissions>`_.
   createDir(dest)
   for kind, path in walkDir(source):
     var noSource = path.substr(source.len()+1)
@@ -1450,7 +1458,8 @@ proc parseCmdLine*(c: string): seq[string] {.
   var a = ""
   while true:
     setLen(a, 0)
-    while c[i] == ' ' or c[i] == '\t': inc(i)
+    # eat all delimiting whitespace
+    while c[i] == ' ' or c[i] == '\t' or c [i] == '\l' or c [i] == '\r' : inc(i)
     when defined(windows):
       # parse a single argument according to the above rules:
       if c[i] == '\0': break
@@ -1507,14 +1516,17 @@ proc copyFileWithPermissions*(source, dest: string,
                               ignorePermissionErrors = true) =
   ## Copies a file from `source` to `dest` preserving file permissions.
   ##
-  ## This is a wrapper proc around copyFile, getFilePermissions and
-  ## setFilePermissions on non Windows platform. On windows this proc is just a
-  ## wrapper for copyFile since that proc already copies attributes.
+  ## This is a wrapper proc around `copyFile() <#copyFile>`_,
+  ## `getFilePermissions() <#getFilePermissions>`_ and `setFilePermissions()
+  ## <#setFilePermissions>`_ on non Windows platform. On Windows this proc is
+  ## just a wrapper for `copyFile() <#copyFile>`_ since that proc already
+  ## copies attributes.
   ##
-  ## On non windows systems permissions are copied after the file itself has
+  ## On non Windows systems permissions are copied after the file itself has
   ## been copied, which won't happen atomically and could lead to a race
-  ## condition. If ignorePermissionErrors is true, errors while reading/setting
-  ## file attributes will be ignored, otherwise will raise `OSError`.
+  ## condition. If `ignorePermissionErrors` is true, errors while
+  ## reading/setting file attributes will be ignored, otherwise will raise
+  ## `OSError`.
   copyFile(source, dest)
   when not defined(Windows):
     try:
@@ -1523,6 +1535,37 @@ proc copyFileWithPermissions*(source, dest: string,
       if not ignorePermissionErrors:
         raise
 
+proc copyDirWithPermissions*(source, dest: string,
+    ignorePermissionErrors = true) {.rtl, extern: "nos$1",
+    tags: [FWriteIO, FReadIO].} =
+  ## Copies a directory from `source` to `dest` preserving file permissions.
+  ##
+  ## If this fails, `EOS` is raised. This is a wrapper proc around `copyDir()
+  ## <#copyDir>`_ and `copyFileWithPermissions() <#copyFileWithPermissions>`_
+  ## on non Windows platforms. On Windows this proc is just a wrapper for
+  ## `copyDir() <#copyDir>`_ since that proc already copies attributes.
+  ##
+  ## On non Windows systems permissions are copied after the file or directory
+  ## itself has been copied, which won't happen atomically and could lead to a
+  ## race condition. If `ignorePermissionErrors` is true, errors while
+  ## reading/setting file attributes will be ignored, otherwise will raise
+  ## `OSError`.
+  createDir(dest)
+  when not defined(Windows):
+    try:
+      setFilePermissions(dest, getFilePermissions(source))
+    except:
+      if not ignorePermissionErrors:
+        raise
+  for kind, path in walkDir(source):
+    var noSource = path.substr(source.len()+1)
+    case kind
+    of pcFile:
+      copyFileWithPermissions(path, dest / noSource, ignorePermissionErrors)
+    of pcDir:
+      copyDirWithPermissions(path, dest / noSource, ignorePermissionErrors)
+    else: discard
+
 proc inclFilePermissions*(filename: string,
                           permissions: set[TFilePermission]) {.
   rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} =
@@ -1560,7 +1603,52 @@ proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
   when defined(windows): return string(getEnv("TEMP")) & "\\"
   else: return "/tmp/"
 
-when defined(windows):
+when defined(nimdoc):
+  # Common forward declaration docstring block for parameter retrieval procs.
+  proc paramCount*(): int {.tags: [FReadIO].} =
+    ## Returns the number of `command line arguments`:idx: given to the
+    ## application.
+    ##
+    ## If your binary was called without parameters this will return zero.  You
+    ## can later query each individual paramater with `paramStr() <#paramStr>`_
+    ## or retrieve all of them in one go with `commandLineParams()
+    ## <#commandLineParams>`_.
+    ##
+    ## **Availability**: On Posix there is no portable way to get the command
+    ## line from a DLL and thus the proc isn't defined in this environment. You
+    ## can test for its availability with `declared() `_.
+    ## Example:
+    ##
+    ## .. code-block:: nimrod
+    ##   when declared(paramCount):
+    ##     # Use paramCount() here
+    ##   else:
+    ##     # Do something else!
+
+  proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} =
+    ## Returns the `i`-th `command line argument`:idx: given to the application.
+    ##
+    ## `i` should be in the range `1..paramCount()`, the `EInvalidIndex`
+    ## exception will be raised for invalid values.  Instead of iterating over
+    ## `paramCount() <#paramCount>`_ with this proc you can call the
+    ## convenience `commandLineParams() <#commandLineParams>`_.
+    ##
+    ## It is possible to call ``paramStr(0)`` but this will return OS specific
+    ## contents (usually the name of the invoked executable). You should avoid
+    ## this and call `getAppFilename() <#getAppFilename>`_ instead.
+    ##
+    ## **Availability**: On Posix there is no portable way to get the command
+    ## line from a DLL and thus the proc isn't defined in this environment. You
+    ## can test for its availability with `declared() `_.
+    ## Example:
+    ##
+    ## .. code-block:: nimrod
+    ##   when declared(paramStr):
+    ##     # Use paramStr() here
+    ##   else:
+    ##     # Do something else!
+
+elif defined(windows):
   # Since we support GUI applications with Nimrod, we sometimes generate
   # a WinMain entry proc. But a WinMain proc has no access to the parsed
   # command line arguments. The way to get them differs. Thus we parse them
@@ -1570,18 +1658,13 @@ when defined(windows):
     ownArgv {.threadvar.}: seq[string]
 
   proc paramCount*(): int {.rtl, extern: "nos$1", tags: [FReadIO].} =
-    ## Returns the number of `command line arguments`:idx: given to the
-    ## application.
+    # Docstring in nimdoc block.
     if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
     result = ownArgv.len-1
 
   proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1",
     tags: [FReadIO].} =
-    ## Returns the `i`-th `command line argument`:idx: given to the
-    ## application.
-    ##
-    ## `i` should be in the range `1..paramCount()`, else
-    ## the `EOutOfIndex` exception is raised.
+    # Docstring in nimdoc block.
     if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
     return TaintedString(ownArgv[i])
 
@@ -1592,13 +1675,31 @@ elif not defined(createNimRtl):
     cmdLine {.importc: "cmdLine".}: cstringArray
 
   proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} =
+    # Docstring in nimdoc block.
     if i < cmdCount and i >= 0: return TaintedString($cmdLine[i])
     raise newException(EInvalidIndex, "invalid index")
 
-  proc paramCount*(): int {.tags: [FReadIO].} = return cmdCount-1
+  proc paramCount*(): int {.tags: [FReadIO].} =
+    # Docstring in nimdoc block.
+    result = cmdCount-1
 
-when defined(paramCount):
+when declared(paramCount) or defined(nimdoc):
   proc commandLineParams*(): seq[TaintedString] =
+    ## Convenience proc which returns the command line parameters.
+    ##
+    ## This returns **only** the parameters. If you want to get the application
+    ## executable filename, call `getAppFilename() <#getAppFilename>`_.
+    ##
+    ## **Availability**: On Posix there is no portable way to get the command
+    ## line from a DLL and thus the proc isn't defined in this environment. You
+    ## can test for its availability with `declared() `_.
+    ## Example:
+    ##
+    ## .. code-block:: nimrod
+    ##   when declared(commandLineParams):
+    ##     # Use commandLineParams() here
+    ##   else:
+    ##     # Do something else!
     result = @[]
     for i in 1..paramCount():
       result.add(paramStr(i))
@@ -1614,7 +1715,7 @@ when defined(linux) or defined(solaris) or defined(bsd) or defined(aix):
 
 when not (defined(windows) or defined(macosx)):
   proc getApplHeuristic(): string =
-    when defined(paramStr):
+    when declared(paramStr):
       result = string(paramStr(0))
       # POSIX guaranties that this contains the executable
       # as it has been executed by the calling process
@@ -1761,12 +1862,12 @@ proc expandTilde*(path: string): string =
 
 when defined(Windows):
   type
-    DeviceId = int32
-    FileId = int64
+    DeviceId* = int32
+    FileId* = int64
 else:
   type
-    DeviceId = TDev
-    FileId = TIno
+    DeviceId* = TDev
+    FileId* = TIno
 
 type
   FileInfo* = object
@@ -1809,6 +1910,7 @@ template rawToFormalFileInfo(rawInfo, formalInfo): expr =
     if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
       formalInfo.kind = succ(result.kind)
 
+
   else:
     template checkAndIncludeMode(rawMode, formalMode: expr) = 
       if (rawInfo.st_mode and rawMode) != 0'i32:
@@ -1895,4 +1997,26 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo =
         osError(osLastError())
     rawToFormalFileInfo(rawInfo, result)
 
+proc isHidden*(path: string): bool =
+  ## Determines whether a given path is hidden or not. Returns false if the
+  ## file doesn't exist. The given path must be accessible from the current
+  ## working directory of the program.
+  ## 
+  ## On Windows, a file is hidden if the file's 'hidden' attribute is set.
+  ## On Unix-like systems, a file is hidden if it starts with a '.' (period)
+  ## and is not *just* '.' or '..' ' ."
+  when defined(Windows):
+    wrapUnary(attributes, getFileAttributesW, path)
+    if attributes != -1'i32:
+      result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32
+  else:
+    if fileExists(path):
+      let
+        fileName = extractFilename(path)
+        nameLen = len(fileName)
+      if nameLen == 2:
+        result = (fileName[0] == '.') and (fileName[1] != '.')
+      elif nameLen > 2:
+        result = (fileName[0] == '.') and (fileName[3] != '.')
+
 {.pop.}
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 04a0c2403a..3c181bf533 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -643,7 +643,7 @@ elif not defined(useNimRtl):
     data.workingDir = workingDir
 
 
-    when defined(posix_spawn) and not defined(useFork) and 
+    when declared(posix_spawn) and not defined(useFork) and 
         not defined(useClone) and not defined(linux):
       pid = startProcessAuxSpawn(data)
     else:
@@ -763,7 +763,7 @@ elif not defined(useNimRtl):
     discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error))
     exitnow(1)
 
-  when defined(macosx):
+  when defined(macosx) or defined(freebsd):
     var environ {.importc.}: cstringArray
 
   proc startProcessAfterFork(data: ptr TStartProcessData) =
@@ -793,7 +793,7 @@ elif not defined(useNimRtl):
     discard fcntl(data.pErrorPipe[writeIdx], F_SETFD, FD_CLOEXEC)
 
     if data.optionPoUsePath:
-      when defined(macosx):
+      when defined(macosx) or defined(freebsd):
         # MacOSX doesn't have execvpe, so we need workaround.
         # On MacOSX we can arrive here only from fork, so this is safe:
         environ = data.sysEnv
diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim
index 727a8efd83..1d61a967b3 100644
--- a/lib/pure/parsecfg.nim
+++ b/lib/pure/parsecfg.nim
@@ -350,7 +350,8 @@ proc next*(c: var TCfgParser): TCfgEvent {.rtl, extern: "npc$1".} =
     rawGetTok(c, c.tok)
     if c.tok.kind == tkBracketRi: 
       rawGetTok(c, c.tok)
-    else: 
+    else:
+      reset(result)
       result.kind = cfgError
       result.msg = errorStr(c, "']' expected, but found: " & c.tok.literal)
   of tkInvalid, tkEquals, tkColon, tkBracketRi: 
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index 68ae537c77..f43853fe68 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -37,7 +37,7 @@ type
                               ## or the argument, ``value`` is not "" if
                               ## the option was given a value
 
-when defined(os.paramCount):
+when declared(os.paramCount):
   # we cannot provide this for NimRtl creation on Posix, because we can't 
   # access the command line arguments then!
 
@@ -127,7 +127,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {.
   ## retrieves the rest of the command line that has not been parsed yet.
   result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString
 
-when defined(initOptParser):
+when declared(initOptParser):
 
   iterator getopt*(): tuple[kind: TCmdLineKind, key, val: TaintedString] =
     ## This is an convenience iterator for iterating over the command line.
diff --git a/lib/pure/parseopt2.nim b/lib/pure/parseopt2.nim
index 5e79d8a180..7638171d1d 100644
--- a/lib/pure/parseopt2.nim
+++ b/lib/pure/parseopt2.nim
@@ -119,7 +119,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {.rtl, extern: "npo$1", deprecat
 type
   TGetoptResult* = tuple[kind: TCmdLineKind, key, val: TaintedString]
 
-when defined(paramCount):
+when declared(paramCount):
   iterator getopt*(): TGetoptResult =
     ## This is an convenience iterator for iterating over the command line.
     ## This uses the TOptParser object. Example:
diff --git a/lib/pure/parseurl.nim b/lib/pure/parseurl.nim
index 357d1df0ff..67c6de9050 100644
--- a/lib/pure/parseurl.nim
+++ b/lib/pure/parseurl.nim
@@ -20,7 +20,7 @@ type
     scheme, username, password, 
     hostname, port, path, query, anchor: string]
     
-proc parseUrl*(url: string): TUrl =
+proc parseUrl*(url: string): TUrl {.deprecated.} =
   var i = 0
 
   var scheme, username, password: string = ""
@@ -86,7 +86,7 @@ proc parseUrl*(url: string): TUrl =
     
   return (scheme, username, password, hostname, port, path, query, anchor)
 
-proc `$`*(u: TUrl): string =
+proc `$`*(u: TUrl): string {.deprecated.} =
   ## turns the URL `u` into its string representation.
   result = ""
   if u.scheme.len > 0:
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index 484ba5184d..06ee07aa83 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -231,88 +231,96 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
   else:
     number = int(res)
 
-proc tenToThePowerOf(b: int): BiggestFloat =
-  var b = b
-  var a = 10.0
-  result = 1.0
-  while true:
-    if (b and 1) == 1:
-      result *= a
-    b = b shr 1
-    if b == 0: break
-    a *= a
+when defined(nimParseBiggestFloatMagic):
+  proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
+    magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.}
+    ## parses a float starting at `start` and stores the value into `number`.
+    ## Result is the number of processed chars or 0 if a parsing error
+    ## occurred.
+else:
+  proc tenToThePowerOf(b: int): BiggestFloat =
+    var b = b
+    var a = 10.0
+    result = 1.0
+    while true:
+      if (b and 1) == 1:
+        result *= a
+      b = b shr 1
+      if b == 0: break
+      a *= a
 
-proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
-  rtl, extern: "npuParseBiggestFloat", noSideEffect.} =
-  ## parses a float starting at `start` and stores the value into `number`.
-  ## Result is the number of processed chars or 0 if there occured a parsing
-  ## error.
-  var
-    esign = 1.0
-    sign = 1.0
-    i = start
-    exponent: int
-    flags: int
-  number = 0.0
-  if s[i] == '+': inc(i)
-  elif s[i] == '-':
-    sign = -1.0
-    inc(i)
-  if s[i] == 'N' or s[i] == 'n':
-    if s[i+1] == 'A' or s[i+1] == 'a':
-      if s[i+2] == 'N' or s[i+2] == 'n':
-        if s[i+3] notin IdentChars:
-          number = NaN
-          return i+3 - start
-    return 0
-  if s[i] == 'I' or s[i] == 'i':
-    if s[i+1] == 'N' or s[i+1] == 'n':
-      if s[i+2] == 'F' or s[i+2] == 'f':
-        if s[i+3] notin IdentChars: 
-          number = Inf*sign
-          return i+3 - start
-    return 0
-  while s[i] in {'0'..'9'}:
-    # Read integer part
-    flags = flags or 1
-    number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
-    inc(i)
-    while s[i] == '_': inc(i)
-  # Decimal?
-  if s[i] == '.':
-    var hd = 1.0
-    inc(i)
-    while s[i] in {'0'..'9'}:
-      # Read fractional part
-      flags = flags or 2
-      number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
-      hd = hd * 10.0
-      inc(i)
-      while s[i] == '_': inc(i)
-    number = number / hd # this complicated way preserves precision
-  # Again, read integer and fractional part
-  if flags == 0: return 0
-  # Exponent?
-  if s[i] in {'e', 'E'}:
-    inc(i)
-    if s[i] == '+':
-      inc(i)
+  proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
+    rtl, extern: "npuParseBiggestFloat", noSideEffect.} =
+    ## parses a float starting at `start` and stores the value into `number`.
+    ## Result is the number of processed chars or 0 if there occured a parsing
+    ## error.
+    var
+      esign = 1.0
+      sign = 1.0
+      i = start
+      exponent: int
+      flags: int
+    number = 0.0
+    if s[i] == '+': inc(i)
     elif s[i] == '-':
-      esign = -1.0
+      sign = -1.0
       inc(i)
-    if s[i] notin {'0'..'9'}:
+    if s[i] == 'N' or s[i] == 'n':
+      if s[i+1] == 'A' or s[i+1] == 'a':
+        if s[i+2] == 'N' or s[i+2] == 'n':
+          if s[i+3] notin IdentChars:
+            number = NaN
+            return i+3 - start
+      return 0
+    if s[i] == 'I' or s[i] == 'i':
+      if s[i+1] == 'N' or s[i+1] == 'n':
+        if s[i+2] == 'F' or s[i+2] == 'f':
+          if s[i+3] notin IdentChars: 
+            number = Inf*sign
+            return i+3 - start
       return 0
     while s[i] in {'0'..'9'}:
-      exponent = exponent * 10 + ord(s[i]) - ord('0')
+      # Read integer part
+      flags = flags or 1
+      number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
       inc(i)
       while s[i] == '_': inc(i)
-  # Calculate Exponent
-  let hd = tenToThePowerOf(exponent)
-  if esign > 0.0: number = number * hd
-  else:           number = number / hd
-  # evaluate sign
-  number = number * sign
-  result = i - start
+    # Decimal?
+    if s[i] == '.':
+      var hd = 1.0
+      inc(i)
+      while s[i] in {'0'..'9'}:
+        # Read fractional part
+        flags = flags or 2
+        number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
+        hd = hd * 10.0
+        inc(i)
+        while s[i] == '_': inc(i)
+      number = number / hd # this complicated way preserves precision
+    # Again, read integer and fractional part
+    if flags == 0: return 0
+    # Exponent?
+    if s[i] in {'e', 'E'}:
+      inc(i)
+      if s[i] == '+':
+        inc(i)
+      elif s[i] == '-':
+        esign = -1.0
+        inc(i)
+      if s[i] notin {'0'..'9'}:
+        return 0
+      while s[i] in {'0'..'9'}:
+        exponent = exponent * 10 + ord(s[i]) - ord('0')
+        inc(i)
+        while s[i] == '_': inc(i)
+    # Calculate Exponent
+    let hd = tenToThePowerOf(exponent)
+    if esign > 0.0: number = number * hd
+    else:           number = number / hd
+    # evaluate sign
+    number = number * sign
+    result = i - start
+
 
 proc parseFloat*(s: string, number: var float, start = 0): int {.
   rtl, extern: "npuParseFloat", noSideEffect.} =
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 68b1ab2237..efe169c1d1 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -870,7 +870,7 @@ template `=~`*(s: string, pattern: TPeg): bool =
   ##     echo("syntax error")
   ##  
   bind maxSubpatterns
-  when not definedInScope(matches):
+  when not declaredInScope(matches):
     var matches {.inject.}: array[0..MaxSubpatterns-1, string]
   match(s, pattern, matches)
 
diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim
index d96741846e..fea09dfa25 100644
--- a/lib/pure/rawsockets.nim
+++ b/lib/pure/rawsockets.nim
@@ -22,7 +22,7 @@ const useWinVersion = defined(Windows) or defined(nimdoc)
 when useWinVersion:
   import winlean
   export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
-         WSAEDISCON
+         WSAEDISCON, ERROR_NETNAME_DELETED
 else:
   import posix
   export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL,
diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim
index 4a6c3f5306..eb3792bcea 100644
--- a/lib/pure/ropes.nim
+++ b/lib/pure/ropes.nim
@@ -58,8 +58,8 @@ proc newRope(data: string): PRope =
   result.data = data
 
 var 
-  cache: PRope                # the root of the cache tree
-  N: PRope                    # dummy rope needed for splay algorithm
+  cache {.threadvar.}: PRope     # the root of the cache tree
+  N {.threadvar.}: PRope         # dummy rope needed for splay algorithm
 
 when countCacheMisses:
   var misses, hits: int
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index e642f6a99d..1d17de2338 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -48,9 +48,11 @@ const
     ## the set of characters a newline terminator can start with
 
   AllChars* = {'\x00'..'\xFF'}
-    ## A set with all the possible characters. Not very useful by its own, you
-    ## can use it to create *inverted* sets to make the ``find()`` proc find
-    ## **invalid** characters in strings. Example:
+    ## A set with all the possible characters.
+    ##
+    ## Not very useful by its own, you can use it to create *inverted* sets to
+    ## make the `find() proc <#find,string,set[char],int>`_ find **invalid**
+    ## characters in strings.  Example:
     ##
     ## .. code-block:: nimrod
     ##   let invalid = AllChars - Digits
@@ -59,8 +61,11 @@ const
 
 proc toLower*(c: char): char {.noSideEffect, procvar,
   rtl, extern: "nsuToLowerChar".} =
-  ## Converts `c` into lower case. This works only for the letters A-Z.
-  ## See `unicode.toLower` for a version that works for any Unicode character.
+  ## Converts `c` into lower case.
+  ##
+  ## This works only for the letters ``A-Z``. See `unicode.toLower
+  ## `_ for a version that works for any Unicode
+  ## character.
   if c in {'A'..'Z'}:
     result = chr(ord(c) + (ord('a') - ord('A')))
   else:
@@ -68,16 +73,22 @@ proc toLower*(c: char): char {.noSideEffect, procvar,
 
 proc toLower*(s: string): string {.noSideEffect, procvar,
   rtl, extern: "nsuToLowerStr".} =
-  ## Converts `s` into lower case. This works only for the letters A-Z.
-  ## See `unicode.toLower` for a version that works for any Unicode character.
+  ## Converts `s` into lower case.
+  ##
+  ## This works only for the letters ``A-Z``. See `unicode.toLower
+  ## `_ for a version that works for any Unicode
+  ## character.
   result = newString(len(s))
   for i in 0..len(s) - 1:
     result[i] = toLower(s[i])
 
 proc toUpper*(c: char): char {.noSideEffect, procvar,
   rtl, extern: "nsuToUpperChar".} =
-  ## Converts `c` into upper case. This works only for the letters a-z.
-  ## See `unicode.toUpper` for a version that works for any Unicode character.
+  ## Converts `c` into upper case.
+  ##
+  ## This works only for the letters ``A-Z``.  See `unicode.toUpper
+  ## `_ for a version that works for any Unicode
+  ## character.
   if c in {'a'..'z'}:
     result = chr(ord(c) - (ord('a') - ord('A')))
   else:
@@ -85,8 +96,11 @@ proc toUpper*(c: char): char {.noSideEffect, procvar,
 
 proc toUpper*(s: string): string {.noSideEffect, procvar,
   rtl, extern: "nsuToUpperStr".} =
-  ## Converts `s` into upper case. This works only for the letters a-z.
-  ## See `unicode.toUpper` for a version that works for any Unicode character.
+  ## Converts `s` into upper case.
+  ##
+  ## This works only for the letters ``A-Z``.  See `unicode.toUpper
+  ## `_ for a version that works for any Unicode
+  ## character.
   result = newString(len(s))
   for i in 0..len(s) - 1:
     result[i] = toUpper(s[i])
@@ -94,13 +108,16 @@ proc toUpper*(s: string): string {.noSideEffect, procvar,
 proc capitalize*(s: string): string {.noSideEffect, procvar,
   rtl, extern: "nsuCapitalize".} =
   ## Converts the first character of `s` into upper case.
-  ## This works only for the letters a-z.
+  ##
+  ## This works only for the letters ``A-Z``.
   result = toUpper(s[0]) & substr(s, 1)
 
 proc normalize*(s: string): string {.noSideEffect, procvar,
   rtl, extern: "nsuNormalize".} =
-  ## Normalizes the string `s`. That means to convert it to lower case and
-  ## remove any '_'. This is needed for Nimrod identifiers for example.
+  ## Normalizes the string `s`.
+  ##
+  ## That means to convert it to lower case and remove any '_'. This is needed
+  ## for Nimrod identifiers for example.
   result = newString(s.len)
   var j = 0
   for i in 0..len(s) - 1:
@@ -155,6 +172,7 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
 proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect,
   rtl, extern: "nsuStrip", operator: 5.} =
   ## Strips whitespace from `s` and returns the resulting string.
+  ##
   ## If `leading` is true, leading whitespace is stripped.
   ## If `trailing` is true, trailing whitespace is stripped.
   const
@@ -169,8 +187,10 @@ proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect,
   result = substr(s, first, last)
 
 proc toOctal*(c: char): string {.noSideEffect, rtl, extern: "nsuToOctal".} =
-  ## Converts a character `c` to its octal representation. The resulting
-  ## string may not have a leading zero. Its length is always exactly 3.
+  ## Converts a character `c` to its octal representation.
+  ##
+  ## The resulting string may not have a leading zero. Its length is always
+  ## exactly 3.
   result = newString(3)
   var val = ord(c)
   for i in countdown(2, 0):
@@ -280,9 +300,11 @@ iterator split*(s: string, sep: string): string =
       inc(last, sep.len)
 
 iterator splitLines*(s: string): string =
-  ## Splits the string `s` into its containing lines. Every newline
-  ## combination (CR, LF, CR-LF) is supported. The result strings contain
-  ## no trailing ``\n``.
+  ## Splits the string `s` into its containing lines.
+  ##
+  ## Every `character literal `_ newline
+  ## combination (CR, LF, CR-LF) is supported. The result strings contain no
+  ## trailing ``\n``.
   ##
   ## Example:
   ##
@@ -315,13 +337,25 @@ iterator splitLines*(s: string): string =
 
 proc splitLines*(s: string): seq[string] {.noSideEffect,
   rtl, extern: "nsuSplitLines".} =
-  ## The same as the `splitLines` iterator, but is a proc that returns a
-  ## sequence of substrings.
+  ## The same as the `splitLines <#splitLines.i,string>`_ iterator, but is a
+  ## proc that returns a sequence of substrings.
   accumulateResult(splitLines(s))
 
 proc countLines*(s: string): int {.noSideEffect,
   rtl, extern: "nsuCountLines".} =
-  ## same as ``len(splitLines(s))``, but much more efficient.
+  ## Returns the number of new line separators in the string `s`.
+  ##
+  ## This is the same as ``len(splitLines(s))``, but much more efficient
+  ## because it doesn't modify the string creating temporal objects. Every
+  ## `character literal `_ newline combination
+  ## (CR, LF, CR-LF) is supported.
+  ##
+  ## Despite its name this proc might not actually return the *number of lines*
+  ## in `s` because the concept of what a line is can vary. For example, a
+  ## string like ``Hello world`` is a line of text, but the proc will return a
+  ## value of zero because there are no newline separators.  Also, text editors
+  ## usually don't count trailing newline characters in a text file as a new
+  ## empty line, but this proc will.
   var i = 0
   while i < s.len:
     case s[i]
@@ -334,28 +368,30 @@ proc countLines*(s: string): int {.noSideEffect,
 
 proc split*(s: string, seps: set[char] = Whitespace): seq[string] {.
   noSideEffect, rtl, extern: "nsuSplitCharSet".} =
-  ## The same as the `split` iterator, but is a proc that returns a
-  ## sequence of substrings.
+  ## The same as the `split iterator <#split.i,string,set[char]>`_, but is a
+  ## proc that returns a sequence of substrings.
   accumulateResult(split(s, seps))
 
 proc split*(s: string, sep: char): seq[string] {.noSideEffect,
   rtl, extern: "nsuSplitChar".} =
-  ## The same as the `split` iterator, but is a proc that returns a sequence
-  ## of substrings.
+  ## The same as the `split iterator <#split.i,string,char>`_, but is a proc
+  ## that returns a sequence of substrings.
   accumulateResult(split(s, sep))
 
 proc split*(s: string, sep: string): seq[string] {.noSideEffect,
   rtl, extern: "nsuSplitString".} =
   ## Splits the string `s` into substrings using a string separator.
   ##
-  ## Substrings are separated by the string `sep`.
+  ## Substrings are separated by the string `sep`. This is a wrapper around the
+  ## `split iterator <#split.i,string,string>`_.
   accumulateResult(split(s, sep))
 
 proc toHex*(x: BiggestInt, len: int): string {.noSideEffect,
   rtl, extern: "nsuToHex".} =
-  ## Converts `x` to its hexadecimal representation. The resulting string
-  ## will be exactly `len` characters long. No prefix like ``0x``
-  ## is generated. `x` is treated as an unsigned value.
+  ## Converts `x` to its hexadecimal representation.
+  ##
+  ## The resulting string will be exactly `len` characters long. No prefix like
+  ## ``0x`` is generated. `x` is treated as an unsigned value.
   const
     HexChars = "0123456789ABCDEF"
   var
@@ -367,9 +403,10 @@ proc toHex*(x: BiggestInt, len: int): string {.noSideEffect,
 
 proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect,
   rtl, extern: "nsuIntToStr".} =
-  ## Converts `x` to its decimal representation. The resulting string
-  ## will be minimally `minchars` characters long. This is achieved by
-  ## adding leading zeros.
+  ## Converts `x` to its decimal representation.
+  ##
+  ## The resulting string will be minimally `minchars` characters long. This is
+  ## achieved by adding leading zeros.
   result = $abs(x)
   for i in 1 .. minchars - len(result):
     result = '0' & result
@@ -378,16 +415,18 @@ proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect,
 
 proc parseInt*(s: string): int {.noSideEffect, procvar,
   rtl, extern: "nsuParseInt".} =
-  ## Parses a decimal integer value contained in `s`. If `s` is not
-  ## a valid integer, `EInvalidValue` is raised.
+  ## Parses a decimal integer value contained in `s`.
+  ##
+  ## If `s` is not a valid integer, `EInvalidValue` is raised.
   var L = parseutils.parseInt(s, result, 0)
   if L != s.len or L == 0:
     raise newException(EInvalidValue, "invalid integer: " & s)
 
 proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar,
   rtl, extern: "nsuParseBiggestInt".} =
-  ## Parses a decimal integer value contained in `s`. If `s` is not
-  ## a valid integer, `EInvalidValue` is raised.
+  ## Parses a decimal integer value contained in `s`.
+  ##
+  ## If `s` is not a valid integer, `EInvalidValue` is raised.
   var L = parseutils.parseBiggestInt(s, result, 0)
   if L != s.len or L == 0:
     raise newException(EInvalidValue, "invalid integer: " & s)
@@ -403,10 +442,11 @@ proc parseFloat*(s: string): float {.noSideEffect, procvar,
 
 proc parseHexInt*(s: string): int {.noSideEffect, procvar,
   rtl, extern: "nsuParseHexInt".} =
-  ## Parses a hexadecimal integer value contained in `s`. If `s` is not
-  ## a valid integer, `EInvalidValue` is raised. `s` can have one of the
-  ## following optional prefixes: ``0x``, ``0X``, ``#``.
-  ## Underscores within `s` are ignored.
+  ## Parses a hexadecimal integer value contained in `s`.
+  ##
+  ## If `s` is not a valid integer, `EInvalidValue` is raised. `s` can have one
+  ## of the following optional prefixes: ``0x``, ``0X``, ``#``.  Underscores
+  ## within `s` are ignored.
   var i = 0
   if s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2)
   elif s[i] == '#': inc(i)
@@ -426,26 +466,32 @@ proc parseHexInt*(s: string): int {.noSideEffect, procvar,
     else: raise newException(EInvalidValue, "invalid integer: " & s)
 
 proc parseBool*(s: string): bool =
-  ## Parses a value into a `bool`. If ``s`` is one of the following values:
-  ## ``y, yes, true, 1, on``, then returns `true`. If ``s`` is one of the
-  ## following values: ``n, no, false, 0, off``, then returns `false`.
-  ## If ``s`` is something else a ``EInvalidValue`` exception is raised.
+  ## Parses a value into a `bool`.
+  ##
+  ## If ``s`` is one of the following values: ``y, yes, true, 1, on``, then
+  ## returns `true`. If ``s`` is one of the following values: ``n, no, false,
+  ## 0, off``, then returns `false`.  If ``s`` is something else a
+  ## ``EInvalidValue`` exception is raised.
   case normalize(s)
   of "y", "yes", "true", "1", "on": result = true
   of "n", "no", "false", "0", "off": result = false
   else: raise newException(EInvalidValue, "cannot interpret as a bool: " & s)
 
 proc parseEnum*[T: enum](s: string): T =
-  ## parses an enum ``T``. Raises ``EInvalidValue`` for an invalid value in 
-  ## `s`. The comparison is done in a style insensitive way.
+  ## Parses an enum ``T``.
+  ##
+  ## Raises ``EInvalidValue`` for an invalid value in `s`. The comparison is
+  ## done in a style insensitive way.
   for e in low(T)..high(T):
     if cmpIgnoreStyle(s, $e) == 0:
       return e
   raise newException(EInvalidValue, "invalid enum value: " & s)
 
 proc parseEnum*[T: enum](s: string, default: T): T =
-  ## parses an enum ``T``. Uses `default` for an invalid value in 
-  ## `s`. The comparison is done in a style insensitive way.
+  ## Parses an enum ``T``.
+  ##
+  ## Uses `default` for an invalid value in `s`. The comparison is done in a
+  ## style insensitive way.
   for e in low(T)..high(T):
     if cmpIgnoreStyle(s, $e) == 0:
       return e
@@ -475,10 +521,11 @@ proc repeatStr*(count: int, s: string): string {.noSideEffect,
 proc align*(s: string, count: int, padding = ' '): string {.
   noSideEffect, rtl, extern: "nsuAlignString".} =
   ## Aligns a string `s` with `padding`, so that is of length `count`.
+  ##
   ## `padding` characters (by default spaces) are added before `s` resulting in
   ## right alignment. If ``s.len >= count``, no spaces are added and `s` is
-  ## returned unchanged. If you need to left align a string use the
-  ## ``repeatChar`` proc. Example:
+  ## returned unchanged. If you need to left align a string use the `repeatChar
+  ## proc <#repeatChar>`_. Example:
   ##
   ## .. code-block:: nimrod
   ##   assert align("abc", 4) == " abc"
@@ -532,10 +579,15 @@ proc wordWrap*(s: string, maxLineWidth = 80,
                seps: set[char] = Whitespace,
                newLine = "\n"): string {.
                noSideEffect, rtl, extern: "nsuWordWrap".} =
-  ## word wraps `s`.
+  ## Word wraps `s`.
   result = newStringOfCap(s.len + s.len shr 6)
   var spaceLeft = maxLineWidth
+  var lastSep = ""
   for word, isSep in tokenize(s, seps):
+    if isSep:
+      lastSep = word
+      spaceLeft = spaceLeft - len(word)
+      continue
     if len(word) > spaceLeft:
       if splitLongWords and len(word) > maxLineWidth:
         result.add(substr(word, 0, spaceLeft-1))
@@ -554,11 +606,12 @@ proc wordWrap*(s: string, maxLineWidth = 80,
         result.add(word)
     else:
       spaceLeft = spaceLeft - len(word)
-      result.add(word)
+      result.add(lastSep & word)
+      lastSep.setLen(0)
 
 proc unindent*(s: string, eatAllIndent = false): string {.
                noSideEffect, rtl, extern: "nsuUnindent".} =
-  ## unindents `s`.
+  ## Unindents `s`.
   result = newStringOfCap(s.len)
   var i = 0
   var pattern = true
@@ -586,6 +639,7 @@ proc unindent*(s: string, eatAllIndent = false): string {.
 proc startsWith*(s, prefix: string): bool {.noSideEffect,
   rtl, extern: "nsuStartsWith".} =
   ## Returns true iff ``s`` starts with ``prefix``.
+  ##
   ## If ``prefix == ""`` true is returned.
   var i = 0
   while true:
@@ -596,6 +650,7 @@ proc startsWith*(s, prefix: string): bool {.noSideEffect,
 proc endsWith*(s, suffix: string): bool {.noSideEffect,
   rtl, extern: "nsuEndsWith".} =
   ## Returns true iff ``s`` ends with ``suffix``.
+  ##
   ## If ``suffix == ""`` true is returned.
   var i = 0
   var j = len(s) - len(suffix)
@@ -607,6 +662,7 @@ proc endsWith*(s, suffix: string): bool {.noSideEffect,
 proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect,
   rtl, extern: "nsuContinuesWith".} =
   ## Returns true iff ``s`` continues with ``substr`` at position ``start``.
+  ##
   ## If ``substr == ""`` true is returned.
   var i = 0
   while true:
@@ -616,6 +672,8 @@ proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect,
 
 proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect,
                                                            inline.} =
+  ## Adds a separator to `dest` only if its length is bigger than `startLen`.
+  ##
   ## A shorthand for:
   ##
   ## .. code-block:: nimrod
@@ -635,15 +693,15 @@ proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect,
   if dest.len > startLen: add(dest, sep)
 
 proc allCharsInSet*(s: string, theSet: TCharSet): bool =
-  ## returns true iff each character of `s` is in the set `theSet`.
+  ## Returns true iff each character of `s` is in the set `theSet`.
   for c in items(s):
     if c notin theSet: return false
   return true
 
 proc abbrev*(s: string, possibilities: openArray[string]): int =
-  ## returns the index of the first item in `possibilities` if not
-  ## ambiguous; -1 if no item has been found; -2 if multiple items
-  ## match.
+  ## Returns the index of the first item in `possibilities` if not ambiguous.
+  ##
+  ## Returns -1 if no item has been found and -2 if multiple items match.
   result = -1 # none found
   for i in 0..possibilities.len-1:
     if possibilities[i].startsWith(s):
@@ -657,7 +715,7 @@ proc abbrev*(s: string, possibilities: openArray[string]): int =
 
 proc join*(a: openArray[string], sep: string): string {.
   noSideEffect, rtl, extern: "nsuJoinSep".} =
-  ## concatenates all strings in `a` separating them with `sep`.
+  ## Concatenates all strings in `a` separating them with `sep`.
   if len(a) > 0:
     var L = sep.len * (a.len-1)
     for i in 0..high(a): inc(L, a[i].len)
@@ -671,7 +729,7 @@ proc join*(a: openArray[string], sep: string): string {.
 
 proc join*(a: openArray[string]): string {.
   noSideEffect, rtl, extern: "nsuJoin".} =
-  ## concatenates all strings in `a`.
+  ## Concatenates all strings in `a`.
   if len(a) > 0:
     var L = 0
     for i in 0..high(a): inc(L, a[i].len)
@@ -689,7 +747,7 @@ proc preprocessSub(sub: string, a: var TSkipTable) =
   for i in 0..m-1: a[sub[i]] = m-i
 
 proc findAux(s, sub: string, start: int, a: TSkipTable): int =
-  # fast "quick search" algorithm:
+  # Fast "quick search" algorithm:
   var
     m = len(sub)
     n = len(s)
@@ -705,32 +763,36 @@ proc findAux(s, sub: string, start: int, a: TSkipTable): int =
 
 proc find*(s, sub: string, start: int = 0): int {.noSideEffect,
   rtl, extern: "nsuFindStr", operator: 6.} =
-  ## Searches for `sub` in `s` starting at position `start`. Searching is
-  ## case-sensitive. If `sub` is not in `s`, -1 is returned.
+  ## Searches for `sub` in `s` starting at position `start`.
+  ##
+  ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
   var a {.noinit.}: TSkipTable
   preprocessSub(sub, a)
   result = findAux(s, sub, start, a)
 
 proc find*(s: string, sub: char, start: int = 0): int {.noSideEffect,
   rtl, extern: "nsuFindChar".} =
-  ## Searches for `sub` in `s` starting at position `start`. Searching is
-  ## case-sensitive. If `sub` is not in `s`, -1 is returned.
+  ## Searches for `sub` in `s` starting at position `start`.
+  ##
+  ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
   for i in start..len(s)-1:
     if sub == s[i]: return i
   return -1
 
 proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect,
   rtl, extern: "nsuFindCharSet".} =
-  ## Searches for `chars` in `s` starting at position `start`. If `s` contains
-  ## none of the characters in `chars`, -1 is returned.
+  ## Searches for `chars` in `s` starting at position `start`.
+  ##
+  ## If `s` contains none of the characters in `chars`, -1 is returned.
   for i in start..s.len-1:
     if s[i] in chars: return i
   return -1
 
 proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} =
   ## Searches for `sub` in `s` in reverse, starting at `start` and going
-  ## backwards to 0. Searching is case-sensitive. If `sub` is not in `s`, -1 is
-  ## returned.
+  ## backwards to 0.
+  ##
+  ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
   let realStart = if start == -1: s.len else: start
   for i in countdown(realStart-sub.len, 0):
     for j in 0..sub.len-1:
@@ -741,11 +803,42 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} =
     if result != -1: return
   return -1
 
+proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect,
+  rtl, extern: "nsuCountString".} =
+  ## Count the occurences of a substring `sub` in the string `s`.
+  ## Overlapping occurences of `sub` only count when `overlapping`
+  ## is set to true.
+  var i = 0
+  while true:
+    i = s.find(sub, i)
+    if i < 0:
+      break
+    if overlapping:
+      inc i
+    else:
+      i += sub.len
+    inc result
+
+proc count*(s: string, sub: char): int {.noSideEffect,
+  rtl, extern: "nsuCountChar".} =
+  ## Count the occurences of the character `sub` in the string `s`.
+  for c in s:
+    if c == sub:
+      inc result
+
+proc count*(s: string, subs: set[char]): int {.noSideEffect,
+  rtl, extern: "nsuCountCharSet".} =
+  ## Count the occurences of the group of character `subs` in the string `s`.
+  for c in s:
+    if c in subs:
+      inc result
+
 proc quoteIfContainsWhite*(s: string): string {.deprecated.} =
-  ## returns ``'"' & s & '"'`` if `s` contains a space and does not
-  ## start with a quote, else returns `s`
-  ## DEPRECATED as it was confused for shell quoting function.
-  ## For this application use osproc.quoteShell.
+  ## Returns ``'"' & s & '"'`` if `s` contains a space and does not
+  ## start with a quote, else returns `s`.
+  ##
+  ## **DEPRECATED** as it was confused for shell quoting function.  For this
+  ## application use `osproc.quoteShell `_.
   if find(s, {' ', '\t'}) >= 0 and s[0] != '"':
     result = '"' & s & '"'
   else:
@@ -781,7 +874,9 @@ proc replace*(s, sub: string, by = ""): string {.noSideEffect,
 
 proc replace*(s: string, sub, by: char): string {.noSideEffect,
   rtl, extern: "nsuReplaceChar".} =
-  ## optimized version for characters.
+  ## Replaces `sub` in `s` by the character `by`.
+  ##
+  ## Optimized version of `replace <#replace,string,string>`_ for characters.
   result = newString(s.len)
   var i = 0
   while i < s.len:
@@ -791,9 +886,11 @@ proc replace*(s: string, sub, by: char): string {.noSideEffect,
 
 proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect,
   rtl, extern: "nsuReplaceWord".} =
-  ## Replaces `sub` in `s` by the string `by`. Each occurance of `sub`
-  ## has to be surrounded by word boundaries (comparable to ``\\w`` in
-  ## regular expressions), otherwise it is not replaced.
+  ## Replaces `sub` in `s` by the string `by`.
+  ##
+  ## Each occurance of `sub` has to be surrounded by word boundaries
+  ## (comparable to ``\\w`` in regular expressions), otherwise it is not
+  ## replaced.
   const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}
   var a {.noinit.}: TSkipTable
   result = ""
@@ -816,8 +913,9 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect,
 
 proc delete*(s: var string, first, last: int) {.noSideEffect,
   rtl, extern: "nsuDelete".} =
-  ## Deletes in `s` the characters at position `first` .. `last`. This modifies
-  ## `s` itself, it does not return a copy.
+  ## Deletes in `s` the characters at position `first` .. `last`.
+  ##
+  ## This modifies `s` itself, it does not return a copy.
   var i = first
   var j = last+1
   var newLen = len(s)-j+i
@@ -829,10 +927,11 @@ proc delete*(s: var string, first, last: int) {.noSideEffect,
 
 proc parseOctInt*(s: string): int {.noSideEffect,
   rtl, extern: "nsuParseOctInt".} =
-  ## Parses an octal integer value contained in `s`. If `s` is not
-  ## a valid integer, `EInvalidValue` is raised. `s` can have one of the
-  ## following optional prefixes: ``0o``, ``0O``.
-  ## Underscores within `s` are ignored.
+  ## Parses an octal integer value contained in `s`.
+  ##
+  ## If `s` is not a valid integer, `EInvalidValue` is raised. `s` can have one
+  ## of the following optional prefixes: ``0o``, ``0O``.  Underscores within
+  ## `s` are ignored.
   var i = 0
   if s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2)
   while true:
@@ -846,8 +945,10 @@ proc parseOctInt*(s: string): int {.noSideEffect,
 
 proc toOct*(x: BiggestInt, len: int): string {.noSideEffect,
   rtl, extern: "nsuToOct".} =
-  ## converts `x` into its octal representation. The resulting string is
-  ## always `len` characters long. No leading ``0o`` prefix is generated.
+  ## Converts `x` into its octal representation.
+  ##
+  ## The resulting string is always `len` characters long. No leading ``0o``
+  ## prefix is generated.
   var
     mask: BiggestInt = 7
     shift: BiggestInt = 0
@@ -860,8 +961,10 @@ proc toOct*(x: BiggestInt, len: int): string {.noSideEffect,
 
 proc toBin*(x: BiggestInt, len: int): string {.noSideEffect,
   rtl, extern: "nsuToBin".} =
-  ## converts `x` into its binary representation. The resulting string is
-  ## always `len` characters long. No leading ``0b`` prefix is generated.
+  ## Converts `x` into its binary representation.
+  ##
+  ## The resulting string is always `len` characters long. No leading ``0b``
+  ## prefix is generated.
   var
     mask: BiggestInt = 1
     shift: BiggestInt = 0
@@ -874,7 +977,8 @@ proc toBin*(x: BiggestInt, len: int): string {.noSideEffect,
 
 proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect,
   rtl, extern: "nsuInsertSep".} =
-  ## inserts the separator `sep` after `digits` digits from right to left.
+  ## Inserts the separator `sep` after `digits` digits from right to left.
+  ##
   ## Even though the algorithm works with any string `s`, it is only useful
   ## if `s` contains a number.
   ## Example: ``insertSep("1000000") == "1_000_000"``
@@ -893,7 +997,9 @@ proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect,
 
 proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
   rtl, extern: "nsuEscape".} =
-  ## Escapes a string `s`. This does these operations (at the same time):
+  ## Escapes a string `s`.
+  ##
+  ## This does these operations (at the same time):
   ## * replaces any ``\`` by ``\\``
   ## * replaces any ``'`` by ``\'``
   ## * replaces any ``"`` by ``\"``
@@ -917,11 +1023,13 @@ proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
 
 proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
   rtl, extern: "nsuUnescape".} =
-  ## Unescapes a string `s`. This complements ``escape`` as it performs the
-  ## opposite operations.
+  ## Unescapes a string `s`.
   ##
-  ## If `s` does not begin with ``prefix`` and end with ``suffix`` a EInvalidValue
-  ## exception will be raised.
+  ## This complements `escape <#escape>`_ as it performs the opposite
+  ## operations.
+  ##
+  ## If `s` does not begin with ``prefix`` and end with ``suffix`` a
+  ## EInvalidValue exception will be raised.
   result = newStringOfCap(s.len)
   var i = 0
   if s[0 .. prefix.len-1] != prefix:
@@ -955,9 +1063,10 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
 
 proc validIdentifier*(s: string): bool {.noSideEffect,
   rtl, extern: "nsuValidIdentifier".} =
-  ## returns true if `s` is a valid identifier. A valid identifier starts
-  ## with a character of the set `IdentStartChars` and is followed by any
-  ## number of characters of the set `IdentChars`.
+  ## Returns true if `s` is a valid identifier.
+  ##
+  ## A valid identifier starts with a character of the set `IdentStartChars`
+  ## and is followed by any number of characters of the set `IdentChars`.
   if s[0] in IdentStartChars:
     for i in 1..s.len-1:
       if s[i] notin IdentChars: return false
@@ -965,9 +1074,10 @@ proc validIdentifier*(s: string): bool {.noSideEffect,
 
 proc editDistance*(a, b: string): int {.noSideEffect,
   rtl, extern: "nsuEditDistance".} =
-  ## returns the edit distance between `a` and `b`. This uses the 
-  ## `Levenshtein`:idx: distance algorithm with only a linear memory overhead.
-  ## This implementation is highly optimized!
+  ## Returns the edit distance between `a` and `b`.
+  ##
+  ## This uses the `Levenshtein`:idx: distance algorithm with only a linear
+  ## memory overhead.  This implementation is highly optimized!
   var len1 = a.len
   var len2 = b.len
   if len1 > len2:
@@ -1066,7 +1176,7 @@ type
 proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
                          precision: range[0..32] = 16): string {.
                          noSideEffect, operator: 2, rtl, extern: "nsu$1".} =
-  ## converts a floating point value `f` to a string.
+  ## Converts a floating point value `f` to a string.
   ##
   ## If ``format == ffDecimal`` then precision is the number of digits to
   ## be printed after the decimal point.
@@ -1097,7 +1207,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
 proc formatFloat*(f: float, format: TFloatFormat = ffDefault,
                   precision: range[0..32] = 16): string {.
                   noSideEffect, operator: 2, rtl, extern: "nsu$1".} =
-  ## converts a floating point value `f` to a string.
+  ## Converts a floating point value `f` to a string.
   ##
   ## If ``format == ffDecimal`` then precision is the number of digits to
   ## be printed after the decimal point.
@@ -1192,6 +1302,8 @@ proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {.
 
 proc `%` *(formatstr: string, a: openArray[string]): string {.noSideEffect,
   rtl, extern: "nsuFormatOpenArray".} =
+  ## Interpolates a format string with the values from `a`.
+  ##
   ## The `substitution`:idx: operator performs string substitutions in
   ## `formatstr` and returns a modified `formatstr`. This is often called
   ## `string interpolation`:idx:.
@@ -1272,3 +1384,8 @@ when isMainModule:
   doAssert parseEnum[TMyEnum]("enu_D") == enuD
 
   doAssert parseEnum("invalid enum value", enC) == enC
+
+  doAssert count("foofoofoo", "foofoo") == 1
+  doAssert count("foofoofoo", "foofoo", overlapping = true) == 2
+  doAssert count("foofoofoo", 'f') == 3
+  doAssert count("foofoofoobar", {'f','b'}) == 4
diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim
index 92797744a4..ed87610d61 100644
--- a/lib/pure/subexes.nim
+++ b/lib/pure/subexes.nim
@@ -84,7 +84,8 @@ proc getFormatArg(p: var TFormatParser, a: openArray[string]): int =
   if result >=% a.len: raiseInvalidFormat("index out of bounds: " & $result)
   p.i = i
 
-proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string)
+proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string) {.
+  noSideEffect.}
 
 proc emitChar(p: var TFormatParser, x: var string, ch: char) {.inline.} =
   x.add(ch)
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 4985118998..8b33d2c738 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -63,44 +63,44 @@ elif defined(windows):
 elif defined(JS):
   type
     TTime* {.final, importc.} = object
-      getDay: proc (): int {.tags: [], raises: [].}
-      getFullYear: proc (): int {.tags: [], raises: [].}
-      getHours: proc (): int {.tags: [], raises: [].}
-      getMilliseconds: proc (): int {.tags: [], raises: [].}
-      getMinutes: proc (): int {.tags: [], raises: [].}
-      getMonth: proc (): int {.tags: [], raises: [].}
-      getSeconds: proc (): int {.tags: [], raises: [].}
-      getTime: proc (): int {.tags: [], raises: [].}
-      getTimezoneOffset: proc (): int {.tags: [], raises: [].}
-      getDate: proc (): int {.tags: [], raises: [].}
-      getUTCDate: proc (): int {.tags: [], raises: [].}
-      getUTCFullYear: proc (): int {.tags: [], raises: [].}
-      getUTCHours: proc (): int {.tags: [], raises: [].}
-      getUTCMilliseconds: proc (): int {.tags: [], raises: [].}
-      getUTCMinutes: proc (): int {.tags: [], raises: [].}
-      getUTCMonth: proc (): int {.tags: [], raises: [].}
-      getUTCSeconds: proc (): int {.tags: [], raises: [].}
-      getUTCDay: proc (): int {.tags: [], raises: [].}
-      getYear: proc (): int {.tags: [], raises: [].}
-      parse: proc (s: cstring): TTime {.tags: [], raises: [].}
-      setDate: proc (x: int) {.tags: [], raises: [].}
-      setFullYear: proc (x: int) {.tags: [], raises: [].}
-      setHours: proc (x: int) {.tags: [], raises: [].}
-      setMilliseconds: proc (x: int) {.tags: [], raises: [].}
-      setMinutes: proc (x: int) {.tags: [], raises: [].}
-      setMonth: proc (x: int) {.tags: [], raises: [].}
-      setSeconds: proc (x: int) {.tags: [], raises: [].}
-      setTime: proc (x: int) {.tags: [], raises: [].}
-      setUTCDate: proc (x: int) {.tags: [], raises: [].}
-      setUTCFullYear: proc (x: int) {.tags: [], raises: [].}
-      setUTCHours: proc (x: int) {.tags: [], raises: [].}
-      setUTCMilliseconds: proc (x: int) {.tags: [], raises: [].}
-      setUTCMinutes: proc (x: int) {.tags: [], raises: [].}
-      setUTCMonth: proc (x: int) {.tags: [], raises: [].}
-      setUTCSeconds: proc (x: int) {.tags: [], raises: [].}
-      setYear: proc (x: int) {.tags: [], raises: [].}
-      toGMTString: proc (): cstring {.tags: [], raises: [].}
-      toLocaleString: proc (): cstring {.tags: [], raises: [].}
+      getDay: proc (): int {.tags: [], raises: [], gcsafe.}
+      getFullYear: proc (): int {.tags: [], raises: [], gcsafe.}
+      getHours: proc (): int {.tags: [], raises: [], gcsafe.}
+      getMilliseconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getMinutes: proc (): int {.tags: [], raises: [], gcsafe.}
+      getMonth: proc (): int {.tags: [], raises: [], gcsafe.}
+      getSeconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getTime: proc (): int {.tags: [], raises: [], gcsafe.}
+      getTimezoneOffset: proc (): int {.tags: [], raises: [], gcsafe.}
+      getDate: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCDate: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCFullYear: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCHours: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCMilliseconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCMinutes: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCMonth: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCSeconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCDay: proc (): int {.tags: [], raises: [], gcsafe.}
+      getYear: proc (): int {.tags: [], raises: [], gcsafe.}
+      parse: proc (s: cstring): TTime {.tags: [], raises: [], gcsafe.}
+      setDate: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setFullYear: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setHours: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setMilliseconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setMinutes: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setMonth: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setSeconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setTime: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCDate: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCFullYear: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCHours: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCMilliseconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCMinutes: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCMonth: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCSeconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setYear: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      toGMTString: proc (): cstring {.tags: [], raises: [], gcsafe.}
+      toLocaleString: proc (): cstring {.tags: [], raises: [], gcsafe.}
 
 type
   TTimeInfo* = object of TObject ## represents a time in different parts
@@ -513,7 +513,7 @@ elif defined(JS):
     result.setFullYear(timeInfo.year)
     result.setDate(timeInfo.monthday)
   
-  proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo))
+  proc `$`(timeInfo: TTimeInfo): string = return $(timeInfoToTime(timeInfo))
   proc `$`(time: TTime): string = return $time.toLocaleString()
     
   proc `-` (a, b: TTime): int64 = 
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index e7bd363cf9..3203ee6997 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -11,7 +11,26 @@
 ## working with types
 
 proc name*(t: typedesc): string {.magic: "TypeTrait".}
-  ## Returns the name of the given type
+  ## Returns the name of the given type.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##
+  ##   import typetraits
+  ##
+  ##   proc `$`*[T](some:typedesc[T]): string = name(T)
+  ##
+  ##   template test(x): stmt =
+  ##     echo "type: ", type(x), ", value: ", x
+  ##
+  ##   test 42
+  ##   # --> type: int, value: 42
+  ##   test "Foo"
+  ##   # --> type: string, value: Foo
+  ##   test(@['A','B'])
+  ##   # --> type: seq[char], value: @[A, B]
+
 
 proc arity*(t: typedesc): int {.magic: "TypeTrait".}
-  ## Returns the arity of the given type
\ No newline at end of file
+  ## Returns the arity of the given type
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index f5640a1b4b..7cc95f0ad1 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -19,7 +19,7 @@
 import
   macros
 
-when defined(stdout):
+when declared(stdout):
   import os
 
 when not defined(ECMAScript):
@@ -99,7 +99,7 @@ template fail* =
   when not defined(ECMAScript):
     if AbortOnError: quit(1)
  
-  when defined(TestStatusIMPL):
+  when declared(TestStatusIMPL):
     TestStatusIMPL = FAILED
   else:
     program_result += 1
@@ -188,7 +188,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
   result = getAst(expectBody(errorTypes, exp.lineinfo, body))
 
 
-when defined(stdout):
+when declared(stdout):
   ## Reading settings
   var envOutLvl = os.getEnv("NIMTEST_OUTPUT_LVL").string
 
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index ee1226a359..7ec8230338 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -7,17 +7,24 @@
 #    distribution, for details about the copyright.
 #
 
-## **Note**: This module will be deprecated in the future and merged into a
-## new ``url`` module.
+## This module implements URI parsing as specified by RFC 3986.
 
-import strutils
+import strutils, parseutils
 type
   TUrl* = distinct string
 
-proc `$`*(url: TUrl): string = return string(url)
+  TUri* = object
+    scheme*, username*, password*: string 
+    hostname*, port*, path*, query*, anchor*: string
 
-proc `/`*(a, b: TUrl): TUrl =
+proc `$`*(url: TUrl): string {.deprecated.} =
+  ## **Deprecated since 0.9.6**: Use ``TUri`` instead.
+  return string(url)
+
+proc `/`*(a, b: TUrl): TUrl {.deprecated.} =
   ## Joins two URLs together, separating them with / if needed.
+  ##
+  ## **Deprecated since 0.9.6**: Use ``TUri`` instead.
   var urlS = $a
   var bS = $b
   if urlS == "": return b
@@ -29,9 +36,338 @@ proc `/`*(a, b: TUrl): TUrl =
     urlS.add(bs)
   result = TUrl(urlS)
 
-proc add*(url: var TUrl, a: TUrl) =
+proc add*(url: var TUrl, a: TUrl) {.deprecated.} =
   ## Appends url to url.
+  ##
+  ## **Deprecated since 0.9.6**: Use ``TUri`` instead.
   url = url / a
 
+proc parseAuthority(authority: string, result: var TUri) =
+  var i = 0
+  var inPort = false
+  while true:
+    case authority[i]
+    of '@':
+      result.password = result.port
+      result.port = ""
+      result.username = result.hostname
+      result.hostname = ""
+      inPort = false
+    of ':':
+      inPort = true
+    of '\0': break
+    else:
+      if inPort:
+        result.port.add(authority[i])
+      else:
+        result.hostname.add(authority[i])
+    i.inc
+
+proc parsePath(uri: string, i: var int, result: var TUri) =
+  
+  i.inc parseUntil(uri, result.path, {'?', '#'}, i)
+
+  # The 'mailto' scheme's PATH actually contains the hostname/username
+  if result.scheme.ToLower() == "mailto":
+    parseAuthority(result.path, result)
+    result.path = ""
+
+  if uri[i] == '?':
+    i.inc # Skip '?'
+    i.inc parseUntil(uri, result.query, {'#'}, i)
+
+  if uri[i] == '#':
+    i.inc # Skip '#'
+    i.inc parseUntil(uri, result.anchor, {}, i)
+
+proc initUri(): TUri =
+  result = TUri(scheme: "", username: "", password: "", hostname: "", port: "",
+                path: "", query: "", anchor: "")
+
+proc parseUri*(uri: string): TUri =
+  ## Parses a URI.
+  result = initUri()
+
+  var i = 0
+
+  # Check if this is a reference URI (relative URI)
+  if uri[i] == '/':
+    parsePath(uri, i, result)
+    return
+
+  # Scheme
+  i.inc parseWhile(uri, result.scheme, Letters + Digits + {'+', '-', '.'}, i)
+  if uri[i] != ':':
+    # Assume this is a reference URI (relative URI)
+    i = 0
+    result.scheme = ""
+    parsePath(uri, i, result)
+    return
+  i.inc # Skip ':'
+
+  # Authority
+  if uri[i] == '/' and uri[i+1] == '/':
+    i.inc(2) # Skip //
+    var authority = ""
+    i.inc parseUntil(uri, authority, {'/', '?', '#'}, i)
+    if authority == "":
+      raise newException(EInvalidValue, "Expected authority got nothing.")
+    parseAuthority(authority, result)
+
+  # Path
+  parsePath(uri, i, result)
+
+proc removeDotSegments(path: string): string =
+  var collection: seq[string] = @[]
+  let endsWithSlash = path[path.len-1] == '/'
+  var i = 0
+  var currentSegment = ""
+  while true:
+    case path[i]
+    of '/':
+      collection.add(currentSegment)
+      currentSegment = ""
+    of '.':
+      if path[i+1] == '.' and path[i+2] == '/':
+        if collection.len > 0:
+          discard collection.pop()
+          i.inc 3
+          continue
+      elif path[i+1] == '/':
+        i.inc 2
+        continue
+      currentSegment.add path[i]
+    of '\0':
+      if currentSegment != "":
+        collection.add currentSegment
+      break
+    else:
+      currentSegment.add path[i]
+    i.inc
+
+  result = collection.join("/")
+  if endsWithSlash: result.add '/'
+
+proc merge(base, reference: TUri): string =
+  # http://tools.ietf.org/html/rfc3986#section-5.2.3
+  if base.hostname != "" and base.path == "":
+    '/' & reference.path
+  else:
+    let lastSegment = rfind(base.path, "/")
+    if lastSegment == -1:
+      reference.path
+    else:
+      base.path[0 .. lastSegment] & reference.path
+
+proc combine*(base: TUri, reference: TUri): TUri =
+  ## Combines a base URI with a reference URI.
+  ##
+  ## This uses the algorithm specified in
+  ## `section 5.2.2 of RFC 3986 `_.
+  ##
+  ## This means that the slashes inside the base URI's path as well as reference
+  ## URI's path affect the resulting URI.
+  ##
+  ## For building URIs you may wish to use \`/\` instead.
+  ##
+  ## Examples:
+  ##
+  ## .. code-block:: nimrod
+  ##   let foo = combine(parseUri("http://example.com/foo/bar"), parseUri("/baz"))
+  ##   assert foo.path == "/baz"
+  ##
+  ##   let bar = combine(parseUri("http://example.com/foo/bar"), parseUri("baz"))
+  ##   assert foo.path == "/foo/baz"
+  ##
+  ##   let bar = combine(parseUri("http://example.com/foo/bar/"), parseUri("baz"))
+  ##   assert foo.path == "/foo/bar/baz"
+  
+  template setAuthority(dest, src: expr): stmt =
+    dest.hostname = src.hostname
+    dest.username = src.username
+    dest.port = src.port
+    dest.password = src.password
+
+  result = initUri()
+  if reference.scheme != base.scheme and reference.scheme != "":
+    result = reference
+    result.path = removeDotSegments(result.path)
+  else:
+    if reference.hostname != "":
+      setAuthority(result, reference)
+      result.path = removeDotSegments(reference.path)
+      result.query = reference.query
+    else:
+      if reference.path == "":
+        result.path = base.path
+        if reference.query != "":
+          result.query = reference.query
+        else:
+          result.query = base.query
+      else:
+        if reference.path.startsWith("/"):
+          result.path = removeDotSegments(reference.path)
+        else:
+          result.path = removeDotSegments(merge(base, reference))
+        result.query = reference.query
+      setAuthority(result, base)
+    result.scheme = base.scheme
+  result.anchor = reference.anchor
+
+proc combine*(uris: varargs[TUri]): TUri =
+  ## Combines multiple URIs together.
+  result = uris[0]
+  for i in 1 ..  0:
+    result.add(u.scheme)
+    result.add("://")
+  if u.username.len > 0:
+    result.add(u.username)
+    if u.password.len > 0:
+      result.add(":")
+      result.add(u.password)
+    result.add("@")
+  result.add(u.hostname)
+  if u.port.len > 0:
+    result.add(":")
+    result.add(u.port)
+  if u.path.len > 0:
+    if u.path[0] != '/': result.add("/")
+    result.add(u.path)
+  result.add(u.query)
+  result.add(u.anchor)
+
 when isMainModule:
-  assert($("http://".TUrl / "localhost:5000".TUrl) == "http://localhost:5000")
+  block:
+    let test = parseUri("http://localhost:8080/test")
+    doAssert test.scheme == "http"
+    doAssert test.port == "8080"
+    doAssert test.path == "/test"
+    doAssert test.hostname == "localhost"
+
+  block:
+    let test = parseUri("foo://username:password@example.com:8042/over/there" &
+                        "/index.dtb?type=animal&name=narwhal#nose")
+    doAssert test.scheme == "foo"
+    doAssert test.username == "username"
+    doAssert test.password == "password"
+    doAssert test.hostname == "example.com"
+    doAssert test.port == "8042"
+    doAssert test.path == "/over/there/index.dtb"
+    doAssert test.query == "type=animal&name=narwhal"
+    doAssert test.anchor == "nose"
+
+  block:
+    let test = parseUri("urn:example:animal:ferret:nose")
+    doAssert test.scheme == "urn"
+    doAssert test.path == "example:animal:ferret:nose"
+
+  block:
+    let test = parseUri("mailto:username@example.com?subject=Topic")
+    doAssert test.scheme == "mailto"
+    doAssert test.username == "username"
+    doAssert test.hostname == "example.com"
+    doAssert test.query == "subject=Topic"
+
+  block:
+    let test = parseUri("magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar")
+    doAssert test.scheme == "magnet"
+    doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
+
+  block:
+    let test = parseUri("/test/foo/bar?q=2#asdf")
+    doAssert test.scheme == ""
+    doAssert test.path == "/test/foo/bar"
+    doAssert test.query == "q=2"
+    doAssert test.anchor == "asdf"
+
+  block:
+    let test = parseUri("test/no/slash")
+    doAssert test.path == "test/no/slash"
+
+  # Remove dot segments tests
+  block:
+    doAssert removeDotSegments("/foo/bar/baz") == "/foo/bar/baz"
+
+  # Combine tests
+  block:
+    let concat = combine(parseUri("http://google.com/foo/bar/"), parseUri("baz"))
+    doAssert concat.path == "/foo/bar/baz"
+    doAssert concat.hostname == "google.com"
+    doAssert concat.scheme == "http"
+
+  block:
+    let concat = combine(parseUri("http://google.com/foo"), parseUri("/baz"))
+    doAssert concat.path == "/baz"
+    doAssert concat.hostname == "google.com"
+    doAssert concat.scheme == "http"
+
+  block:
+    let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar"))
+    doAssert concat.path == "/foo/bar"
+
+  block:
+    let concat = combine(parseUri("http://google.com/foo/test"), parseUri("/bar"))
+    doAssert concat.path == "/bar"
+
+  block:
+    let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar"))
+    doAssert concat.path == "/foo/bar"
+
+  block:
+    let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar"))
+    doAssert concat.path == "/foo/test/bar"
+
+  block:
+    let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/"))
+    doAssert concat.path == "/foo/test/bar/"
+
+  block:
+    let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/"),
+                         parseUri("baz"))
+    doAssert concat.path == "/foo/test/bar/baz"
+
+  # `/` tests
+  block:
+    let test = parseUri("http://example.com/foo") / "bar/asd"
+    doAssert test.path == "/foo/bar/asd"
+
+  block:
+    let test = parseUri("http://example.com/foo/") / "/bar/asd"
+    doAssert test.path == "/foo/bar/asd"
+
+  
diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim
index 47e94243eb..d63b6c5dd3 100644
--- a/lib/pure/xmldom.nim
+++ b/lib/pure/xmldom.nim
@@ -45,7 +45,7 @@ const
   DocumentFragmentNode* = 11
 
   # Nodes which are childless - Not sure about AttributeNode
-  childlessObjects = {DocumentNode, AttributeNode, TextNode, 
+  childlessObjects = {DocumentNode, AttributeNode, TextNode,
     CDataSectionNode, ProcessingInstructionNode, CommentNode}
   # Illegal characters
   illegalChars = {'>', '<', '&', '"'}
@@ -69,21 +69,21 @@ type
     FOwnerDocument: PDocument # Read-Only
     FParentNode: PNode # Read-Only
     prefix*: string # Setting this should change some values... TODO!
-  
+
   PElement* = ref Element
   Element = object of Node
     FTagName: string # Read-only
-  
+
   PCharacterData* = ref CharacterData
   CharacterData = object of Node
     data*: string
-    
+
   PDocument* = ref Document
   Document = object of Node
     FImplementation: PDOMImplementation # Read-only
     FDocumentElement: PElement # Read-only
-    
-  PAttr* = ref Attr  
+
+  PAttr* = ref Attr
   Attr = object of Node
     FName: string # Read-only
     FSpecified: bool # Read-only
@@ -95,13 +95,13 @@ type
 
   PText* = ref Text
   Text = object of CharacterData
-  
+
   PComment* = ref comment
   Comment = object of CharacterData
-  
+
   PCDataSection* = ref CDataSection
   CDataSection = object of Text
-    
+
   PProcessingInstruction* = ref ProcessingInstruction
   ProcessingInstruction = object of Node
     data*: string
@@ -111,8 +111,8 @@ type
 proc getDOM*(): PDOMImplementation =
   ## Returns a DOMImplementation
   new(result)
-  result.Features = @[(name: "core", version: "2.0"), 
-                      (name: "core", version: "1.0"), 
+  result.Features = @[(name: "core", version: "2.0"),
+                      (name: "core", version: "1.0"),
                       (name: "XML", version: "2.0")]
 
 proc createDocument*(dom: PDOMImplementation, namespaceURI: string, qualifiedName: string): PDocument =
@@ -121,28 +121,28 @@ proc createDocument*(dom: PDOMImplementation, namespaceURI: string, qualifiedNam
   new(doc)
   doc.FNamespaceURI = namespaceURI
   doc.FImplementation = dom
-  
+
   var elTag: PElement
   new(elTag)
   elTag.FTagName = qualifiedName
   elTag.FNodeName = qualifiedName
   doc.FDocumentElement = elTag
   doc.FNodeType = DocumentNode
-  
+
   return doc
-  
+
 proc createDocument*(dom: PDOMImplementation, n: PElement): PDocument =
   ## Creates an XML Document object of the specified type with its document element.
-  
+
   # This procedure is not in the specification, it's provided for the parser.
   var doc: PDocument
   new(doc)
   doc.FDocumentElement = n
   doc.FImplementation = dom
   doc.FNodeType = DocumentNode
-  
+
   return doc
-  
+
 proc hasFeature*(dom: PDOMImplementation, feature: string, version: string = ""): bool =
   ## Returns ``true`` if this ``version`` of the DomImplementation implements ``feature``, otherwise ``false``
   for iName, iVersion in items(dom.Features):
@@ -157,11 +157,11 @@ proc hasFeature*(dom: PDOMImplementation, feature: string, version: string = "")
 
 # Document
 # Attributes
-  
+
 proc implementation*(doc: PDocument): PDOMImplementation =
   return doc.FImplementation
-  
-proc documentElement*(doc: PDocument): PElement = 
+
+proc documentElement*(doc: PDocument): PElement =
   return doc.FDocumentElement
 
 # Internal procedures
@@ -175,13 +175,13 @@ proc findNodes(nl: PNode, name: string): seq[PNode] =
     if i.FNodeType == ElementNode:
       if i.FNodeName == name or name == "*":
         r.add(i)
-        
+
       if not isNil(i.childNodes):
         if i.childNodes.len() != 0:
           r.add(findNodes(i, name))
-    
+
   return r
-  
+
 proc findNodesNS(nl: PNode, namespaceURI: string, localName: string): seq[PNode] =
   # Made for getElementsByTagNameNS
   var r: seq[PNode] = @[]
@@ -192,23 +192,23 @@ proc findNodesNS(nl: PNode, namespaceURI: string, localName: string): seq[PNode]
     if i.FNodeType == ElementNode:
       if (i.FNamespaceURI == namespaceURI or namespaceURI == "*") and (i.FLocalName == localName or localName == "*"):
         r.add(i)
-        
+
       if not isNil(i.childNodes):
         if i.childNodes.len() != 0:
           r.add(findNodesNS(i, namespaceURI, localName))
-    
+
   return r
-    
+
 
 #Procedures
 proc createAttribute*(doc: PDocument, name: string): PAttr =
   ## Creates an Attr of the given name. Note that the Attr instance can then be set on an Element using the setAttributeNode method.
-  ## To create an attribute with a qualified name and namespace URI, use the createAttributeNS method. 
-  
+  ## To create an attribute with a qualified name and namespace URI, use the createAttributeNS method.
+
   # Check if name contains illegal characters
   if illegalChars in name:
     raise newException(EInvalidCharacterErr, "Invalid character")
-  
+
   var AttrNode: PAttr
   new(AttrNode)
   AttrNode.FName = name
@@ -222,21 +222,21 @@ proc createAttribute*(doc: PDocument, name: string): PAttr =
 
 proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PAttr =
   ## Creates an attribute of the given qualified name and namespace URI
-  
+
   # Check if name contains illegal characters
   if illegalChars in namespaceURI or illegalChars in qualifiedName:
     raise newException(EInvalidCharacterErr, "Invalid character")
   # Exceptions
   if qualifiedName.contains(':'):
-    if namespaceURI == nil:
+    if isNil(namespaceURI):
       raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
     elif qualifiedName.split(':')[0].toLower() == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace":
-      raise newException(ENamespaceErr, 
+      raise newException(ENamespaceErr,
         "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
     elif qualifiedName.split(':')[1].toLower() == "xmlns" and namespaceURI != "http://www.w3.org/2000/xmlns/":
-      raise newException(ENamespaceErr, 
+      raise newException(ENamespaceErr,
         "When the namespace prefix is \"xmlns\" namespaceURI has to be \"http://www.w3.org/2000/xmlns/\"")
-  
+
   var AttrNode: PAttr
   new(AttrNode)
   AttrNode.FName = qualifiedName
@@ -250,7 +250,7 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str
     AttrNode.prefix = nil
     AttrNode.FLocalName = qualifiedName
   AttrNode.value = ""
-  
+
   AttrNode.FNodeType = AttributeNode
   return AttrNode
 
@@ -265,12 +265,12 @@ proc createCDATASection*(doc: PDocument, data: string): PCDATASection =
   return CData
 
 proc createComment*(doc: PDocument, data: string): PComment =
-  ## Creates a Comment node given the specified string. 
+  ## Creates a Comment node given the specified string.
   var Comm: PComment
   new(Comm)
   Comm.data = data
   Comm.nodeValue = data
-  
+
   Comm.FNodeType = CommentNode
   return Comm
 
@@ -282,11 +282,11 @@ proc createDocumentFragment*(doc: PDocument): PDocumentFragment =
 
 proc createElement*(doc: PDocument, tagName: string): PElement =
   ## Creates an element of the type specified.
-  
+
   # Check if name contains illegal characters
   if illegalChars in tagName:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   var elNode: PElement
   new(elNode)
   elNode.FTagName = tagName
@@ -296,24 +296,24 @@ proc createElement*(doc: PDocument, tagName: string): PElement =
   elNode.FNamespaceURI = nil
   elNode.childNodes = @[]
   elNode.attributes = @[]
-  
+
   elNode.FNodeType = ElementNode
-  
+
   return elNode
 
 proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PElement =
   ## Creates an element of the given qualified name and namespace URI.
   if qualifiedName.contains(':'):
-    if namespaceURI == nil:
+    if isNIl(namespaceURI):
       raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
     elif qualifiedName.split(':')[0].toLower() == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace":
-      raise newException(ENamespaceErr, 
+      raise newException(ENamespaceErr,
         "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
-        
+
   # Check if name contains illegal characters
   if illegalChars in namespaceURI or illegalChars in qualifiedName:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   var elNode: PElement
   new(elNode)
   elNode.FTagName = qualifiedName
@@ -327,18 +327,18 @@ proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: strin
   elNode.FNamespaceURI = namespaceURI
   elNode.childNodes = @[]
   elNode.attributes = @[]
-  
+
   elNode.FNodeType = ElementNode
-  
+
   return elNode
 
-proc createProcessingInstruction*(doc: PDocument, target: string, data: string): PProcessingInstruction = 
-  ## Creates a ProcessingInstruction node given the specified name and data strings. 
-  
+proc createProcessingInstruction*(doc: PDocument, target: string, data: string): PProcessingInstruction =
+  ## Creates a ProcessingInstruction node given the specified name and data strings.
+
   #Check if name contains illegal characters
   if illegalChars in target:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   var PI: PProcessingInstruction
   new(PI)
   PI.FTarget = target
@@ -347,13 +347,13 @@ proc createProcessingInstruction*(doc: PDocument, target: string, data: string):
   return PI
 
 proc createTextNode*(doc: PDocument, data: string): PText = #Propably TextNode
-  ## Creates a Text node given the specified string. 
+  ## Creates a Text node given the specified string.
   var txtNode: PText
   new(txtNode)
   txtNode.data = data
   txtNode.nodeValue = data
   txtNode.FNodeName = "#text"
-  
+
   txtNode.FNodeType = TextNode
   return txtNode
 
@@ -363,22 +363,22 @@ discard """proc getElementById*(doc: PDocument, elementId: string): PElement =
 
 proc getElementsByTagName*(doc: PDocument, tagName: string): seq[PNode] =
   ## Returns a NodeList of all the Elements with a given tag name in
-  ## the order in which they are encountered in a preorder traversal of the Document tree. 
+  ## the order in which they are encountered in a preorder traversal of the Document tree.
   var result: seq[PNode] = @[]
   if doc.FDocumentElement.FNodeName == tagName or tagName == "*":
     result.add(doc.FDocumentElement)
-  
+
   result.add(doc.FDocumentElement.findNodes(tagName))
   return result
-  
+
 proc getElementsByTagNameNS*(doc: PDocument, namespaceURI: string, localName: string): seq[PNode] =
   ## Returns a NodeList of all the Elements with a given localName and namespaceURI
-  ## in the order in which they are encountered in a preorder traversal of the Document tree. 
+  ## in the order in which they are encountered in a preorder traversal of the Document tree.
   var result: seq[PNode] = @[]
   if doc.FDocumentElement.FLocalName == localName or localName == "*":
     if doc.FDocumentElement.FNamespaceURI == namespaceURI or namespaceURI == "*":
       result.add(doc.FDocumentElement)
-      
+
   result.add(doc.FDocumentElement.findNodesNS(namespaceURI, localName))
   return result
 
@@ -406,7 +406,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
     if deep:
       for i in low(tmp.len())..high(tmp.len()):
         n.childNodes.add(importNode(doc, tmp[i], deep))
-        
+
     return n
   of ElementNode:
     var n: PNode
@@ -414,7 +414,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
     n = importedNode
     n.FOwnerDocument = doc
     n.FParentNode = nil
-    
+
     var tmpA: seq[PAttr] = n.attributes
     n.attributes = @[]
     # Import the Element node's attributes
@@ -426,7 +426,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
     if deep:
       for i in low(tmp.len())..high(tmp.len()):
         n.childNodes.add(importNode(doc, tmp[i], deep))
-        
+
     return n
   of ProcessingInstructionNode, TextNode, CDataSectionNode, CommentNode:
     var n: PNode
@@ -437,27 +437,27 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
     return n
   else:
     raise newException(ENotSupportedErr, "The type of node being imported is not supported")
-  
+
 
 # Node
 # Attributes
-  
+
 proc firstChild*(n: PNode): PNode =
   ## Returns this node's first child
 
-  if n.childNodes.len() > 0:
+  if not isNil(n.childNodes) and n.childNodes.len() > 0:
     return n.childNodes[0]
   else:
     return nil
-  
+
 proc lastChild*(n: PNode): PNode =
   ## Returns this node's last child
 
-  if n.childNodes.len() > 0:
+  if not isNil(n.childNodes) and n.childNodes.len() > 0:
     return n.childNodes[n.childNodes.len() - 1]
   else:
     return nil
-  
+
 proc localName*(n: PNode): string =
   ## Returns this nodes local name
 
@@ -465,15 +465,17 @@ proc localName*(n: PNode): string =
 
 proc namespaceURI*(n: PNode): string =
   ## Returns this nodes namespace URI
-  
+
   return n.FNamespaceURI
-  
-proc `namespaceURI=`*(n: PNode, value: string) = 
+
+proc `namespaceURI=`*(n: PNode, value: string) =
   n.FNamespaceURI = value
 
 proc nextSibling*(n: PNode): PNode =
   ## Returns the next sibling of this node
 
+  if isNil(n.FParentNode) or isNil(n.FParentNode.childNodes):
+    return nil
   var nLow: int = low(n.FParentNode.childNodes)
   var nHigh: int = high(n.FParentNode.childNodes)
   for i in nLow..nHigh:
@@ -500,17 +502,19 @@ proc parentNode*(n: PNode): PNode =
   ## Returns the parent node of this node
 
   return n.FParentNode
-  
+
 proc previousSibling*(n: PNode): PNode =
   ## Returns the previous sibling of this node
 
+  if isNil(n.FParentNode) or isNil(n.FParentNode.childNodes):
+    return nil
   var nLow: int = low(n.FParentNode.childNodes)
   var nHigh: int = high(n.FParentNode.childNodes)
   for i in nLow..nHigh:
     if n.FParentNode.childNodes[i] == n:
       return n.FParentNode.childNodes[i - 1]
   return nil
-  
+
 proc `prefix=`*(n: PNode, value: string) =
   ## Modifies the prefix of this node
 
@@ -519,13 +523,13 @@ proc `prefix=`*(n: PNode, value: string) =
   if illegalChars in value:
     raise newException(EInvalidCharacterErr, "Invalid character")
 
-  if n.FNamespaceURI == nil:
+  if isNil(n.FNamespaceURI):
     raise newException(ENamespaceErr, "namespaceURI cannot be nil")
   elif value.toLower() == "xml" and n.FNamespaceURI != "http://www.w3.org/XML/1998/namespace":
-    raise newException(ENamespaceErr, 
+    raise newException(ENamespaceErr,
       "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
   elif value.toLower() == "xmlns" and n.FNamespaceURI != "http://www.w3.org/2000/xmlns/":
-    raise newException(ENamespaceErr, 
+    raise newException(ENamespaceErr,
       "When the namespace prefix is \"xmlns\" namespaceURI has to be \"http://www.w3.org/2000/xmlns/\"")
   elif value.toLower() == "xmlns" and n.FNodeType == AttributeNode:
     raise newException(ENamespaceErr, "An AttributeNode cannot have a prefix of \"xmlns\"")
@@ -543,33 +547,33 @@ proc `prefix=`*(n: PNode, value: string) =
 proc appendChild*(n: PNode, newChild: PNode) =
   ## Adds the node newChild to the end of the list of children of this node.
   ## If the newChild is already in the tree, it is first removed.
-  
+
   # Check if n contains newChild
-  if not IsNil(n.childNodes):
+  if not isNil(n.childNodes):
     for i in low(n.childNodes)..high(n.childNodes):
       if n.childNodes[i] == newChild:
         raise newException(EHierarchyRequestErr, "The node to append is already in this nodes children.")
-  
+
   # Check if newChild is from this nodes document
   if n.FOwnerDocument != newChild.FOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-  
+
   if n == newChild:
     raise newException(EHierarchyRequestErr, "You can't add a node into itself")
-  
+
   if n.nodeType in childlessObjects:
     raise newException(ENoModificationAllowedErr, "Cannot append children to a childless node")
-  
+
   if isNil(n.childNodes): n.childNodes = @[]
-    
+
   newChild.FParentNode = n
   for i in low(n.childNodes)..high(n.childNodes):
     if n.childNodes[i] == newChild:
       n.childNodes[i] = newChild
-    
+
   n.childNodes.add(newChild)
 
-proc cloneNode*(n: PNode, deep: bool): PNode = 
+proc cloneNode*(n: PNode, deep: bool): PNode =
   ## Returns a duplicate of this node, if ``deep`` is `true`, Element node's children are copied
   case n.FNodeType
   of AttributeNode:
@@ -586,7 +590,7 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
     # Import the childNodes
     var tmp: seq[PNode] = n.childNodes
     n.childNodes = @[]
-    if deep:
+    if deep and not isNil(tmp):
       for i in low(tmp.len())..high(tmp.len()):
         n.childNodes.add(cloneNode(tmp[i], deep))
     return newNode
@@ -597,34 +601,39 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
     return newNode
 
 proc hasAttributes*(n: PNode): bool =
-  ## Returns whether this node (if it is an element) has any attributes. 
-  return n.attributes.len() > 0
+  ## Returns whether this node (if it is an element) has any attributes.
+  return not isNil(n.attributes) and n.attributes.len() > 0
 
-proc hasChildNodes*(n: PNode): bool = 
+proc hasChildNodes*(n: PNode): bool =
   ## Returns whether this node has any children.
-  return n.childNodes.len() > 0
+  return not isNil(n.childNodes) and n.childNodes.len() > 0
 
 proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
   ## Inserts the node ``newChild`` before the existing child node ``refChild``.
   ## If ``refChild`` is nil, insert ``newChild`` at the end of the list of children.
-  
+
   # Check if newChild is from this nodes document
   if n.FOwnerDocument != newChild.FOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-    
+
+  if isNil(n.childNodes):
+    n.ChildNodes = @[]
+
   for i in low(n.childNodes)..high(n.childNodes):
     if n.childNodes[i] == refChild:
       n.childNodes.insert(newChild, i - 1)
-    return
+      return
+
+  n.ChildNodes.add(newChild)
 
 proc isSupported*(n: PNode, feature: string, version: string): bool =
-  ## Tests whether the DOM implementation implements a specific 
-  ## feature and that feature is supported by this node. 
+  ## Tests whether the DOM implementation implements a specific
+  ## feature and that feature is supported by this node.
   return n.FOwnerDocument.FImplementation.hasFeature(feature, version)
 
 proc isEmpty(s: string): bool =
 
-  if s == "" or s == nil:
+  if isNil(s) or s == "":
     return True
   for i in items(s):
     if i != ' ':
@@ -635,18 +644,18 @@ proc normalize*(n: PNode) =
   ## Merges all seperated TextNodes together, and removes any empty TextNodes
   var curTextNode: PNode = nil
   var i: int = 0
-  
+
   var newChildNodes: seq[PNode] = @[]
   while True:
-    if i >= n.childNodes.len:
+    if isNil(n.childNodes) or i >= n.childNodes.len:
       break
     if n.childNodes[i].nodeType == TextNode:
-      
+
       #If the TextNode is empty, remove it
       if PText(n.childNodes[i]).data.isEmpty():
         inc(i)
-      
-      if curTextNode == nil:
+
+      if isNil(curTextNode):
         curTextNode = n.childNodes[i]
       else:
         PText(curTextNode).data.add(PText(n.childNodes[i]).data)
@@ -656,35 +665,37 @@ proc normalize*(n: PNode) =
       newChildNodes.add(curTextNode)
       newChildNodes.add(n.childNodes[i])
       curTextNode = nil
-    
+
     inc(i)
   n.childNodes = newChildNodes
 
 proc removeChild*(n: PNode, oldChild: PNode): PNode =
   ## Removes the child node indicated by ``oldChild`` from the list of children, and returns it.
-  for i in low(n.childNodes)..high(n.childNodes):
-    if n.childNodes[i] == oldChild:
-      result = n.childNodes[i]
-      n.childNodes.delete(i)
-      return result
-      
+  if not isNil(n.childNodes):
+    for i in low(n.childNodes)..high(n.childNodes):
+      if n.childNodes[i] == oldChild:
+        result = n.childNodes[i]
+        n.childNodes.delete(i)
+        return result
+
   raise newException(ENotFoundErr, "Node not found")
-    
+
 proc replaceChild*(n: PNode, newChild: PNode, oldChild: PNode): PNode =
   ## Replaces the child node ``oldChild`` with ``newChild`` in the list of children, and returns the ``oldChild`` node.
-  
+
   # Check if newChild is from this nodes document
   if n.FOwnerDocument != newChild.FOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-  
-  for i in low(n.childNodes)..high(n.childNodes):
-    if n.childNodes[i] == oldChild:
-      result = n.childNodes[i]
-      n.childNodes[i] = newChild
-      return result
-  
+
+  if not isNil(n.childNodes):
+    for i in low(n.childNodes)..high(n.childNodes):
+      if n.childNodes[i] == oldChild:
+        result = n.childNodes[i]
+        n.childNodes[i] = newChild
+        return result
+
   raise newException(ENotFoundErr, "Node not found")
-  
+
 # NamedNodeMap
 
 proc getNamedItem*(NList: seq[PNode], name: string): PNode =
@@ -693,22 +704,22 @@ proc getNamedItem*(NList: seq[PNode], name: string): PNode =
     if i.nodeName() == name:
       return i
   return nil
-  
+
 proc getNamedItem*(NList: seq[PAttr], name: string): PAttr =
   ## Retrieves a node specified by ``name``. If this node cannot be found returns ``nil``
   for i in items(NList):
     if i.nodeName() == name:
       return i
   return nil
-      
+
 proc getNamedItemNS*(NList: seq[PNode], namespaceURI: string, localName: string): PNode =
   ## Retrieves a node specified by ``localName`` and ``namespaceURI``. If this node cannot be found returns ``nil``
   for i in items(NList):
     if i.namespaceURI() == namespaceURI and i.localName() == localName:
       return i
   return nil
-  
-proc getNamedItemNS*(NList: seq[PAttr], namespaceURI: string, localName: string): PAttr = 
+
+proc getNamedItemNS*(NList: seq[PAttr], namespaceURI: string, localName: string): PAttr =
   ## Retrieves a node specified by ``localName`` and ``namespaceURI``. If this node cannot be found returns ``nil``
   for i in items(NList):
     if i.NamespaceURI() == namespaceURI and i.LocalName() == localName:
@@ -716,7 +727,7 @@ proc getNamedItemNS*(NList: seq[PAttr], namespaceURI: string, localName: string)
   return nil
 
 proc item*(NList: seq[PNode], index: int): PNode =
-  ## Returns the ``index`` th item in the map. 
+  ## Returns the ``index`` th item in the map.
   ## If ``index`` is greater than or equal to the number of nodes in this map, this returns ``nil``.
   if index >= NList.len(): return nil
   else: return NList[index]
@@ -729,9 +740,9 @@ proc removeNamedItem*(NList: var seq[PNode], name: string): PNode =
       result = NList[i]
       NList.delete(i)
       return result
-  
+
   raise newException(ENotFoundErr, "Node not found")
-  
+
 proc removeNamedItemNS*(NList: var seq[PNode], namespaceURI: string, localName: string): PNode =
   ## Removes a node specified by local name and namespace URI
   for i in low(NList)..high(NList):
@@ -739,7 +750,7 @@ proc removeNamedItemNS*(NList: var seq[PNode], namespaceURI: string, localName:
       result = NList[i]
       NList.delete(i)
       return result
-  
+
   raise newException(ENotFoundErr, "Node not found")
 
 proc setNamedItem*(NList: var seq[PNode], arg: PNode): PNode =
@@ -751,9 +762,9 @@ proc setNamedItem*(NList: var seq[PNode], arg: PNode): PNode =
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
   #Exceptions End
-  
+
   var item: PNode = NList.getNamedItem(arg.NodeName())
-  if item == nil:
+  if isNil(item):
     NList.add(arg)
     return nil
   else:
@@ -765,22 +776,22 @@ proc setNamedItem*(NList: var seq[PNode], arg: PNode): PNode =
         break
     NList[index] = arg
     return item # Return the replaced node
-    
+
 proc setNamedItem*(NList: var seq[PAttr], arg: PAttr): PAttr =
   ## Adds ``arg`` as a ``Node`` to the ``NList``
   ## If a node with the same name is already present in this map, it is replaced by the new one.
-  if not IsNil(NList):
+  if not isNil(NList):
     if NList.len() > 0:
       # Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-        
-  if arg.FOwnerElement != nil:
+
+  if not isNil(arg.FOwnerElement):
     raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
-        
+
   # Exceptions end
   var item: PAttr = NList.getNamedItem(arg.nodeName())
-  if item == nil:
+  if isNil(item):
     NList.add(arg)
     return nil
   else:
@@ -792,18 +803,18 @@ proc setNamedItem*(NList: var seq[PAttr], arg: PAttr): PAttr =
         break
     NList[index] = arg
     return item # Return the replaced node
-    
+
 proc setNamedItemNS*(NList: var seq[PNode], arg: PNode): PNode =
   ## Adds a node using its ``namespaceURI`` and ``localName``
-  if not IsNil(NList):
+  if not isNil(NList):
     if NList.len() > 0:
       # Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
   #Exceptions end
-        
+
   var item: PNode = NList.getNamedItemNS(arg.namespaceURI(), arg.localName())
-  if item == nil:
+  if isNil(item):
     NList.add(arg)
     return nil
   else:
@@ -815,7 +826,7 @@ proc setNamedItemNS*(NList: var seq[PNode], arg: PNode): PNode =
         break
     NList[index] = arg
     return item # Return the replaced node
-    
+
 proc setNamedItemNS*(NList: var seq[PAttr], arg: PAttr): PAttr =
   ## Adds a node using its ``namespaceURI`` and ``localName``
   if not isNil(NList):
@@ -823,13 +834,13 @@ proc setNamedItemNS*(NList: var seq[PAttr], arg: PAttr): PAttr =
       # Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-        
-  if arg.FOwnerElement != nil:
+
+  if not isNil(arg.FOwnerElement):
     raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
-        
+
   # Exceptions end
   var item: PAttr = NList.getNamedItemNS(arg.namespaceURI(), arg.localName())
-  if item == nil:
+  if isNil(item):
     NList.add(arg)
     return nil
   else:
@@ -841,8 +852,8 @@ proc setNamedItemNS*(NList: var seq[PAttr], arg: PAttr): PAttr =
         break
     NList[index] = arg
     return item # Return the replaced node
-    
-# CharacterData - Decided to implement this, 
+
+# CharacterData - Decided to implement this,
 # Didn't add the procedures, because you can just edit .data
 
 # Attr
@@ -851,13 +862,13 @@ proc name*(a: PAttr): string =
   ## Returns the name of the Attribute
 
   return a.FName
-  
+
 proc specified*(a: PAttr): bool =
   ## Specifies whether this attribute was specified in the original document
 
   return a.FSpecified
-  
-proc ownerElement*(a: PAttr): PElement = 
+
+proc ownerElement*(a: PAttr): PElement =
   ## Returns this Attributes owner element
 
   return a.FOwnerElement
@@ -873,27 +884,35 @@ proc tagName*(el: PElement): string =
 # Procedures
 proc getAttribute*(el: PElement, name: string): string =
   ## Retrieves an attribute value by ``name``
+  if isNil(el.attributes):
+    return nil
   var attribute = el.attributes.getNamedItem(name)
-  if attribute != nil:
+  if not isNil(attribute):
     return attribute.value
   else:
     return nil
 
 proc getAttributeNS*(el: PElement, namespaceURI: string, localName: string): string =
   ## Retrieves an attribute value by ``localName`` and ``namespaceURI``
+  if isNil(el.attributes):
+    return nil
   var attribute = el.attributes.getNamedItemNS(namespaceURI, localName)
-  if attribute != nil:
+  if not isNil(attribute):
     return attribute.value
   else:
     return nil
-    
+
 proc getAttributeNode*(el: PElement, name: string): PAttr =
   ## Retrieves an attribute node by ``name``
   ## To retrieve an attribute node by qualified name and namespace URI, use the `getAttributeNodeNS` method
+  if isNil(el.attributes):
+    return nil
   return el.attributes.getNamedItem(name)
 
 proc getAttributeNodeNS*(el: PElement, namespaceURI: string, localName: string): PAttr =
   ## Retrieves an `Attr` node by ``localName`` and ``namespaceURI``
+  if isNil(el.attributes):
+    return nil
   return el.attributes.getNamedItemNS(namespaceURI, localName)
 
 proc getElementsByTagName*(el: PElement, name: string): seq[PNode] =
@@ -909,103 +928,110 @@ proc getElementsByTagNameNS*(el: PElement, namespaceURI: string, localName: stri
   result = el.findNodesNS(namespaceURI, localName)
 
 proc hasAttribute*(el: PElement, name: string): bool =
-  ## Returns ``true`` when an attribute with a given ``name`` is specified 
-  ## on this element , ``false`` otherwise. 
-  return el.attributes.getNamedItem(name) != nil
+  ## Returns ``true`` when an attribute with a given ``name`` is specified
+  ## on this element , ``false`` otherwise.
+  if isNil(el.attributes):
+    return false
+  return not isNil(el.attributes.getNamedItem(name))
 
 proc hasAttributeNS*(el: PElement, namespaceURI: string, localName: string): bool =
   ## Returns ``true`` when an attribute with a given ``localName`` and
-  ## ``namespaceURI`` is specified on this element , ``false`` otherwise 
-  return el.attributes.getNamedItemNS(namespaceURI, localName) != nil
+  ## ``namespaceURI`` is specified on this element , ``false`` otherwise
+  if isNil(el.attributes):
+    return false
+  return not isNil(el.attributes.getNamedItemNS(namespaceURI, localName))
 
 proc removeAttribute*(el: PElement, name: string) =
   ## Removes an attribute by ``name``
-  for i in low(el.attributes)..high(el.attributes):
-    if el.attributes[i].FName == name:
-      el.attributes.delete(i)
-      
+  if not isNil(el.attributes):
+    for i in low(el.attributes)..high(el.attributes):
+      if el.attributes[i].FName == name:
+        el.attributes.delete(i)
+
 proc removeAttributeNS*(el: PElement, namespaceURI: string, localName: string) =
   ## Removes an attribute by ``localName`` and ``namespaceURI``
-  for i in low(el.attributes)..high(el.attributes):
-    if el.attributes[i].FNamespaceURI == namespaceURI and 
-        el.attributes[i].FLocalName == localName:
-      el.attributes.delete(i)
-  
+  if not isNil(el.attributes):
+    for i in low(el.attributes)..high(el.attributes):
+      if el.attributes[i].FNamespaceURI == namespaceURI and
+          el.attributes[i].FLocalName == localName:
+        el.attributes.delete(i)
+
 proc removeAttributeNode*(el: PElement, oldAttr: PAttr): PAttr =
   ## Removes the specified attribute node
   ## If the attribute node cannot be found raises ``ENotFoundErr``
-  for i in low(el.attributes)..high(el.attributes):
-    if el.attributes[i] == oldAttr:
-      result = el.attributes[i]
-      el.attributes.delete(i)
-      return result
-  
+  if not isNil(el.attributes):
+    for i in low(el.attributes)..high(el.attributes):
+      if el.attributes[i] == oldAttr:
+        result = el.attributes[i]
+        el.attributes.delete(i)
+        return result
+
   raise newException(ENotFoundErr, "oldAttr is not a member of el's Attributes")
 
 proc setAttributeNode*(el: PElement, newAttr: PAttr): PAttr =
   ## Adds a new attribute node, if an attribute with the same `nodeName` is
   ## present, it is replaced by the new one and the replaced attribute is
   ## returned, otherwise ``nil`` is returned.
-  
+
   # Check if newAttr is from this nodes document
   if el.FOwnerDocument != newAttr.FOwnerDocument:
-    raise newException(EWrongDocumentErr, 
+    raise newException(EWrongDocumentErr,
       "This node belongs to a different document, use importNode.")
-        
-  if newAttr.FOwnerElement != nil:
-    raise newException(EInuseAttributeErr, 
+
+  if not isNil(newAttr.FOwnerElement):
+    raise newException(EInuseAttributeErr,
       "This attribute is in use by another element, use cloneNode")
   # Exceptions end
-  
+
   if isNil(el.attributes): el.attributes = @[]
   return el.attributes.setNamedItem(newAttr)
-  
+
 proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
-  ## Adds a new attribute node, if an attribute with the localName and 
+  ## Adds a new attribute node, if an attribute with the localName and
   ## namespaceURI of ``newAttr`` is present, it is replaced by the new one
   ## and the replaced attribute is returned, otherwise ``nil`` is returned.
-  
+
   # Check if newAttr is from this nodes document
   if el.FOwnerDocument != newAttr.FOwnerDocument:
-    raise newException(EWrongDocumentErr, 
+    raise newException(EWrongDocumentErr,
       "This node belongs to a different document, use importNode.")
-        
-  if newAttr.FOwnerElement != nil:
-    raise newException(EInuseAttributeErr, 
+
+  if not isNil(newAttr.FOwnerElement):
+    raise newException(EInuseAttributeErr,
       "This attribute is in use by another element, use cloneNode")
   # Exceptions end
-  
+
   if isNil(el.attributes): el.attributes = @[]
   return el.attributes.setNamedItemNS(newAttr)
 
 proc setAttribute*(el: PElement, name: string, value: string) =
   ## Adds a new attribute, as specified by ``name`` and ``value``
-  ## If an attribute with that name is already present in the element, its 
+  ## If an attribute with that name is already present in the element, its
   ## value is changed to be that of the value parameter
-  ## Raises the EInvalidCharacterErr if the specified ``name`` contains 
+  ## Raises the EInvalidCharacterErr if the specified ``name`` contains
   ## illegal characters
   var AttrNode = el.FOwnerDocument.createAttribute(name)
   # Check if name contains illegal characters
   if illegalChars in name:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   discard el.setAttributeNode(AttrNode)
   # Set the info later, the setAttributeNode checks
   # if FOwnerElement is nil, and if it isn't it raises an exception
   AttrNode.FOwnerElement = el
   AttrNode.FSpecified = True
   AttrNode.value = value
-  
+
 proc setAttributeNS*(el: PElement, namespaceURI, localName, value: string) =
-  ## Adds a new attribute, as specified by ``namespaceURI``, ``localName`` 
+  ## Adds a new attribute, as specified by ``namespaceURI``, ``localName``
   ## and ``value``.
-  
+
   # Check if name contains illegal characters
   if illegalChars in namespaceURI or illegalChars in localName:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   var AttrNode = el.FOwnerDocument.createAttributeNS(namespaceURI, localName)
-    
+
   discard el.setAttributeNodeNS(AttrNode)
   # Set the info later, the setAttributeNode checks
   # if FOwnerElement is nil, and if it isn't it raises an exception
@@ -1013,19 +1039,19 @@ proc setAttributeNS*(el: PElement, namespaceURI, localName, value: string) =
   AttrNode.FSpecified = True
   AttrNode.value = value
 
-# Text  
+# Text
 proc splitData*(TextNode: PText, offset: int): PText =
-  ## Breaks this node into two nodes at the specified offset, 
+  ## Breaks this node into two nodes at the specified offset,
   ## keeping both in the tree as siblings.
-  
+
   if offset > TextNode.data.len():
     raise newException(EIndexSizeErr, "Index out of bounds")
-  
+
   var left: string = TextNode.data.substr(0, offset)
   TextNode.data = left
   var right: string = TextNode.data.substr(offset, TextNode.data.len())
-  
-  if TextNode.FParentNode != nil:
+
+  if not isNil(TextNode.FParentNode) and not isNil(TextNode.FParentNode.childNodes):
     for i in low(TextNode.FParentNode.childNodes)..high(TextNode.FParentNode.childNodes):
       if TextNode.FParentNode.childNodes[i] == TextNode:
         var newNode: PText = TextNode.FOwnerDocument.createTextNode(right)
@@ -1042,10 +1068,10 @@ proc target*(PI: PProcessingInstruction): string =
 
   return PI.FTarget
 
-    
+
 # --Other stuff--
 # Writer
-proc addEscaped(s: string): string = 
+proc addEscaped(s: string): string =
   result = ""
   for c in items(s):
     case c
@@ -1057,10 +1083,11 @@ proc addEscaped(s: string): string =
 
 proc nodeToXml(n: PNode, indent: int = 0): string =
   result = repeatChar(indent, ' ') & "<" & n.nodeName
-  for i in items(n.Attributes):
-    result.add(" " & i.name & "=\"" & addEscaped(i.value) & "\"")
-  
-  if n.childNodes.len() == 0:
+  if not isNil(n.attributes):
+    for i in items(n.attributes):
+      result.add(" " & i.name & "=\"" & addEscaped(i.value) & "\"")
+
+  if isNil(n.childNodes) or n.childNodes.len() == 0:
     result.add("/>") # No idea why this doesn't need a \n :O
   else:
     # End the beginning of this tag
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 95b48a850d..1af7db7d55 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -151,6 +151,8 @@ proc addEscaped*(result: var string, s: string) =
     of '>': result.add(">")
     of '&': result.add("&")
     of '"': result.add(""")
+    of '\'': result.add("'")
+    of '/': result.add("/")
     else: result.add(c)
 
 proc escape*(s: string): string = 
@@ -164,6 +166,8 @@ proc escape*(s: string): string =
   ##  ``>``          ``>``
   ##  ``&``          ``&``
   ##  ``"``          ``"``
+  ##  ``'``          ``'``
+  ##  ``/``          ``/``
   ## ------------    -------------------
   result = newStringOfCap(s.len)
   addEscaped(result, s)
diff --git a/lib/system.nim b/lib/system.nim
index 3bb6325367..0df8849f5a 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -13,6 +13,21 @@
 ## Each module implicitly imports the System module; it must not be listed
 ## explicitly. Because of this there cannot be a user-defined module named
 ## ``system``.
+##
+## Exception hierarchy
+## ===================
+##
+## For visual convenience here is the exception inheritance hierarchy
+## represented as a tree:
+##
+## .. include:: ../doc/exception_hierarchy_fragment.txt
+##
+## Module system
+## =============
+##
+
+# That lonesome header above is to prevent :idx: entries from being mentioned
+# in the global index as part of the previous header (Exception hierarchy).
 
 type
   int* {.magic: Int.} ## default integer type; bitwidth depends on
@@ -83,16 +98,8 @@ type
 
 proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
   ## Special compile-time procedure that checks whether `x` is
-  ## defined. `x` has to be an identifier or a qualified identifier.
-  ## This can be used to check whether a library provides a certain
-  ## feature or not:
-  ##
-  ## .. code-block:: Nimrod
-  ##   when not defined(strutils.toUpper):
-  ##     # provide our own toUpper proc here, because strutils is
-  ##     # missing it.
-  ##
-  ## You can also check external symbols introduced through the compiler's
+  ## defined.
+  ## `x` is an external symbol introduced through the compiler's
   ## `-d:x switch `_ to enable build time
   ## conditionals:
   ##
@@ -101,13 +108,28 @@ proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
   ##     # Do here programmer friendly expensive sanity checks.
   ##   # Put here the normal code
 
+proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
+  ## Special compile-time procedure that checks whether `x` is
+  ## declared. `x` has to be an identifier or a qualified identifier.
+  ## This can be used to check whether a library provides a certain
+  ## feature or not:
+  ##
+  ## .. code-block:: Nimrod
+  ##   when not defined(strutils.toUpper):
+  ##     # provide our own toUpper proc here, because strutils is
+  ##     # missing it.
+
 when defined(useNimRtl):
   {.deadCodeElim: on.}
 
 proc definedInScope*(x: expr): bool {.
+  magic: "DefinedInScope", noSideEffect, deprecated.}
+  ## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
+
+proc declaredInScope*(x: expr): bool {.
   magic: "DefinedInScope", noSideEffect.}
   ## Special compile-time procedure that checks whether `x` is
-  ## defined in the current scope. `x` has to be an identifier.
+  ## declared in the current scope. `x` has to be an identifier.
 
 proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
   ## Boolean not; returns true iff ``x == false``.
@@ -301,9 +323,11 @@ type
   FWriteIO* = object of FIO    ## Effect describing a write IO operation.
   FExecIO* = object of FIO     ## Effect describing an executing IO operation.
 
-  E_Base* {.compilerproc.} = object of TObject ## base exception class;
-                                               ## each exception has to
-                                               ## inherit from `E_Base`.
+  E_Base* {.compilerproc.} = object of TObject ## \
+    ## Base exception class.
+    ##
+    ## Each exception has to inherit from `E_Base`. See the full `exception
+    ## hierarchy`_.
     parent: ref E_Base        ## parent exception (can be used as a stack)
     name: cstring             ## The exception's name is its Nimrod identifier.
                               ## This field is filled automatically in the
@@ -313,99 +337,142 @@ type
                                         ## is bad style.
     trace: string
 
-  EAsynch* = object of E_Base ## Abstract exception class for
-                              ## *asynchronous exceptions* (interrupts).
-                              ## This is rarely needed: Most
-                              ## exception types inherit from `ESynch`
-  ESynch* = object of E_Base  ## Abstract exception class for
-                              ## *synchronous exceptions*. Most exceptions
-                              ## should be inherited (directly or indirectly)
-                              ## from ESynch.
-  ESystem* = object of ESynch ## Abstract class for exceptions that the runtime
-                              ## system raises.
-  EIO* = object of ESystem    ## raised if an IO error occured.
-  EOS* = object of ESystem    ## raised if an operating system service failed.
+  EAsynch* = object of E_Base ## \
+    ## Abstract exception class for *asynchronous exceptions* (interrupts).
+    ##
+    ## This is rarely needed: most exception types inherit from `ESynch
+    ## <#ESynch>`_. See the full `exception hierarchy`_.
+  EControlC* = object of EAsynch ## \
+    ## Raised for Ctrl+C key presses in console applications.
+    ##
+    ## See the full `exception hierarchy`_.
+  ESynch* = object of E_Base ## \
+    ## Abstract exception class for *synchronous exceptions*.
+    ##
+    ## Most exceptions should be inherited (directly or indirectly) from
+    ## `ESynch` instead of from `EAsynch <#EAsynch>`_. See the full `exception
+    ## hierarchy`_.
+  ESystem* = object of ESynch ## \
+    ## Abstract class for exceptions that the runtime system raises.
+    ##
+    ## See the full `exception hierarchy`_.
+  EIO* = object of ESystem ## \
+    ## Raised if an IO error occured.
+    ##
+    ## See the full `exception hierarchy`_.
+  EOS* = object of ESystem ## \
+    ## Raised if an operating system service failed.
+    ##
+    ## See the full `exception hierarchy`_.
     errorCode*: int32 ## OS-defined error code describing this error.
-  EInvalidLibrary* = object of EOS ## raised if a dynamic library
-                                   ## could not be loaded.
-  EResourceExhausted* = object of ESystem ## raised if a resource request
-                                          ## could not be fullfilled.
-  EArithmetic* = object of ESynch       ## raised if any kind of arithmetic
-                                        ## error occured.
-  EDivByZero* {.compilerproc.} =
-    object of EArithmetic ## is the exception class for integer divide-by-zero
-                          ## errors.
-  EOverflow* {.compilerproc.} =
-    object of EArithmetic  ## is the exception class for integer calculations
-                           ## whose results are too large to fit in the
-                           ## provided bits.
+  EInvalidLibrary* = object of EOS ## \
+    ## Raised if a dynamic library could not be loaded.
+    ##
+    ## See the full `exception hierarchy`_.
+  EResourceExhausted* = object of ESystem ## \
+    ## Raised if a resource request could not be fullfilled.
+    ##
+    ## See the full `exception hierarchy`_.
+  EArithmetic* = object of ESynch ## \
+    ## Raised if any kind of arithmetic error occured.
+    ##
+    ## See the full `exception hierarchy`_.
+  EDivByZero* {.compilerproc.} = object of EArithmetic ## \
+    ## Raised for runtime integer divide-by-zero errors.
+    ##
+    ## See the full `exception hierarchy`_.
+  EOverflow* {.compilerproc.} = object of EArithmetic ## \
+    ## Raised for runtime integer overflows.
+    ##
+    ## This happens for calculations whose results are too large to fit in the
+    ## provided bits.  See the full `exception hierarchy`_.
+  EAccessViolation* {.compilerproc.} = object of ESynch ## \
+    ## Raised for invalid memory access errors
+    ##
+    ## See the full `exception hierarchy`_.
+  EAssertionFailed* {.compilerproc.} = object of ESynch ## \
+    ## Raised when assertion is proved wrong.
+    ##
+    ## Usually the result of using the `assert() template <#assert>`_.  See the
+    ## full `exception hierarchy`_.
+  EInvalidValue* = object of ESynch ## \
+    ## Raised for string and object conversion errors.
+  EInvalidKey* = object of EInvalidValue ## \
+    ## Raised if a key cannot be found in a table.
+    ##
+    ## Mostly used by the `tables `_ module, it can also be raised
+    ## by other collection modules like `sets `_ or `strtabs
+    ## `_. See the full `exception hierarchy`_.
+  EOutOfMemory* = object of ESystem ## \
+    ## Raised for unsuccessful attempts to allocate memory.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidIndex* = object of ESynch ## \
+    ## Raised if an array index is out of bounds.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidField* = object of ESynch ## \
+    ## Raised if a record field is not accessible because its dicriminant's
+    ## value does not fit.
+    ##
+    ## See the full `exception hierarchy`_.
+  EOutOfRange* = object of ESynch ## \
+    ## Raised if a range check error occurred.
+    ##
+    ## See the full `exception hierarchy`_.
+  EStackOverflow* = object of ESystem ## \
+    ## Raised if the hardware stack used for subroutine calls overflowed.
+    ##
+    ## See the full `exception hierarchy`_.
+  ENoExceptionToReraise* = object of ESynch ## \
+    ## Raised if there is no exception to reraise.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidObjectAssignment* = object of ESynch ## \
+    ## Raised if an object gets assigned to its parent's object.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidObjectConversion* = object of ESynch ## \
+    ## Raised if an object is converted to an incompatible object type.
+    ##
+    ## See the full `exception hierarchy`_.
+  EFloatingPoint* = object of ESynch ## \
+    ## Base class for floating point exceptions.
+    ##
+    ## See the full `exception hierarchy`_.
+  EFloatInvalidOp* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised by invalid operations according to IEEE.
+    ##
+    ## Raised by ``0.0/0.0``, for example.  See the full `exception
+    ## hierarchy`_.
+  EFloatDivByZero* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised by division by zero.
+    ##
+    ## Divisor is zero and dividend is a finite nonzero number.  See the full
+    ## `exception hierarchy`_.
+  EFloatOverflow* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised for overflows.
+    ##
+    ## The operation produced a result that exceeds the range of the exponent.
+    ## See the full `exception hierarchy`_.
+  EFloatUnderflow* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised for underflows.
+    ##
+    ## The operation produced a result that is too small to be represented as a
+    ## normal number. See the full `exception hierarchy`_.
+  EFloatInexact* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised for inexact results.
+    ##
+    ## The operation produced a result that cannot be represented with infinite
+    ## precision -- for example: ``2.0 / 3.0, log(1.1)``
+    ##
+    ## **NOTE**: Nimrod currently does not detect these!  See the full
+    ## `exception hierarchy`_.
+  EDeadThread* = object of ESynch ## \
+    ## Raised if it is attempted to send a message to a dead thread.
+    ##
+    ## See the full `exception hierarchy`_.
 
-  EAccessViolation* {.compilerproc.} =
-    object of ESynch ## the exception class for invalid memory access errors
-
-  EAssertionFailed* {.compilerproc.} =
-    object of ESynch  ## is the exception class for Assert
-                      ## procedures that is raised if the
-                      ## assertion proves wrong
-
-  EControlC* = object of EAsynch        ## is the exception class for Ctrl+C
-                                        ## key presses in console applications.
-
-  EInvalidValue* = object of ESynch     ## is the exception class for string
-                                        ## and object conversion errors.
-  EInvalidKey* = object of EInvalidValue ## is the exception class if a key
-                                         ## cannot be found in a table.
-
-  EOutOfMemory* = object of ESystem     ## is the exception class for
-                                        ## unsuccessful attempts to allocate
-                                        ## memory.
-
-  EInvalidIndex* = object of ESynch     ## is raised if an array index is out
-                                        ## of bounds.
-  EInvalidField* = object of ESynch     ## is raised if a record field is not
-                                        ## accessible because its dicriminant's
-                                        ## value does not fit.
-
-  EOutOfRange* = object of ESynch       ## is raised if a range check error
-                                        ## occurred.
-
-  EStackOverflow* = object of ESystem   ## is raised if the hardware stack
-                                        ## used for subroutine calls overflowed.
-
-  ENoExceptionToReraise* = object of ESynch ## is raised if there is no
-                                            ## exception to reraise.
-
-  EInvalidObjectAssignment* =
-    object of ESynch ## is raised if an object gets assigned to its
-                     ## parent's object.
-
-  EInvalidObjectConversion* =
-    object of ESynch ## is raised if an object is converted to an incompatible
-                     ## object type.
-
-  EFloatingPoint* = object of ESynch ## base class for floating point exceptions
-  EFloatInvalidOp* {.compilerproc.} = 
-    object of EFloatingPoint ## Invalid operation according to IEEE: Raised by 
-                             ## 0.0/0.0, for example.
-  EFloatDivByZero* {.compilerproc.} = 
-    object of EFloatingPoint ## Division by zero. Divisor is zero and dividend 
-                             ## is a finite nonzero number.
-  EFloatOverflow* {.compilerproc.} = 
-    object of EFloatingPoint ## Overflow. Operation produces a result 
-                             ## that exceeds the range of the exponent
-  EFloatUnderflow* {.compilerproc.} = 
-    object of EFloatingPoint ## Underflow. Operation produces a result 
-                             ## that is too small to be represented as 
-                             ## a normal number
-  EFloatInexact* {.compilerproc.} = 
-    object of EFloatingPoint ## Inexact. Operation produces a result
-                             ## that cannot be represented with infinite
-                             ## precision -- for example, 2.0 / 3.0, log(1.1) 
-                             ## NOTE: Nimrod currently does not detect these!
-  EDeadThread* =
-    object of ESynch ## is raised if it is attempted to send a message to a
-                     ## dead thread.
-                     
   TResult* = enum Failure, Success
 
 proc sizeof*[T](x: T): Natural {.magic: "SizeOf", noSideEffect.}
@@ -782,13 +849,13 @@ proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
   ##   assert((1..3).contains(4) == false)
   result = s.a <= value and value <= s.b
 
-template `in` * (x, y: expr): expr {.immediate.} = contains(y, x)
-  ## Suger for contains
+template `in` * (x, y: expr): expr {.immediate, dirty.} = contains(y, x)
+  ## Sugar for contains
   ##
   ## .. code-block:: Nimrod
   ##   assert(1 in (1..3) == true)
   ##   assert(5 in (1..3) == false)
-template `notin` * (x, y: expr): expr {.immediate.} = not contains(y, x)
+template `notin` * (x, y: expr): expr {.immediate, dirty.} = not contains(y, x)
   ## Sugar for not containing
   ##
   ## .. code-block:: Nimrod
@@ -814,9 +881,9 @@ proc `of` *[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.}
   ## Checks if `x` has a type of `y`
   ##
   ## .. code-block:: Nimrod
-  ##   assert(EFloatingPoint is EBase)
-  ##   assert(EIO is ESystem)
-  ##   assert(EDivByZero is EBase)
+  ##   assert(EFloatingPoint of EBase)
+  ##   assert(EIO of ESystem)
+  ##   assert(EDivByZero of EBase)
 
 proc cmp*[T](x, y: T): int {.procvar.} =
   ## Generic compare proc. Returns a value < 0 iff x < y, a value > 0 iff x > y
@@ -1052,7 +1119,7 @@ proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
   ## containers should also call their adding proc `add` for consistency.
   ## Generic code becomes much easier to write if the Nimrod naming scheme is
   ## respected.
-  var xl = x.len
+  let xl = x.len
   setLen(x, xl + y.len)
   for i in 0..high(y): x[xl+i] = y[i]
 
@@ -1066,20 +1133,20 @@ proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".}
 proc del*[T](x: var seq[T], i: int) {.noSideEffect.} = 
   ## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`.
   ## This is an O(1) operation.
-  var xl = x.len
+  let xl = x.len
   shallowCopy(x[i], x[xl-1])
   setLen(x, xl-1)
   
 proc delete*[T](x: var seq[T], i: int) {.noSideEffect.} = 
   ## deletes the item at index `i` by moving ``x[i+1..]`` by one position.
   ## This is an O(n) operation.
-  var xl = x.len
+  let xl = x.len
   for j in i..xl-2: shallowCopy(x[j], x[j+1]) 
   setLen(x, xl-1)
   
 proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} = 
   ## inserts `item` into `x` at position `i`.
-  var xl = x.len
+  let xl = x.len
   setLen(x, xl+1)
   var j = xl-1
   while j >= i:
@@ -1930,16 +1997,16 @@ when not defined(nimrodVM) and hostOS != "standalone":
     ## returns an informative string about the GC's activity. This may be useful
     ## for tweaking.
     
-  proc GC_ref*[T](x: ref T) {.magic: "GCref".}
-  proc GC_ref*[T](x: seq[T]) {.magic: "GCref".}
-  proc GC_ref*(x: string) {.magic: "GCref".}
+  proc GC_ref*[T](x: ref T) {.magic: "GCref", gcsafe.}
+  proc GC_ref*[T](x: seq[T]) {.magic: "GCref", gcsafe.}
+  proc GC_ref*(x: string) {.magic: "GCref", gcsafe.}
     ## marks the object `x` as referenced, so that it will not be freed until
     ## it is unmarked via `GC_unref`. If called n-times for the same object `x`,
     ## n calls to `GC_unref` are needed to unmark `x`. 
     
-  proc GC_unref*[T](x: ref T) {.magic: "GCunref".}
-  proc GC_unref*[T](x: seq[T]) {.magic: "GCunref".}
-  proc GC_unref*(x: string) {.magic: "GCunref".}
+  proc GC_unref*[T](x: ref T) {.magic: "GCunref", gcsafe.}
+  proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", gcsafe.}
+  proc GC_unref*(x: string) {.magic: "GCunref", gcsafe.}
     ## see the documentation of `GC_ref`.
 
 template accumulateResult*(iter: expr) =
@@ -2001,7 +2068,8 @@ type
     procname*: cstring  ## name of the proc that is currently executing
     line*: int          ## line number of the proc that is currently executing
     filename*: cstring  ## filename of the proc that is currently executing
-    len*: int           ## length of the inspectable slots
+    len*: int16         ## length of the inspectable slots
+    calldepth*: int16   ## used for max call depth checking
 
 when defined(JS):
   proc add*(x: var string, y: cstring) {.asmNoStackFrame.} =
@@ -2025,19 +2093,25 @@ elif hostOS != "standalone":
   {.pop.}
 
 proc echo*[T](x: varargs[T, `$`]) {.magic: "Echo", tags: [FWriteIO], gcsafe.}
-  ## special built-in that takes a variable number of arguments. Each argument
+  ## Writes and flushes the parameters to the standard output.
+  ##
+  ## Special built-in that takes a variable number of arguments. Each argument
   ## is converted to a string via ``$``, so it works for user-defined
   ## types that have an overloaded ``$`` operator.
-  ## It is roughly equivalent to ``writeln(stdout, x); flush(stdout)``, but
+  ## It is roughly equivalent to ``writeln(stdout, x); flushFile(stdout)``, but
   ## available for the JavaScript target too.
+  ##
   ## Unlike other IO operations this is guaranteed to be thread-safe as
-  ## ``echo`` is very often used for debugging convenience.
+  ## ``echo`` is very often used for debugging convenience. If you want to use
+  ## ``echo`` inside a `proc without side effects
+  ## `_ you can use `debugEcho <#debugEcho>`_
+  ## instead.
 
 proc debugEcho*[T](x: varargs[T, `$`]) {.magic: "Echo", noSideEffect, 
                                          tags: [], raises: [].}
-  ## Same as ``echo``, but as a special semantic rule, ``debugEcho`` pretends
-  ## to be free of side effects, so that it can be used for debugging routines
-  ## marked as ``noSideEffect``.
+  ## Same as `echo <#echo>`_, but as a special semantic rule, ``debugEcho``
+  ## pretends to be free of side effects, so that it can be used for debugging
+  ## routines marked as `noSideEffect `_.
 
 template newException*(exceptn: typedesc, message: string): expr =
   ## creates an exception object of type ``exceptn`` and sets its ``msg`` field
@@ -2051,7 +2125,7 @@ template newException*(exceptn: typedesc, message: string): expr =
 when hostOS == "standalone":
   include panicoverride
 
-when not defined(sysFatal):
+when not declared(sysFatal):
   template sysFatal(exceptn: typedesc, message: string) =
     when hostOS == "standalone":
       panic(message)
@@ -2103,11 +2177,17 @@ when not defined(JS): #and not defined(NimrodVM):
       # WARNING: This is very fragile! An array size of 8 does not work on my
       # Linux 64bit system. -- That's because the stack direction is the other
       # way round.
-      when defined(setStackBottom):
+      when declared(setStackBottom):
         var locals {.volatile.}: pointer
         locals = addr(locals)
         setStackBottom(locals)
 
+    proc initStackBottomWith(locals: pointer) {.inline, compilerproc.} =
+      # We need to keep initStackBottom around for now to avoid
+      # bootstrapping problems.
+      when declared(setStackBottom):
+        setStackBottom(locals)
+
     var
       strDesc: TNimType
 
@@ -2376,7 +2456,7 @@ when not defined(JS): #and not defined(NimrodVM):
       hasRaiseAction: bool
       raiseAction: proc (e: ref E_Base): bool {.closure.}
   
-  when defined(initAllocator):
+  when declared(initAllocator):
     initAllocator()
   when hasThreadSupport:
     include "system/syslocks"
@@ -2493,11 +2573,11 @@ when not defined(JS): #and not defined(NimrodVM):
     include "system/assign"
     include "system/repr"
 
-    proc getCurrentException*(): ref E_Base {.compilerRtl, inl.} =
+    proc getCurrentException*(): ref E_Base {.compilerRtl, inl, gcsafe.} =
       ## retrieves the current exception; if there is none, nil is returned.
       result = currException
 
-    proc getCurrentExceptionMsg*(): string {.inline.} =
+    proc getCurrentExceptionMsg*(): string {.inline, gcsafe.} =
       ## retrieves the error message that was attached to the current
       ## exception; if there is none, "" is returned.
       var e = getCurrentException()
@@ -2949,7 +3029,7 @@ proc compiles*(x): bool {.magic: "Compiles", noSideEffect.} =
   ##     echo "'+' for integers is available"
   discard
 
-when defined(initDebugger):
+when declared(initDebugger):
   initDebugger()
 
 when hostOS != "standalone":
@@ -2990,17 +3070,12 @@ proc locals*(): TObject {.magic: "Locals", noSideEffect.} =
   ##   # -> B is 1
   discard
 
-proc deepCopy*[T](x: T): T {.magic: "DeepCopy", noSideEffect.} = discard
-  ## performs a deep copy of `x`. This is also used by the code generator
-  ## for the implementation of ``spawn``.
+when hostOS != "standalone" and not defined(NimrodVM) and not defined(JS):
+  proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
+    ## performs a deep copy of `x`. This is also used by the code generator
+    ## for the implementation of ``spawn``.
+    discard
+
+  include "system/deepcopy"
 
 {.pop.} #{.push warning[GcMem]: off.}
-
-when not defined(booting):
-  type
-    semistatic*[T] = static[T] | T
-    # indicates a param of proc specialized for each static value,
-    # but also accepting run-time values
-
-  template isStatic*(x): expr = compiles(static(x))
-    # checks whether `x` is a value known at compile-time
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index 5111bc3cf5..673d55582c 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -39,7 +39,7 @@ var
   c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar
 
 # constants faked as variables:
-when not defined(SIGINT):
+when not declared(SIGINT):
   when NoFakeVars:
     when defined(windows):
       const
@@ -78,10 +78,23 @@ when defined(macosx):
 else:
   template SIGBUS: expr = SIGSEGV
 
-proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
-  header: "", importc: "longjmp".}
-proc c_setjmp(jmpb: C_JmpBuf): cint {.
-  header: "", importc: "setjmp".}
+when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
+  proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
+    header: "", importc: "siglongjmp".}
+  template c_setjmp(jmpb: C_JmpBuf): cint =
+    proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {.
+      header: "", importc: "sigsetjmp".}
+    c_sigsetjmp(jmpb, 0)
+elif defined(nimRawSetjmp) and not defined(nimStdSetjmp):
+  proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
+    header: "", importc: "_longjmp".}
+  proc c_setjmp(jmpb: C_JmpBuf): cint {.
+    header: "", importc: "_setjmp".}
+else:
+  proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
+    header: "", importc: "longjmp".}
+  proc c_setjmp(jmpb: C_JmpBuf): cint {.
+    header: "", importc: "setjmp".}
 
 proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
   importc: "signal", header: "".}
@@ -106,7 +119,7 @@ proc c_fopen(filename, mode: cstring): C_TextFileStar {.
   importc: "fopen", header: "".}
 proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "".}
 
-proc c_sprintf(buf, frmt: cstring) {.header: "", 
+proc c_sprintf(buf, frmt: cstring): cint {.header: "", 
   importc: "sprintf", varargs, noSideEffect.}
   # we use it only in a way that cannot lead to security issues
 
@@ -132,7 +145,7 @@ proc c_realloc(p: pointer, newsize: int): pointer {.
   importc: "realloc", header: "".}
 
 when hostOS != "standalone":
-  when not defined(errno):
+  when not declared(errno):
     when defined(NimrodVM):
       var vmErrnoWrapper {.importc.}: ptr cint
       template errno: expr = 
diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim
index d9b3aebac1..7672947cdf 100644
--- a/lib/system/arithm.nim
+++ b/lib/system/arithm.nim
@@ -114,63 +114,69 @@ when asmVersion and not defined(gcc) and not defined(llvm_gcc):
   proc addInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     # a in eax, and b in edx
     asm """
-        mov eax, `a`
-        add eax, `b`
+        mov eax, ecx
+        add eax, edx
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc subInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        sub eax, `b`
+        mov eax, ecx
+        sub eax, edx
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc negInt(a: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
+        mov eax, ecx
         neg eax
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc divInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        mov ecx, `b`
+        mov eax, ecx
+        mov ecx, edx
         xor edx, edx
         idiv ecx
         jno  theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc modInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        mov ecx, `b`
+        mov eax, ecx
+        mov ecx, edx
         xor edx, edx
         idiv ecx
         jno theEnd
         call `raiseOverflow`
       theEnd:
         mov eax, edx
+        ret
     """
 
   proc mulInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        mov ecx, `b`
+        mov eax, ecx
+        mov ecx, edx
         xor edx, edx
         imul ecx
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
 elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
@@ -241,26 +247,26 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
     """
 
 # Platform independent versions of the above (slower!)
-when not defined(addInt):
+when not declared(addInt):
   proc addInt(a, b: int): int {.compilerProc, inline.} =
     result = a +% b
     if (result xor a) >= 0 or (result xor b) >= 0:
       return result
     raiseOverflow()
 
-when not defined(subInt):
+when not declared(subInt):
   proc subInt(a, b: int): int {.compilerProc, inline.} =
     result = a -% b
     if (result xor a) >= 0 or (result xor not b) >= 0:
       return result
     raiseOverflow()
 
-when not defined(negInt):
+when not declared(negInt):
   proc negInt(a: int): int {.compilerProc, inline.} =
     if a != low(int): return -a
     raiseOverflow()
 
-when not defined(divInt):
+when not declared(divInt):
   proc divInt(a, b: int): int {.compilerProc, inline.} =
     if b == 0:
       raiseDivByZero()
@@ -268,13 +274,13 @@ when not defined(divInt):
       raiseOverflow()
     return a div b
 
-when not defined(modInt):
+when not declared(modInt):
   proc modInt(a, b: int): int {.compilerProc, inline.} =
     if b == 0:
       raiseDivByZero()
     return a mod b
 
-when not defined(mulInt):
+when not declared(mulInt):
   #
   # This code has been inspired by Python's source code.
   # The native int product x*y is either exactly right or *way* off, being
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index 2ae945fb1c..0e27eb57fe 100644
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -89,14 +89,10 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
     copyMem(dest, src, mt.size) # copy raw bits
 
 proc genericAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
-  GC_disable()
   genericAssignAux(dest, src, mt, false)
-  GC_enable()
 
 proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
-  GC_disable()
   genericAssignAux(dest, src, mt, true)
-  GC_enable()
 
 when false:
   proc debugNimType(t: PNimType) =
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 43b3f0438f..695a5f63e0 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-## Atomic operations for Nimrod.
+# Atomic operations for Nimrod.
 {.push stackTrace:off.}
 
 const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang)
@@ -174,7 +174,7 @@ proc atomicInc*(memLoc: var int, x: int = 1): int =
   
 proc atomicDec*(memLoc: var int, x: int = 1): int =
   when defined(gcc) and hasThreadSupport:
-    when defined(atomic_sub_fetch):
+    when declared(atomic_sub_fetch):
       result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED)
     else:
       result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED)
@@ -201,14 +201,14 @@ when (defined(x86) or defined(amd64)) and (defined(gcc) or defined(llvm_gcc)):
     {.emit: """asm volatile("pause" ::: "memory");""".}
 elif (defined(x86) or defined(amd64)) and defined(vcc):
   proc cpuRelax {.importc: "YieldProcessor", header: "".}
-elif defined(intelc):
+elif defined(icl):
   proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".}
 elif false:
   from os import sleep
 
   proc cpuRelax {.inline.} = os.sleep(1)
 
-when not defined(fence) and hasThreadSupport:
+when not declared(fence) and hasThreadSupport:
   # XXX fixme
   proc fence*() {.inline.} =
     var dummy: bool
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index e5535dbdc8..df46922e4e 100644
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -14,7 +14,7 @@
 ## **Note:** The current implementation of message passing is slow and does
 ## not work with cyclic data structures.
   
-when not defined(NimString): 
+when not declared(NimString):
   {.error: "You must not import this module explicitly".}
 
 type
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
new file mode 100644
index 0000000000..e7eb1cdb42
--- /dev/null
+++ b/lib/system/deepcopy.nim
@@ -0,0 +1,141 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) {.gcsafe.}
+proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  case n.kind
+  of nkSlot:
+    genericDeepCopyAux(cast[pointer](d +% n.offset), 
+                       cast[pointer](s +% n.offset), n.typ)
+  of nkList:
+    for i in 0..n.len-1:
+      genericDeepCopyAux(dest, src, n.sons[i])
+  of nkCase:
+    var dd = selectBranch(dest, n)
+    var m = selectBranch(src, n)
+    # reset if different branches are in use; note different branches also
+    # imply that's not self-assignment (``x = x``)!
+    if m != dd and dd != nil: 
+      genericResetAux(dest, dd)
+    copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
+            n.typ.size)
+    if m != nil:
+      genericDeepCopyAux(dest, src, m)
+  of nkNone: sysAssert(false, "genericDeepCopyAux")
+
+proc copyDeepString(src: NimString): NimString {.inline.} =
+  if src != nil:
+    result = rawNewString(src.space)
+    result.len = src.len
+    c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
+
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  sysAssert(mt != nil, "genericDeepCopyAux 2")
+  case mt.kind
+  of tyString:
+    var x = cast[PPointer](dest)
+    var s2 = cast[PPointer](s)[]
+    if s2 == nil:
+      unsureAsgnRef(x, s2)
+    else:
+      unsureAsgnRef(x, copyDeepString(cast[NimString](s2)))
+  of tySequence:
+    var s2 = cast[PPointer](src)[]
+    var seq = cast[PGenericSeq](s2)
+    var x = cast[PPointer](dest)
+    if s2 == nil:
+      unsureAsgnRef(x, s2)
+      return
+    sysAssert(dest != nil, "genericDeepCopyAux 3")
+    unsureAsgnRef(x, newSeq(mt, seq.len))
+    var dst = cast[TAddress](cast[PPointer](dest)[])
+    for i in 0..seq.len-1:
+      genericDeepCopyAux(
+        cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
+        cast[pointer](cast[TAddress](s2) +% i *% mt.base.size +%
+                     GenericSeqSize),
+        mt.base)
+  of tyObject:
+    # we need to copy m_type field for tyObject, as it could be empty for
+    # sequence reallocations:
+    var pint = cast[ptr PNimType](dest)
+    pint[] = cast[ptr PNimType](src)[]
+    if mt.base != nil:
+      genericDeepCopyAux(dest, src, mt.base)
+    genericDeepCopyAux(dest, src, mt.node)
+  of tyTuple:
+    genericDeepCopyAux(dest, src, mt.node)
+  of tyArray, tyArrayConstr:
+    for i in 0..(mt.size div mt.base.size)-1:
+      genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size),
+                         cast[pointer](s +% i*% mt.base.size), mt.base)
+  of tyRef:
+    if mt.base.deepCopy != nil:
+      let z = mt.base.deepCopy(cast[PPointer](src)[])
+      unsureAsgnRef(cast[PPointer](dest), z)
+    else:
+      # we modify the header of the cell temporarily; instead of the type
+      # field we store a forwarding pointer. XXX This is bad when the cloning
+      # fails due to OOM etc.
+      let s2 = cast[PPointer](src)[]
+      if s2 == nil:
+        unsureAsgnRef(cast[PPointer](dest), s2)
+        return
+      when declared(usrToCell):
+        # unfortunately we only have cycle detection for our native GCs.
+        let x = usrToCell(s2)
+        let forw = cast[int](x.typ)
+        if (forw and 1) == 1:
+          # we stored a forwarding pointer, so let's use that:
+          let z = cast[pointer](forw and not 1)
+          unsureAsgnRef(cast[PPointer](dest), z)
+        else:
+          let realType = x.typ
+          let z = newObj(realType, realType.base.size)
+          
+          unsureAsgnRef(cast[PPointer](dest), z)
+          x.typ = cast[PNimType](cast[int](z) or 1)
+          genericDeepCopyAux(z, s2, realType.base)
+          x.typ = realType
+      else:
+        let realType = mt
+        let z = newObj(realType, realType.base.size)        
+        unsureAsgnRef(cast[PPointer](dest), z)
+        genericDeepCopyAux(z, s2, realType.base)        
+  of tyPtr:
+    # no cycle check here, but also not really required
+    if mt.base.deepCopy != nil:
+      cast[PPointer](dest)[] = mt.base.deepCopy(cast[PPointer](s)[])
+    else:
+      cast[PPointer](dest)[] = cast[PPointer](s)[]
+  else:
+    copyMem(dest, src, mt.size)
+
+proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
+  genericDeepCopyAux(dest, src, mt)
+
+proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
+  # also invoked for 'string'
+  var src = src
+  genericDeepCopy(dest, addr(src), mt)
+
+proc genericDeepCopyOpenArray(dest, src: pointer, len: int,
+                            mt: PNimType) {.compilerproc.} =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  for i in 0..len-1:
+    genericDeepCopy(cast[pointer](d +% i*% mt.base.size),
+                    cast[pointer](s +% i*% mt.base.size), mt.base)
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 63a61183f6..3c5436afb5 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -38,21 +38,11 @@ proc chckRangeF(x, a, b: float): float {.inline, compilerproc, gcsafe.}
 proc chckNil(p: pointer) {.noinline, compilerproc, gcsafe.}
 
 var
-  framePtr {.rtlThreadVar.}: PFrame
-  excHandler {.rtlThreadVar.}: PSafePoint
+  framePtr {.threadvar.}: PFrame
+  excHandler {.threadvar.}: PSafePoint
     # list of exception handlers
     # a global variable for the root of all try blocks
-  currException {.rtlThreadVar.}: ref E_Base
-
-when defined(nimRequiresNimFrame):
-  proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} =
-    s.prev = framePtr
-    framePtr = s
-else:
-  proc pushFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} =
-    # XXX only for backwards compatibility
-    s.prev = framePtr
-    framePtr = s
+  currException {.threadvar.}: ref E_Base
 
 proc popFrame {.compilerRtl, inl.} =
   framePtr = framePtr.prev
@@ -280,6 +270,23 @@ proc getStackTrace(e: ref E_Base): string =
   else:
     result = ""
 
+when defined(nimRequiresNimFrame):
+  proc stackOverflow() {.noinline.} =
+    writeStackTrace()
+    showErrorMessage("Stack overflow\n")
+    quitOrDebug()
+
+  proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} =
+    s.calldepth = if framePtr == nil: 0 else: framePtr.calldepth+1
+    s.prev = framePtr
+    framePtr = s
+    if s.calldepth == 2000: stackOverflow()
+else:
+  proc pushFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} =
+    # XXX only for backwards compatibility
+    s.prev = framePtr
+    framePtr = s
+
 when defined(endb):
   var
     dbgAborting: bool # whether the debugger wants to abort
@@ -300,7 +307,7 @@ when not defined(noSignalHandler):
         action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
       else:
         block platformSpecificSignal:
-          when defined(SIGPIPE):
+          when declared(SIGPIPE):
             if s == SIGPIPE:
               action("SIGPIPE: Pipe closed.\n")
               break platformSpecificSignal
@@ -329,7 +336,7 @@ when not defined(noSignalHandler):
     c_signal(SIGFPE, signalHandler)
     c_signal(SIGILL, signalHandler)
     c_signal(SIGBUS, signalHandler)
-    when defined(SIGPIPE):
+    when declared(SIGPIPE):
       c_signal(SIGPIPE, signalHandler)
 
   registerSignalHandler() # call it in initialization section
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 3b85fe6002..0c1fc7748d 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -30,7 +30,7 @@ const
                                           # cycles instead of the complex
                                           # algorithm
 
-when withRealTime and not defined(getTicks):
+when withRealTime and not declared(getTicks):
   include "system/timers"
 when defined(memProfiler):
   proc nimProfile(requestedSize: int)
@@ -413,7 +413,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
 {.push stackTrace: off, profiler:off.}
 proc gcInvariant*() =
   sysAssert(allocInv(gch.region), "injected")
-  when defined(markForDebug):
+  when declared(markForDebug):
     markForDebug(gch)
 {.pop.}
 
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index 31c99a601c..132da9885b 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -26,7 +26,7 @@ const
                       # this seems to be a good value
   withRealTime = defined(useRealtimeGC)
 
-when withRealTime and not defined(getTicks):
+when withRealTime and not declared(getTicks):
   include "system/timers"
 when defined(memProfiler):
   proc nimProfile(requestedSize: int)
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index 64174e60f1..ef8f50831d 100644
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-when defined(NimString): 
+when declared(NimString): 
   # we are in system module:
   {.pragma: codegenType, compilerproc.}
 else:
@@ -86,6 +86,7 @@ type
     node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum
     finalizer: pointer # the finalizer for the type
     marker: proc (p: pointer, op: int) {.nimcall, gcsafe.} # marker proc for GC
+    deepcopy: proc (p: pointer): pointer {.nimcall, gcsafe.}
   PNimType = ptr TNimType
   
 # node.len may be the ``first`` element of a set
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 52f8873cf4..423f63e2a8 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -515,7 +515,7 @@ proc isFatPointer(ti: PNimType): bool =
 
 proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
 
-proc nimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.compilerproc.} =
+proc nimCopyAux(dest, src: pointer, n: ptr TNimNode) {.compilerproc.} =
   case n.kind
   of nkNone: sysAssert(false, "nimCopyAux")
   of nkSlot:
@@ -566,7 +566,7 @@ proc nimCopy(x: pointer, ti: PNimType): pointer =
   else:
     result = x
 
-proc genericReset(x: Pointer, ti: PNimType): pointer {.compilerproc.} =
+proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} =
   case ti.kind
   of tyPtr, tyRef, tyVar, tyNil:
     if not isFatPointer(ti):
@@ -639,3 +639,87 @@ proc addChar(x: string, c: char) {.compilerproc, asmNoStackFrame.} =
   """
 
 {.pop.}
+
+proc tenToThePowerOf(b: int): BiggestFloat =
+  var b = b
+  var a = 10.0
+  result = 1.0
+  while true:
+    if (b and 1) == 1:
+      result = result * a
+    b = b shr 1
+    if b == 0: break
+    a = a * a
+
+const
+  IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
+
+# XXX use JS's native way here
+proc nimParseBiggestFloat(s: string, number: var BiggestFloat, start = 0): int {.
+                          compilerProc.} =
+  var
+    esign = 1.0
+    sign = 1.0
+    i = start
+    exponent: int
+    flags: int
+  number = 0.0
+  if s[i] == '+': inc(i)
+  elif s[i] == '-':
+    sign = -1.0
+    inc(i)
+  if s[i] == 'N' or s[i] == 'n':
+    if s[i+1] == 'A' or s[i+1] == 'a':
+      if s[i+2] == 'N' or s[i+2] == 'n':
+        if s[i+3] notin IdentChars:
+          number = NaN
+          return i+3 - start
+    return 0
+  if s[i] == 'I' or s[i] == 'i':
+    if s[i+1] == 'N' or s[i+1] == 'n':
+      if s[i+2] == 'F' or s[i+2] == 'f':
+        if s[i+3] notin IdentChars: 
+          number = Inf*sign
+          return i+3 - start
+    return 0
+  while s[i] in {'0'..'9'}:
+    # Read integer part
+    flags = flags or 1
+    number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
+    inc(i)
+    while s[i] == '_': inc(i)
+  # Decimal?
+  if s[i] == '.':
+    var hd = 1.0
+    inc(i)
+    while s[i] in {'0'..'9'}:
+      # Read fractional part
+      flags = flags or 2
+      number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
+      hd = hd * 10.0
+      inc(i)
+      while s[i] == '_': inc(i)
+    number = number / hd # this complicated way preserves precision
+  # Again, read integer and fractional part
+  if flags == 0: return 0
+  # Exponent?
+  if s[i] in {'e', 'E'}:
+    inc(i)
+    if s[i] == '+':
+      inc(i)
+    elif s[i] == '-':
+      esign = -1.0
+      inc(i)
+    if s[i] notin {'0'..'9'}:
+      return 0
+    while s[i] in {'0'..'9'}:
+      exponent = exponent * 10 + ord(s[i]) - ord('0')
+      inc(i)
+      while s[i] == '_': inc(i)
+  # Calculate Exponent
+  let hd = tenToThePowerOf(exponent)
+  if esign > 0.0: number = number * hd
+  else:           number = number / hd
+  # evaluate sign
+  number = number * sign
+  result = i - start
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index a09b6cf934..606743f51a 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -131,6 +131,14 @@ when defined(boehmgc):
       if result == nil: raiseOutOfMem()
     proc deallocShared(p: pointer) = boehmDealloc(p)
 
+    when hasThreadSupport:
+      proc getFreeSharedMem(): int =
+        boehmGetFreeBytes()
+      proc getTotalSharedMem(): int =
+        boehmGetHeapSize()
+      proc getOccupiedSharedMem(): int =
+        getTotalSharedMem() - getFreeSharedMem()
+
     #boehmGCincremental()
 
     proc GC_disable() = boehmGC_disable()
@@ -164,11 +172,11 @@ when defined(boehmgc):
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
   
-  proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
   type
@@ -180,7 +188,7 @@ when defined(boehmgc):
   proc alloc0(r: var TMemRegion, size: int): pointer =
     result = alloc(size)
     zeroMem(result, size)
-  proc dealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p)  
+  proc dealloc(r: var TMemRegion, p: pointer) = boehmDealloc(p)  
   proc deallocOsPages(r: var TMemRegion) {.inline.} = discard
   proc deallocOsPages() {.inline.} = discard
 
@@ -239,11 +247,11 @@ elif defined(nogc) and defined(useMalloc):
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
   
-  proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
   type
@@ -292,11 +300,11 @@ elif defined(nogc):
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
   
-  proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
   var allocator {.rtlThreadVar.}: TMemRegion
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index 487bac0527..8e1bc5f264 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -17,12 +17,12 @@ proc reprFloat(x: float): string {.compilerproc.} = return $x
 
 proc reprPointer(x: pointer): string {.compilerproc.} =
   var buf: array [0..59, char]
-  c_sprintf(buf, "%p", x)
+  discard c_sprintf(buf, "%p", x)
   return $buf
 
 proc `$`(x: uint64): string =
   var buf: array [0..59, char]
-  c_sprintf(buf, "%llu", x)
+  discard c_sprintf(buf, "%llu", x)
   return $buf
 
 proc reprStrAux(result: var string, s: string) =
@@ -121,7 +121,7 @@ proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
 type
   TReprClosure {.final.} = object # we cannot use a global variable here
                                   # as this wouldn't be thread-safe
-    when defined(TCellSet):
+    when declared(TCellSet):
       marked: TCellSet
     recdepth: int       # do not recurse endlessly
     indent: int         # indentation
@@ -130,16 +130,16 @@ when not defined(useNimRtl):
   proc initReprClosure(cl: var TReprClosure) =
     # Important: cellsets does not lock the heap when doing allocations! We
     # have to do it here ...
-    when hasThreadSupport and hasSharedHeap and defined(heapLock):
+    when hasThreadSupport and hasSharedHeap and declared(heapLock):
       AcquireSys(HeapLock)
-    when defined(TCellSet):
+    when declared(TCellSet):
       init(cl.marked)
     cl.recdepth = -1      # default is to display everything!
     cl.indent = 0
 
   proc deinitReprClosure(cl: var TReprClosure) =
-    when defined(TCellSet): deinit(cl.marked)
-    when hasThreadSupport and hasSharedHeap and defined(heapLock): 
+    when declared(TCellSet): deinit(cl.marked)
+    when hasThreadSupport and hasSharedHeap and declared(heapLock): 
       ReleaseSys(HeapLock)
 
   proc reprBreak(result: var string, cl: TReprClosure) =
@@ -201,7 +201,7 @@ when not defined(useNimRtl):
   proc reprRef(result: var string, p: pointer, typ: PNimType,
                cl: var TReprClosure) =
     # we know that p is not nil here:
-    when defined(TCellSet):
+    when declared(TCellSet):
       when defined(boehmGC) or defined(nogc):
         var cell = cast[PCell](p)
       else:
@@ -221,7 +221,7 @@ when not defined(useNimRtl):
     dec(cl.recdepth)
     case typ.kind
     of tySet: reprSetAux(result, p, typ)
-    of tyArray: reprArray(result, p, typ, cl)
+    of tyArray, tyArrayConstr: reprArray(result, p, typ, cl)
     of tyTuple: reprRecord(result, p, typ, cl)
     of tyObject: 
       var t = cast[ptr PNimType](p)[]
@@ -275,7 +275,7 @@ when not defined(useNimRtl):
       cl: TReprClosure
     initReprClosure(cl)
     result = ""
-    if typ.kind in {tyObject, tyTuple, tyArray, tySet}:
+    if typ.kind in {tyObject, tyTuple, tyArray, tyArrayConstr, tySet}:
       reprAux(result, p, typ, cl)
     else:
       var p = p
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index 95cdba65d1..5161104a9f 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -9,7 +9,7 @@
 
 ## Implements Nimrod's 'spawn'.
 
-when not defined(NimString): 
+when not declared(NimString): 
   {.error: "You must not import this module explicitly".}
 
 {.push stackTrace:off.}
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 4244bae4cb..bc79bb254d 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -32,7 +32,7 @@ proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
   return a.len == b.len and
     c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32
 
-when defined(allocAtomic):
+when declared(allocAtomic):
   template allocStr(size: expr): expr =
     cast[NimString](allocAtomic(size))
 else:
@@ -85,7 +85,7 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
   if src != nil:
     var s = src.space
     if s < 8: s = 7
-    when defined(newObjRC1):
+    when declared(newObjRC1):
       result = cast[NimString](newObjRC1(addr(strDesc), sizeof(TGenericSeq) +
                                s+1))
     else:
@@ -250,10 +250,115 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
   for j in 0..i div 2 - 1:
     swap(result[j], result[i-j-1])
 
-proc nimFloatToStr(x: float): string {.compilerproc.} =
-  var buf: array [0..59, char]
-  c_sprintf(buf, "%#.16e", x)
-  return $buf
+proc nimFloatToStr(f: float): string {.compilerproc.} =
+  var buf: array [0..64, char]
+  var n: int = c_sprintf(buf, "%.16g", f)
+  var hasDot = false
+  for i in 0..n-1:
+    if buf[i] == ',':
+      buf[i] = '.'
+      hasDot = true
+    elif buf[i] in {'a'..'z', 'A'..'Z', '.'}: 
+      hasDot = true
+  if not hasDot:
+    buf[n] = '.'
+    buf[n+1] = '0'
+    buf[n+2] = '\0'
+  result = $buf
+
+proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc,
+  header: "", noSideEffect.}
+
+var decimalPoint: char
+
+proc getDecimalPoint(): char =
+  result = decimalPoint
+  if result == '\0':
+    if strtod("0,5", nil) == 0.5: result = ','
+    else: result = '.'
+    # yes this is threadsafe in practice, spare me:
+    decimalPoint = result
+
+const
+  IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
+
+proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
+                          start = 0): int {.compilerProc.} =
+  # This routine leverages `strtod()` for the non-trivial task of
+  # parsing floating point numbers correctly. Because `strtod()` is
+  # locale-dependent with respect to the radix character, we create
+  # a copy where the decimal point is replaced with the locale's
+  # radix character.
+  var
+    i = start
+    sign = 1.0
+    t: array[128, char]
+    ti = 0
+    hasdigits = false
+
+  template addToBuf(c) =
+    if ti < t.high:
+      t[ti] = c; inc(ti)
+  
+  # Sign?
+  if s[i] == '+' or s[i] == '-':
+    if s[i] == '-':
+      sign = -1.0
+    t[ti] = s[i]
+    inc(i); inc(ti)
+
+  # NaN?
+  if s[i] == 'N' or s[i] == 'n':
+    if s[i+1] == 'A' or s[i+1] == 'a':
+      if s[i+2] == 'N' or s[i+2] == 'n':
+        if s[i+3] notin IdentChars:
+          number = NaN
+          return i+3 - start
+    return 0
+
+  # Inf?
+  if s[i] == 'I' or s[i] == 'i':
+    if s[i+1] == 'N' or s[i+1] == 'n':
+      if s[i+2] == 'F' or s[i+2] == 'f':
+        if s[i+3] notin IdentChars: 
+          number = Inf*sign
+          return i+3 - start
+    return 0
+
+  # Integer part?
+  while s[i] in {'0'..'9'}:
+    hasdigits = true
+    addToBuf(s[i])
+    inc(i);
+    while s[i] == '_': inc(i)
+
+  # Fractional part?
+  if s[i] == '.':
+    addToBuf(getDecimalPoint())
+    inc(i)
+    while s[i] in {'0'..'9'}:
+      hasdigits = true
+      addToBuf(s[i])
+      inc(i)
+      while s[i] == '_': inc(i)
+  if not hasdigits:
+    return 0
+
+  # Exponent?
+  if s[i] in {'e', 'E'}:
+    addToBuf(s[i])
+    inc(i)
+    if s[i] in {'+', '-'}:
+      addToBuf(s[i])
+      inc(i)
+    if s[i] notin {'0'..'9'}:
+      return 0
+    while s[i] in {'0'..'9'}:
+      addToBuf(s[i])
+      inc(i)
+      while s[i] == '_': inc(i)
+  number = strtod(t, nil)
+  result = i - start
 
 proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
   result = newString(sizeof(x)*4)
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index d3b3aa457e..c30c57fb9e 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -1,17 +1,17 @@
 #
 #
-#            Nimrod's Runtime Library
+#            Nim's Runtime Library
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## Thread support for Nimrod. **Note**: This is part of the system module.
+## Thread support for Nim. **Note**: This is part of the system module.
 ## Do not import it directly. To activate thread support you need to compile
 ## with the ``--threads:on`` command line switch.
 ##
-## Nimrod's memory model for threads is quite different from other common 
+## Nim's memory model for threads is quite different from other common 
 ## programming languages (C, Pascal): Each thread has its own
 ## (garbage collected) heap and sharing of memory is restricted. This helps
 ## to prevent race conditions and improves efficiency. See `the manual for
@@ -19,7 +19,7 @@
 ##
 ## Example:
 ##
-## .. code-block:: nimrod
+## .. code-block:: Nim
 ##
 ##  import locks
 ##
@@ -39,7 +39,7 @@
 ##    createThread(thr[i], threadFunc, (i*10, i*10+5))
 ##  joinThreads(thr)
   
-when not defined(NimString): 
+when not declared(NimString): 
   {.error: "You must not import this module explicitly".}
 
 const
@@ -190,7 +190,7 @@ var globalsSlot = threadVarAlloc()
 
 when emulatedThreadVars:
   proc GetThreadLocalVars(): pointer {.compilerRtl, inl.} =
-    result = addr(cast[PGcThread](ThreadVarGetValue(globalsSlot)).tls)
+    result = addr(cast[PGcThread](threadVarGetValue(globalsSlot)).tls)
 
 when useStackMaskHack:
   proc maskStackPointer(offset: int): pointer {.compilerRtl, inl.} =
@@ -210,7 +210,7 @@ when not defined(useNimRtl):
     initGC()
     
   when emulatedThreadVars:
-    if NimThreadVarsSize() > sizeof(TThreadLocalStorage):
+    if nimThreadVarsSize() > sizeof(TThreadLocalStorage):
       echo "too large thread local storage size requested"
       quit 1
   
@@ -245,14 +245,14 @@ when not defined(useNimRtl):
     # the GC can examine the stacks?
     proc stopTheWord() = discard
     
-# We jump through some hops here to ensure that Nimrod thread procs can have
-# the Nimrod calling convention. This is needed because thread procs are 
+# We jump through some hops here to ensure that Nim thread procs can have
+# the Nim calling convention. This is needed because thread procs are 
 # ``stdcall`` on Windows and ``noconv`` on UNIX. Alternative would be to just
 # use ``stdcall`` since it is mapped to ``noconv`` on UNIX anyway.
 
 type
   TThread* {.pure, final.}[TArg] =
-      object of TGcThread ## Nimrod thread. A thread is a heavy object (~14K)
+      object of TGcThread ## Nim thread. A thread is a heavy object (~14K)
                           ## that **must not** be part of a message! Use
                           ## a ``TThreadId`` for that.
     when TArg is void:
@@ -267,7 +267,7 @@ when not defined(boehmgc) and not hasSharedHeap:
   proc deallocOsPages()
 
 template threadProcWrapperBody(closure: expr) {.immediate.} =
-  when defined(globalsSlot): ThreadVarSetValue(globalsSlot, closure)
+  when declared(globalsSlot): threadVarSetValue(globalsSlot, closure)
   var t = cast[ptr TThread[TArg]](closure)
   when useStackMaskHack:
     var tls: TThreadLocalStorage
@@ -275,13 +275,13 @@ template threadProcWrapperBody(closure: expr) {.immediate.} =
     # init the GC for this thread:
     setStackBottom(addr(t))
     initGC()
-  when defined(registerThread):
+  when declared(registerThread):
     t.stackBottom = addr(t)
     registerThread(t)
   when TArg is void: t.dataFn()
   else: t.dataFn(t.data)
-  when defined(registerThread): unregisterThread(t)
-  when defined(deallocOsPages): deallocOsPages()
+  when declared(registerThread): unregisterThread(t)
+  when declared(deallocOsPages): deallocOsPages()
   # Since an unhandled exception terminates the whole process (!), there is
   # no need for a ``try finally`` here, nor would it be correct: The current
   # exception is tried to be re-raised by the code-gen after the ``finally``!
@@ -305,22 +305,26 @@ proc running*[TArg](t: TThread[TArg]): bool {.inline.} =
   ## returns true if `t` is running.
   result = t.dataFn != nil
 
-proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = 
-  ## waits for the thread `t` to finish.
-  when hostOS == "windows":
+when hostOS == "windows":
+  proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = 
+    ## waits for the thread `t` to finish.
     discard waitForSingleObject(t.sys, -1'i32)
-  else:
-    discard pthread_join(t.sys, nil)
 
-proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = 
-  ## waits for every thread in `t` to finish.
-  when hostOS == "windows":
+  proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = 
+    ## waits for every thread in `t` to finish.
     var a: array[0..255, TSysThread]
     sysAssert a.len >= t.len, "a.len >= t.len"
     for i in 0..t.high: a[i] = t[i].sys
-    discard waitForMultipleObjects(t.len.int32, 
+    discard waitForMultipleObjects(t.len.int32,
                                    cast[ptr TSysThread](addr(a)), 1, -1)
-  else:
+
+else:
+  proc joinThread*[TArg](t: TThread[TArg]) {.inline.} =
+    ## waits for the thread `t` to finish.
+    discard pthread_join(t.sys, nil)
+
+  proc joinThreads*[TArg](t: varargs[TThread[TArg]]) =
+    ## waits for every thread in `t` to finish.
     for i in 0..t.high: joinThread(t[i])
 
 when false:
@@ -332,25 +336,35 @@ when false:
       discard TerminateThread(t.sys, 1'i32)
     else:
       discard pthread_cancel(t.sys)
-    when defined(registerThread): unregisterThread(addr(t))
+    when declared(registerThread): unregisterThread(addr(t))
     t.dataFn = nil
 
-proc createThread*[TArg](t: var TThread[TArg], 
-                         tp: proc (arg: TArg) {.thread.}, 
-                         param: TArg) =
-  ## creates a new thread `t` and starts its execution. Entry point is the
-  ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
-  ## don't need to pass any data to the thread.
-  when TArg isnot void: t.data = param
-  t.dataFn = tp
-  when hasSharedHeap: t.stackSize = ThreadStackSize
-  when hostOS == "windows":
+when hostOS == "windows":
+  proc createThread*[TArg](t: var TThread[TArg],
+                           tp: proc (arg: TArg) {.thread.}, 
+                           param: TArg) =
+    ## creates a new thread `t` and starts its execution. Entry point is the
+    ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
+    ## don't need to pass any data to the thread.
+    when TArg isnot void: t.data = param
+    t.dataFn = tp
+    when hasSharedHeap: t.stackSize = ThreadStackSize
     var dummyThreadId: int32
     t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg],
                          addr(t), 0'i32, dummyThreadId)
     if t.sys <= 0:
       raise newException(EResourceExhausted, "cannot create thread")
-  else:
+
+else:
+  proc createThread*[TArg](t: var TThread[TArg], 
+                           tp: proc (arg: TArg) {.thread.}, 
+                           param: TArg) =
+    ## creates a new thread `t` and starts its execution. Entry point is the
+    ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
+    ## don't need to pass any data to the thread.
+    when TArg isnot void: t.data = param
+    t.dataFn = tp
+    when hasSharedHeap: t.stackSize = ThreadStackSize
     var a {.noinit.}: Tpthread_attr
     pthread_attr_init(a)
     pthread_attr_setstacksize(a, ThreadStackSize)
@@ -364,7 +378,7 @@ proc threadId*[TArg](t: var TThread[TArg]): TThreadId[TArg] {.inline.} =
 proc myThreadId*[TArg](): TThreadId[TArg] =
   ## returns the thread ID of the thread that calls this proc. This is unsafe
   ## because the type ``TArg`` is not checked for consistency!
-  result = cast[TThreadId[TArg]](ThreadVarGetValue(globalsSlot))
+  result = cast[TThreadId[TArg]](threadVarGetValue(globalsSlot))
 
 when false:
   proc mainThreadId*[TArg](): TThreadId[TArg] =
diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim
index e2a5d87e90..cd64ff410e 100644
--- a/lib/system/widestrs.nim
+++ b/lib/system/widestrs.nim
@@ -7,10 +7,10 @@
 #    distribution, for details about the copyright.
 #
 
-## Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system
-## module! Do not import it directly!
+# Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system
+# module! Do not import it directly!
 
-when not defined(NimString):
+when not declared(NimString):
   {.error: "You must not import this module explicitly".}
 
 type
@@ -103,7 +103,7 @@ proc newWideCString*(source: cstring, L: int): WideCString =
 proc newWideCString*(s: cstring): WideCString =
   if s.isNil: return nil
 
-  when not defined(c_strlen):
+  when not declared(c_strlen):
     proc c_strlen(a: cstring): int {.
       header: "", noSideEffect, importc: "strlen".}
 
diff --git a/lib/windows/ole2.nim b/lib/windows/ole2.nim
deleted file mode 100644
index ec0ab8f5da..0000000000
--- a/lib/windows/ole2.nim
+++ /dev/null
@@ -1,208 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2006 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-import 
-  windows
-
-const 
-  GUID_NULL*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000000])
-  IID_IUnknown*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IClassFactory*: TGUID = (D1: 0x00000001, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IMarshal*: TGUID = (D1: 0x00000003, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IMalloc*: TGUID = (D1: 0x00000002, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IStdMarshalInfo*: TGUID = (D1: 0x00000018, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IExternalConnection*: TGUID = (D1: 0x00000019, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IEnumUnknown*: TGUID = (D1: 0x00000100, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IBindCtx*: TGUID = (D1: 0x0000000E, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumMoniker*: TGUID = (D1: 0x00000102, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRunnableObject*: TGUID = (D1: 0x00000126, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRunningObjectTable*: TGUID = (D1: 0x00000010, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IPersist*: TGUID = (D1: 0x0000010C, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IPersistStream*: TGUID = (D1: 0x00000109, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IMoniker*: TGUID = (D1: 0x0000000F, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumString*: TGUID = (D1: 0x00000101, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IStream*: TGUID = (D1: 0x0000000C, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumStatStg*: TGUID = (D1: 0x0000000D, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IStorage*: TGUID = (D1: 0x0000000B, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IPersistFile*: TGUID = (D1: 0x0000010B, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IPersistStorage*: TGUID = (D1: 0x0000010A, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ILockBytes*: TGUID = (D1: 0x0000000A, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumFormatEtc*: TGUID = (D1: 0x00000103, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumStatData*: TGUID = (D1: 0x00000105, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRootStorage*: TGUID = (D1: 0x00000012, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IAdviseSink*: TGUID = (D1: 0x0000010F, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IAdviseSink2*: TGUID = (D1: 0x00000125, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDataObject*: TGUID = (D1: 0x0000010E, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDataAdviseHolder*: TGUID = (D1: 0x00000110, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IMessageFilter*: TGUID = (D1: 0x00000016, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRpcChannelBuffer*: TGUID = (D1: 0xD5F56B60, D2: 0x0000593B, 
-    D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
-  IID_IRpcProxyBuffer*: TGUID = (D1: 0xD5F56A34, D2: 0x0000593B, D3: 0x0000101A, D4: [
-      0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D, 
-      0x000000BF, 0x0000007A])
-  IID_IRpcStubBuffer*: TGUID = (D1: 0xD5F56AFC, D2: 0x0000593B, D3: 0x0000101A, D4: [
-      0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D, 
-      0x000000BF, 0x0000007A])
-  IID_IPSFactoryBuffer*: TGUID = (D1: 0xD5F569D0, D2: 0x0000593B, 
-    D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
-  IID_ICreateTypeInfo*: TGUID = (D1: 0x00020405, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ICreateTypeLib*: TGUID = (D1: 0x00020406, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDispatch*: TGUID = (D1: 0x00020400, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumVariant*: TGUID = (D1: 0x00020404, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ITypeComp*: TGUID = (D1: 0x00020403, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ITypeInfo*: TGUID = (D1: 0x00020401, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ITypeLib*: TGUID = (D1: 0x00020402, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IErrorInfo*: TGUID = (D1: 0x1CF2B120, D2: 0x0000547D, D3: 0x0000101B, D4: [
-      0x0000008E, 0x00000065, 0x00000008, 0x00000000, 0x0000002B, 0x0000002B, 
-      0x000000D1, 0x00000019])
-  IID_ICreateErrorInfo*: TGUID = (D1: 0x22F03340, D2: 0x0000547D, 
-    D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
-  IID_ISupportErrorInfo*: TGUID = (D1: 0xDF0B3D60, D2: 0x0000548F, 
-    D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
-  IID_IOleAdviseHolder*: TGUID = (D1: 0x00000111, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleCache*: TGUID = (D1: 0x0000011E, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleCache2*: TGUID = (D1: 0x00000128, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleCacheControl*: TGUID = (D1: 0x00000129, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IParseDisplayName*: TGUID = (D1: 0x0000011A, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleContainer*: TGUID = (D1: 0x0000011B, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleClientSite*: TGUID = (D1: 0x00000118, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleObject*: TGUID = (D1: 0x00000112, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleWindow*: TGUID = (D1: 0x00000114, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleLink*: TGUID = (D1: 0x0000011D, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleItemContainer*: TGUID = (D1: 0x0000011C, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceUIWindow*: TGUID = (D1: 0x00000115, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceActiveObject*: TGUID = (D1: 0x00000117, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceFrame*: TGUID = (D1: 0x00000116, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceObject*: TGUID = (D1: 0x00000113, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceSite*: TGUID = (D1: 0x00000119, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IViewObject*: TGUID = (D1: 0x0000010D, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IViewObject2*: TGUID = (D1: 0x00000127, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDropSource*: TGUID = (D1: 0x00000121, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDropTarget*: TGUID = (D1: 0x00000122, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumOleVerb*: TGUID = (D1: 0x00000104, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index dcae6ffaf2..09696b67fa 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -664,6 +664,7 @@ const
   WSAEDISCON* = 10101
   WSAENETRESET* = 10052
   WSAETIMEDOUT* = 10060
+  ERROR_NETNAME_DELETED* = 64
 
 proc CreateIoCompletionPort*(FileHandle: THANDLE, ExistingCompletionPort: THANDLE,
                              CompletionKey: DWORD,
diff --git a/lib/wrappers/postgres.nim b/lib/wrappers/postgres.nim
index d99e5651c5..ce78d34352 100644
--- a/lib/wrappers/postgres.nim
+++ b/lib/wrappers/postgres.nim
@@ -213,6 +213,8 @@ proc PQexecParams*(conn: PPGconn, command: cstring, nParams: int32,
                    paramTypes: POid, paramValues: cstringArray, 
                    paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
     cdecl, dynlib: dllName, importc: "PQexecParams".}
+proc PQprepare*(conn: PPGconn, stmtName, query: cstring, nParams: int32,
+    paramTypes: POid): PPGresult{.cdecl, dynlib: dllName, importc: "PQprepare".}
 proc PQexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32, 
                      paramValues: cstringArray, 
                      paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
diff --git a/lib/wrappers/sdl/sdl_ttf.nim b/lib/wrappers/sdl/sdl_ttf.nim
index f501e31d83..45247df4dc 100644
--- a/lib/wrappers/sdl/sdl_ttf.nim
+++ b/lib/wrappers/sdl/sdl_ttf.nim
@@ -333,11 +333,5 @@ proc VERSION*(X: var sdl.Tversion) =
   X.patch = PATCHLEVEL
 
 
-when not (defined(Workaround_RenderText_Solid)): 
-  proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{.
-      cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.}
-else: 
-  proc RenderText_Solid(font: PFont, text: cstring, fg: TColor): PSurface = 
-    var Black: TColor         # initialized to zero
-    result = RenderText_Shaded(font, text, fg, Black)
-
+proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{.
+    cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.}
diff --git a/lib/wrappers/zmq.nim b/lib/wrappers/zmq.nim
deleted file mode 100644
index 9826ab8130..0000000000
--- a/lib/wrappers/zmq.nim
+++ /dev/null
@@ -1,322 +0,0 @@
-# Nimrod wrapper of 0mq
-# Generated by c2nim with modifications and enhancement from Andreas Rumpf
-# Original licence follows:
-
-#
-#    Copyright (c) 2007-2011 iMatix Corporation
-#    Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
-#
-#    This file is part of 0MQ.
-#
-#    0MQ is free software; you can redistribute it and/or modify it under
-#    the terms of the GNU Lesser General Public License as published by
-#    the Free Software Foundation; either version 3 of the License, or
-#    (at your option) any later version.
-#
-#    0MQ is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU Lesser General Public License for more details.
-#
-#    You should have received a copy of the GNU Lesser General Public License
-#    along with this program.  If not, see .
-#
-
-# Generated from zmq version 2.1.5
-
-## Nimrod 0mq wrapper. This file contains the low level C wrappers as well as
-## some higher level constructs. The higher level constructs are easily
-## recognizable because they are the only ones that have documentation.
-##
-## Example of a client:
-## 
-## .. code-block:: nimrod
-##   import zmq
-##   
-##   var connection = zmq.open("tcp://localhost:5555", server=false)
-##   echo("Connecting...")
-##   for i in 0..10:
-##     echo("Sending hello...", i)
-##     send(connection, "Hello")
-##     var reply = receive(connection)
-##     echo("Received ...", reply)
-##   close(connection)
-##
-## Example of a server:
-##
-## .. code-block:: nimrod
-##   
-##   import zmq
-##   var connection = zmq.open("tcp://*:5555", server=true)
-##   while True:
-##     var request = receive(connection)
-##     echo("Received: ", request)
-##     send(connection, "World")
-##   close(connection)
-
-{.deadCodeElim: on.}
-when defined(windows): 
-  const 
-    zmqdll* = "zmq.dll"
-elif defined(macosx): 
-  const 
-    zmqdll* = "libzmq.dylib"
-else:
-  const 
-    zmqdll* = "libzmq.so"
-
-# A number random enough not to collide with different errno ranges on      
-# different OSes. The assumption is that error_t is at least 32-bit type.  
-const 
-  HAUSNUMERO* = 156384712
-  # On Windows platform some of the standard POSIX errnos are not defined.    
-  ENOTSUP* = (HAUSNUMERO + 1)
-  EPROTONOSUPPORT* = (HAUSNUMERO + 2)
-  ENOBUFS* = (HAUSNUMERO + 3)
-  ENETDOWN* = (HAUSNUMERO + 4)
-  EADDRINUSE* = (HAUSNUMERO + 5)
-  EADDRNOTAVAIL* = (HAUSNUMERO + 6)
-  ECONNREFUSED* = (HAUSNUMERO + 7)
-  EINPROGRESS* = (HAUSNUMERO + 8)
-  # Native 0MQ error codes.  
-  EFSM* = (HAUSNUMERO + 51)
-  ENOCOMPATPROTO* = (HAUSNUMERO + 52)
-  ETERM* = (HAUSNUMERO + 53)
-  EMTHREAD* = (HAUSNUMERO + 54)
-  #  Maximal size of "Very Small Message". VSMs are passed by value            
-  #  to avoid excessive memory allocation/deallocation.                        
-  #  If VMSs larger than 255 bytes are required, type of 'vsm_size'            
-  #  field in msg_t structure should be modified accordingly.
-  MAX_VSM_SIZE* = 30
-
-  POLLIN* = 1
-  POLLOUT* = 2
-  POLLERR* = 4
-
-  STREAMER* = 1
-  FORWARDER* = 2
-  QUEUE* = 3
-
-  PAIR* = 0
-  PUB* = 1
-  SUB* = 2
-  REQ* = 3
-  REP* = 4
-  DEALER* = 5
-  ROUTER* = 6
-  PULL* = 7
-  PUSH* = 8
-  XPUB* = 9
-  XSUB* = 10
-  XREQ* = DEALER      #  Old alias, remove in 3.x               
-  XREP* = ROUTER      #  Old alias, remove in 3.x               
-  UPSTREAM* = PULL    #  Old alias, remove in 3.x               
-  DOWNSTREAM* = PUSH  #  Old alias, remove in 3.x        
-
-type
-  #  Message types. These integers may be stored in 'content' member of the    
-  #  message instead of regular pointer to the data. 
-  TMsgTypes* = enum
-    DELIMITER = 31,
-    VSM = 32
-  #  Message flags. MSG_SHARED is strictly speaking not a message flag     
-  #  (it has no equivalent in the wire format), however, making  it a flag     
-  #  allows us to pack the stucture tighter and thus improve performance.   
-  TMsgFlags* = enum 
-    MSG_MORE = 1,
-    MSG_SHARED = 128,
-    MSG_MASK = 129         # Merges all the flags 
-  #  A message. Note that 'content' is not a pointer to the raw data.          
-  #  Rather it is pointer to zmq::msg_content_t structure                      
-  #  (see src/msg_content.hpp for its definition).    
-  TMsg*{.pure, final.} = object 
-    content*: pointer
-    flags*: char
-    vsm_size*: char
-    vsm_data*: array[0..MAX_VSM_SIZE - 1, char]
-
-  TFreeFn = proc (data, hint: pointer) {.noconv.}
-
-  TContext {.final, pure.} = object
-  PContext* = ptr TContext
-  
-  # Socket Types
-  TSocket {.final, pure.} = object
-  PSocket* = ptr TSocket       
-
-  #  Socket options.                                                           
-  TSockOptions* = enum
-    HWM = 1,
-    SWAP = 3,
-    AFFINITY = 4,
-    IDENTITY = 5,
-    SUBSCRIBE = 6,
-    UNSUBSCRIBE = 7,
-    RATE = 8,
-    RECOVERY_IVL = 9,
-    MCAST_LOOP = 10,
-    SNDBUF = 11,
-    RCVBUF = 12,
-    RCVMORE = 13,
-    FD = 14,
-    EVENTS = 15,
-    theTYPE = 16,
-    LINGER = 17,
-    RECONNECT_IVL = 18,
-    BACKLOG = 19,
-    RECOVERY_IVL_MSEC = 20, #  opt. recovery time, reconcile in 3.x   
-    RECONNECT_IVL_MAX = 21
-
-  #  Send/recv options.                                                        
-  TSendRecvOptions* = enum
-    NOBLOCK, SNDMORE
-  
-  TPollItem*{.pure, final.} = object 
-    socket*: PSocket
-    fd*: cint
-    events*: cshort
-    revents*: cshort
-  
-#  Run-time API version detection                                            
-
-proc version*(major: var cint, minor: var cint, patch: var cint){.cdecl, 
-    importc: "zmq_version", dynlib: zmqdll.}
-#****************************************************************************
-#  0MQ errors.                                                               
-#****************************************************************************
-
-#  This function retrieves the errno as it is known to 0MQ library. The goal 
-#  of this function is to make the code 100% portable, including where 0MQ   
-#  compiled with certain CRT library (on Windows) is linked to an            
-#  application that uses different CRT library.                              
-
-proc errno*(): cint{.cdecl, importc: "zmq_errno", dynlib: zmqdll.}
-#  Resolves system errors and 0MQ errors to human-readable string.
-
-proc strerror*(errnum: cint): cstring {.cdecl, importc: "zmq_strerror", 
-    dynlib: zmqdll.}
-#****************************************************************************
-#  0MQ message definition.                                                   
-#****************************************************************************
-
-proc msg_init*(msg: var TMsg): cint{.cdecl, importc: "zmq_msg_init", 
-    dynlib: zmqdll.}
-proc msg_init*(msg: var TMsg, size: int): cint{.cdecl, 
-    importc: "zmq_msg_init_size", dynlib: zmqdll.}
-proc msg_init*(msg: var TMsg, data: cstring, size: int, 
-               ffn: TFreeFn, hint: pointer): cint{.cdecl, 
-    importc: "zmq_msg_init_data", dynlib: zmqdll.}
-proc msg_close*(msg: var TMsg): cint {.cdecl, importc: "zmq_msg_close", 
-    dynlib: zmqdll.}
-proc msg_move*(dest, src: var TMsg): cint{.cdecl, 
-    importc: "zmq_msg_move", dynlib: zmqdll.}
-proc msg_copy*(dest, src: var TMsg): cint{.cdecl, 
-    importc: "zmq_msg_copy", dynlib: zmqdll.}
-proc msg_data*(msg: var TMsg): cstring {.cdecl, importc: "zmq_msg_data", 
-    dynlib: zmqdll.}
-proc msg_size*(msg: var TMsg): int {.cdecl, importc: "zmq_msg_size", 
-    dynlib: zmqdll.}
-    
-#****************************************************************************
-#  0MQ infrastructure (a.k.a. context) initialisation & termination.         
-#****************************************************************************
-
-proc init*(io_threads: cint): PContext {.cdecl, importc: "zmq_init", 
-    dynlib: zmqdll.}
-proc term*(context: PContext): cint {.cdecl, importc: "zmq_term", 
-                                        dynlib: zmqdll.}
-#****************************************************************************
-#  0MQ socket definition.                                                    
-#****************************************************************************                                                         
-
-proc socket*(context: PContext, theType: cint): PSocket {.cdecl, 
-    importc: "zmq_socket", dynlib: zmqdll.}
-proc close*(s: PSocket): cint{.cdecl, importc: "zmq_close", dynlib: zmqdll.}
-proc setsockopt*(s: PSocket, option: cint, optval: pointer, 
-                     optvallen: int): cint {.cdecl, importc: "zmq_setsockopt", 
-    dynlib: zmqdll.}
-proc getsockopt*(s: PSocket, option: cint, optval: pointer, 
-                 optvallen: ptr int): cint{.cdecl, 
-    importc: "zmq_getsockopt", dynlib: zmqdll.}
-proc bindAddr*(s: PSocket, address: cstring): cint{.cdecl, importc: "zmq_bind", 
-    dynlib: zmqdll.}
-proc connect*(s: PSocket, address: cstring): cint{.cdecl, 
-    importc: "zmq_connect", dynlib: zmqdll.}
-proc send*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, 
-    importc: "zmq_send", dynlib: zmqdll.}
-proc recv*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, 
-    importc: "zmq_recv", dynlib: zmqdll.}
-#****************************************************************************
-#  I/O multiplexing.                                                         
-#****************************************************************************
-
-proc poll*(items: ptr TPollItem, nitems: cint, timeout: int): cint{.
-    cdecl, importc: "zmq_poll", dynlib: zmqdll.}
-    
-#****************************************************************************
-#  Built-in devices                                                          
-#****************************************************************************
-
-proc device*(device: cint, insocket, outsocket: PSocket): cint{.
-    cdecl, importc: "zmq_device", dynlib: zmqdll.}
-    
-type
-  EZmq* = object of ESynch ## exception that is raised if something fails
-  TConnection* {.pure, final.} = object ## a connection
-    c*: PContext  ## the embedded context
-    s*: PSocket   ## the embedded socket
-  
-  TConnectionMode* = enum ## connection mode
-    conPAIR = 0,
-    conPUB = 1,
-    conSUB = 2,
-    conREQ = 3,
-    conREP = 4,
-    conDEALER = 5,
-    conROUTER = 6,
-    conPULL = 7,
-    conPUSH = 8,
-    conXPUB = 9,
-    conXSUB = 10
-  
-proc zmqError*() {.noinline, noreturn.} =
-  ## raises EZmq with error message from `zmq.strerror`.
-  var e: ref EZmq
-  new(e)
-  e.msg = $strerror(errno())
-  raise e
-  
-proc open*(address: string, server: bool, mode: TConnectionMode = conDEALER,
-           numthreads = 4): TConnection =
-  ## opens a new connection. If `server` is true, it uses `bindAddr` for the
-  ## underlying socket, otherwise it opens the socket with `connect`.
-  result.c = init(cint(numthreads))
-  if result.c == nil: zmqError()
-  result.s = socket(result.c, cint(ord(mode)))
-  if result.s == nil: zmqError()
-  if server:
-    if bindAddr(result.s, address) != 0'i32: zmqError()
-  else:
-    if connect(result.s, address) != 0'i32: zmqError()
-  
-proc close*(c: TConnection) =
-  ## closes the connection.
-  if close(c.s) != 0'i32: zmqError()
-  if term(c.c) != 0'i32: zmqError()
-  
-proc send*(c: TConnection, msg: string) =
-  ## sends a message over the connection.
-  var m: TMsg
-  if msg_init(m, msg.len) != 0'i32: zmqError()
-  copyMem(msg_data(m), cstring(msg), msg.len)
-  if send(c.s, m, 0'i32) != 0'i32: zmqError()
-  discard msg_close(m)
-  
-proc receive*(c: TConnection): string =
-  ## receives a message from a connection.
-  var m: TMsg
-  if msg_init(m) != 0'i32: zmqError()
-  if recv(c.s, m, 0'i32) != 0'i32: zmqError()
-  result = newString(msg_size(m))
-  copyMem(addr(result[0]), msg_data(m), result.len)
-  discard msg_close(m)
diff --git a/readme.txt b/readme.txt
index 3f6aef05cd..f9e5054fe7 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,60 +1,12 @@
-# Nimrod Compiler
-This repo contains the Nimrod compiler, Nimrod's stdlib, tools and 
+This package contains the Nimrod compiler, Nimrod's stdlib, tools and 
 documentation.
 
-## Compiling
-Compiling the Nimrod compiler is quite straightforward. Because
-the Nimrod compiler itself is written in the Nimrod programming language
-the C source of an older version of the compiler are needed to bootstrap the
-latest version. The C sources are available in a separate repo [here](http://github.com/nimrod-code/csources).
+Nimrod is a compiled, garbage-collected systems programming language which has
+an excellent productivity/performance ratio. Nimrod's design focuses on
+efficiency, expressiveness, elegance (in the order of priority).
 
-Pre-compiled snapshots of the compiler are also available on
-[Nimbuild](http://build.nimrod-lang.org/). Your platform however may not 
-currently be built for.
+Read install.txt for instructions of how to build and install it.
 
-The compiler currently supports the following platform and architecture 
-combinations:
-  
-  * Windows (Windows XP or greater) - x86 and x86_64
-  * Linux (most, if not all, distributions) - x86, x86_64, ppc64 and armv6l
-  * Mac OS X 10.04 or higher - x86, x86_64 and ppc64
-  
-In reality a lot more are supported, however they are not tested regularly.
-
-To build from source you will need:
-
-  * gcc 3.x or later recommended. Other alternatives which may work
-    are: clang, Visual C++, Intel's C++ compiler
-  * git or wget
-
-If you are on a fairly modern *nix system, the following steps should work:
-
-```
-$ git clone git://github.com/Araq/Nimrod.git
-$ cd Nimrod
-$ git clone --depth 1 git://github.com/nimrod-code/csources
-$ cd csources && ./build.sh
-$ cd ..
-$ bin/nimrod c koch
-$ ./koch boot -d:release
-```
-
-``koch install [dir]`` may then be used to install Nimrod, or you can simply
-add it to your PATH. More ``koch`` related options are documented in
-[doc/koch.txt](doc/koch.txt).
-
-The above steps can be performed on Windows in a similar fashion, the
-``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used
-instead of ``build.sh``.
-
-## Getting help
-A [forum](http://forum.nimrod-lang.org/) is available if you have any
-questions, and you can also get help in the IRC channel on
-[Freenode](irc://irc.freenode.net/nimrod) in #nimrod. If you ask questions on
-[StackOverflow use the nimrod
-tag](http://stackoverflow.com/questions/tagged/nimrod).
-
-## License
 The compiler and the standard library are licensed under the MIT license, 
 except for some modules where the documentation suggests otherwise. This means 
 that you can use any license for your own programs developed with Nimrod, 
@@ -62,5 +14,5 @@ allowing you to create commercial applications.
 
 Read copying.txt for more details.
 
-Copyright (c) 2004-2014 Andreas Rumpf.
+Copyright (c) 2006-2014 Andreas Rumpf.
 All rights reserved.
diff --git a/tests/assert/tuserassert.nim b/tests/assert/tuserassert.nim
index 8710ee4867..57b229ca91 100644
--- a/tests/assert/tuserassert.nim
+++ b/tests/assert/tuserassert.nim
@@ -3,7 +3,7 @@ discard """
 """
 
 template myAssert(cond: expr) = 
-  when rand(3) < 3:
+  when 3 <= 3:
     let c = cond.astToStr
     if not cond:
       echo c, "ugh"
diff --git a/tests/async/tasyncexceptions.nim b/tests/async/tasyncexceptions.nim
new file mode 100644
index 0000000000..ca73c6a3d1
--- /dev/null
+++ b/tests/async/tasyncexceptions.nim
@@ -0,0 +1,40 @@
+discard """
+  file: "tasyncexceptions.nim"
+  exitcode: 1
+  outputsub: "Error: unhandled exception: foobar [E_Base]"
+"""
+import asyncdispatch
+
+proc accept(): PFuture[int] {.async.} =
+  await sleepAsync(100)
+  result = 4
+
+proc recvLine(fd: int): PFuture[string] {.async.} =
+  await sleepAsync(100)
+  return "get"
+
+proc processClient(fd: int) {.async.} =
+  # these finish synchronously, we need some async delay to emulate this bug.
+  var line = await recvLine(fd)
+  var foo = line[0]
+  if foo == 'g':
+    raise newException(EBase, "foobar")
+  
+
+proc serve() {.async.} =
+
+  while true:
+    var fut = await accept()
+    await processClient(fut)
+
+when isMainModule:
+  proc main =
+    var fut = serve()
+    fut.callback =
+      proc () =
+        if fut.failed:
+          # This test ensures that this exception crashes the application
+          # as it is not handled.
+          raise fut.error
+    runForever()
+  main()
diff --git a/tests/async/tasynciossl.nim b/tests/async/tasynciossl.nim
index 26c4c587c8..6b38fcf7b1 100644
--- a/tests/async/tasynciossl.nim
+++ b/tests/async/tasynciossl.nim
@@ -5,7 +5,8 @@ discard """
 """
 import sockets, asyncio, strutils, times
 
-var disp = newDispatcher()
+var disp {.threadvar.}: PDispatcher
+disp = newDispatcher()
 var msgCount = 0
 
 when defined(ssl):
diff --git a/tests/ccgbugs/tmissinginit.nim b/tests/ccgbugs/tmissinginit.nim
new file mode 100644
index 0000000000..d440608e65
--- /dev/null
+++ b/tests/ccgbugs/tmissinginit.nim
@@ -0,0 +1,30 @@
+discard """
+  output: '''0
+0
+0
+0
+[[a = nil,
+b = nil]]'''
+"""
+
+# bug #1475
+type
+  Crash = object
+    a: string
+    b: seq[string]
+
+proc initCrash(): Crash = discard
+
+proc test() =
+  var blongname = [initCrash()]
+  echo repr(blongname)
+
+# bug #1434
+proc bug: array[1, int] = discard
+
+echo bug()[0]
+echo bug()[0]
+echo bug()[0]
+echo bug()[0]
+
+when isMainModule: test()
diff --git a/tests/closure/tclosure.nim b/tests/closure/tclosure.nim
index d9e7b8ee4a..764aaa97d1 100644
--- a/tests/closure/tclosure.nim
+++ b/tests/closure/tclosure.nim
@@ -1,7 +1,6 @@
 discard """
   file: "tclosure.nim"
-  output: "2 4 6 8 10"
-  disabled: true
+  output: "1 3 6 11 20"
 """
 # Test the closure implementation
 
@@ -30,7 +29,8 @@ proc testA() =
 testA()
 
 myData.each do (x: int):
-  write(stout, x)
+  write(stdout, x)
+  write(stdout, " ")
 
 #OUT 2 4 6 8 10
 
@@ -42,6 +42,6 @@ type
 proc getInterf(): ITest =
   var shared: int
   
-  return (setter: proc (x) = shared = x,
+  return (setter: proc (x: int) = shared = x,
           getter: proc (): int = return shared)
 
diff --git a/tests/closure/tforum.nim b/tests/closure/tforum.nim
new file mode 100644
index 0000000000..4f6a16ff7f
--- /dev/null
+++ b/tests/closure/tforum.nim
@@ -0,0 +1,44 @@
+discard """
+  output: '''asdas
+processClient end
+false
+'''
+"""
+
+type
+  PAsyncHttpServer = ref object
+    value: string
+  PFutureBase = ref object
+    callback: proc () {.closure.}
+    value: string
+    failed: bool
+
+proc accept(server: PAsyncHttpServer): PFutureBase =
+  new(result)
+  result.callback = proc () =
+    discard
+  server.value = "hahaha"
+
+proc processClient(): PFutureBase =
+  new(result)
+
+proc serve(server: PAsyncHttpServer): PFutureBase =
+  iterator serveIter(): PFutureBase {.closure.} =
+    echo server.value
+    while true:
+      var acceptAddrFut = server.accept()
+      yield acceptAddrFut
+      var fut = acceptAddrFut.value
+
+      var f = processClient()
+      f.callback =
+        proc () =
+          echo("processClient end")
+          echo(f.failed)
+      yield f
+  var x = serveIter
+  for i in 0 .. 1:
+    result = x()
+    result.callback()
+
+discard serve(PAsyncHttpServer(value: "asdas"))
diff --git a/tests/closure/tjester.nim b/tests/closure/tjester.nim
new file mode 100644
index 0000000000..48e5186f03
--- /dev/null
+++ b/tests/closure/tjester.nim
@@ -0,0 +1,32 @@
+discard """
+  output: '''baro0'''
+"""
+
+type
+  Future[T] = ref object
+    data: T
+    callback: proc () {.closure.}
+
+proc cbOuter(response: string) {.closure, discardable.} =
+  iterator cbIter(): Future[int] {.closure.} =
+    for i in 0..7:
+      proc foo(): int =
+        iterator fooIter(): Future[int] {.closure.} =
+          echo response, i
+          yield Future[int](data: 17)
+        var iterVar = fooIter
+        iterVar().data
+      yield Future[int](data: foo())
+      
+  var iterVar2 = cbIter
+  proc cb2() {.closure.} =
+    try:
+      if not finished(iterVar2):
+        let next = iterVar2()
+        if next != nil:
+          next.callback = cb2
+    except:
+      echo "WTF"
+  cb2()
+
+cbOuter "baro"
diff --git a/tests/closure/tnestedclosure.nim b/tests/closure/tnestedclosure.nim
new file mode 100644
index 0000000000..c8f1e231ba
--- /dev/null
+++ b/tests/closure/tnestedclosure.nim
@@ -0,0 +1,51 @@
+discard """
+  output: '''foo88
+23 24foo 88
+foo88
+23 24foo 88
+hohoho'''
+"""
+
+# test nested closure
+proc main(param: int) =
+  var foo = 23
+  proc outer(outerParam: string) =
+    var outerVar = 88
+    echo outerParam, outerVar
+    proc inner() =
+      block Test:
+        echo foo, " ", param, outerParam, " ", outerVar
+    inner()
+  outer("foo")
+
+# test simple closure within dummy 'main':
+proc dummy =
+  proc main2(param: int) =
+    var foo = 23
+    proc outer(outerParam: string) =
+      var outerVar = 88
+      echo outerParam, outerVar
+      proc inner() =
+        block Test:
+          echo foo, " ", param, outerParam, " ", outerVar
+      inner()
+    outer("foo")
+  main2(24)
+
+dummy()
+
+main(24)
+
+# Jester + async triggered this bug:
+proc cbOuter() =
+  var response = "hohoho"
+  block:
+    proc cbIter() =
+      block:
+        proc fooIter() =
+          echo response
+        fooIter()
+        
+    cbIter()
+
+cbOuter()
diff --git a/tests/controlflow/tbreak.nim b/tests/controlflow/tbreak.nim
new file mode 100644
index 0000000000..7deab4cafc
--- /dev/null
+++ b/tests/controlflow/tbreak.nim
@@ -0,0 +1,44 @@
+discard """
+  output: '''10
+true true
+true false
+false true
+false false'''
+"""
+
+var
+  x = false
+  run = true
+
+while run:
+  run = false
+  block myblock:
+    if true:
+      break
+    echo "leaving myblock"
+  x = true
+doAssert(x)
+
+# bug #1418
+iterator foo: int =
+  for x in 0 .. 9:
+    for y in [10,20,30,40,50,60,70,80,90]:
+      yield x + y
+
+for p in foo():
+  echo p
+  break
+
+iterator permutations: int =
+  yield 10
+
+for p in permutations():
+  break
+
+# regression:
+proc main =
+  for x in [true, false]:
+    for y in [true, false]:
+      echo x, " ", y
+
+main()
diff --git a/tests/converter/tconvert.nim b/tests/converter/tconvert.nim
index a8ddcf1193..a371402349 100644
--- a/tests/converter/tconvert.nim
+++ b/tests/converter/tconvert.nim
@@ -1,5 +1,3 @@
-import
-  Cairo
 
 converter FloatConversion64(x: int): float64 = return toFloat(x)
 converter FloatConversion32(x: int): float32 = return toFloat(x)
@@ -7,34 +5,10 @@ converter FloatConversionPlain(x: int): float = return toFloat(x)
 
 const width = 500
 const height = 500
-const outFile = "CairoTest.png"
 
-var surface = Cairo.ImageSurfaceCreate(CAIRO.FORMAT_RGB24, width, height)
-var ç = Cairo.Create(surface)
+proc ImageSurfaceCreate(w, h: float) = discard
 
-ç.SetSourceRGB(1, 1, 1)
-ç.Paint()
-
-ç.SetLineWidth(10)
-ç.SetLineCap(CAIRO.LINE_CAP_ROUND)
-
-const count = 12
-var winc = width / count
-var hinc = width / count
-for i in 1 .. count-1:
-  var amount = i / count
-  ç.SetSourceRGB(0, 1 - amount, amount)
-  ç.MoveTo(i * winc, hinc)
-  ç.LineTo(width - i * winc, height - hinc)
-  ç.Stroke()
-
-  ç.SetSourceRGB(1 - amount, 0, amount)
-  ç.MoveTo(winc, i * hinc)
-  ç.LineTo(width - winc, height - i * hinc)
-  ç.Stroke()
-
-echo(surface.WriteToPNG(outFile))
-surface.Destroy()
+ImageSurfaceCreate(width, height)
 
 type TFoo = object
 
diff --git a/tests/destructor/tdestructor.nim b/tests/destructor/tdestructor.nim
index e5236aaab3..f0ea3c5c67 100644
--- a/tests/destructor/tdestructor.nim
+++ b/tests/destructor/tdestructor.nim
@@ -55,14 +55,14 @@ type
         q: TMyGeneric3[TMyObj, int, int]
       r: string
 
-proc destruct(o: var TMyObj) {.destructor.} =
+proc destroy(o: var TMyObj) {.override.} =
   if o.p != nil: dealloc o.p
   echo "myobj destroyed"
 
-proc destroy(o: var TMyGeneric1) {.destructor.} =
+proc destroy(o: var TMyGeneric1) {.override.} =
   echo "mygeneric1 destroyed"
 
-proc destroy[A, B](o: var TMyGeneric2[A, B]) {.destructor.} =
+proc destroy[A, B](o: var TMyGeneric2[A, B]) {.override.} =
   echo "mygeneric2 destroyed"
 
 proc open: TMyObj =
diff --git a/tests/destructor/tdestructor2.nim b/tests/destructor/tdestructor2.nim
index da9192a3f9..a5b62860ca 100644
--- a/tests/destructor/tdestructor2.nim
+++ b/tests/destructor/tdestructor2.nim
@@ -8,7 +8,7 @@ type
     x, y: int
     p: pointer
     
-proc destruct(o: var TMyObj) {.destructor.} =
+proc destroy(o: var TMyObj) {.override.} =
   if o.p != nil: dealloc o.p
   
 proc open: TMyObj =
diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim
index 0014cff465..f73230ff90 100644
--- a/tests/effects/teffects1.nim
+++ b/tests/effects/teffects1.nim
@@ -1,5 +1,5 @@
 discard """
-  line: 1913
+  line: 2136
   file: "system.nim"
   errormsg: "can raise an unlisted exception: ref EIO"
 """
diff --git a/tests/effects/tgcsafe.nim b/tests/effects/tgcsafe.nim
new file mode 100644
index 0000000000..87388238a8
--- /dev/null
+++ b/tests/effects/tgcsafe.nim
@@ -0,0 +1,16 @@
+discard """
+  line: 15
+  errormsg: "'mainUnsafe' is not GC-safe"
+"""
+
+proc mymap(x: proc ()) =
+  x()
+
+var
+  myglob: string
+
+proc mainSafe() {.gcsafe.} =
+  mymap(proc () = echo "foo")
+
+proc mainUnsafe() {.gcsafe.} =
+  mymap(proc () = myglob = "bar"; echo "foo", myglob)
diff --git a/tests/enum/tenumitems.nim b/tests/enum/tenumitems.nim
index b6eee5ba81..b92cff6bf5 100644
--- a/tests/enum/tenumitems.nim
+++ b/tests/enum/tenumitems.nim
@@ -1,6 +1,6 @@
 discard """
   line: 7
-  errormsg: "type mismatch"
+  errormsg: "expression 'items' cannot be called"
 """
 
 type a = enum b,c,d
diff --git a/tests/float/tfloat4.nim b/tests/float/tfloat4.nim
new file mode 100644
index 0000000000..960c4e5f71
--- /dev/null
+++ b/tests/float/tfloat4.nim
@@ -0,0 +1,42 @@
+import math, strutils
+
+proc c_sprintf(buf, fmt: cstring) {.importc:"sprintf", header: "", varargs.}
+
+proc floatToStr(f: float64): string =
+  var buffer: array[128, char]
+  c_sprintf(buffer, "%.16e", f)
+  result = ""
+  for ch in buffer:
+    if ch == '\0':
+      return
+    add(result, ch)
+
+let testFloats = [
+  "0", "-1", "1", "1.", ".3", "3.3", "-.3", "-99.99",
+  "1.1e10", "-2e100", "1.234e-10", "1.234e+10",
+  "-inf", "inf", "+inf",
+  "3.14159265358979323846264338327950288",
+  "1.57079632679489661923132169163975144",
+  "0.785398163397448309615660845819875721",
+  "1.41421356237309504880168872420969808",
+  "0.707106781186547524400844362104849039",
+  "2.71828182845904523536028747135266250",
+  "0.00097656250000000021684043449710088680149056017398834228515625"
+]
+
+for num in testFloats:
+  assert num.parseFloat.floatToStr.parseFloat == num.parseFloat
+
+assert "0".parseFloat == 0.0
+assert "-.1".parseFloat == -0.1
+assert "2.5e1".parseFloat == 25.0
+assert "1e10".parseFloat == 10_000_000_000.0
+assert "0.000_005".parseFloat == 5.000_000e-6
+assert "1.234_567e+2".parseFloat == 123.4567
+assert "1e1_00".parseFloat == "1e100".parseFloat
+assert "3.1415926535897932384626433".parseFloat ==
+       3.1415926535897932384626433
+assert "2.71828182845904523536028747".parseFloat ==
+       2.71828182845904523536028747
+assert 0.00097656250000000021684043449710088680149056017398834228515625 ==
+     "0.00097656250000000021684043449710088680149056017398834228515625".parseFloat
diff --git a/tests/generics/mdotlookup.nim b/tests/generics/mdotlookup.nim
index 7a5e0ccbf0..0c4d0c87c7 100644
--- a/tests/generics/mdotlookup.nim
+++ b/tests/generics/mdotlookup.nim
@@ -6,3 +6,11 @@ type MyObj = object
 proc foo*(b: any) =
   var o: MyObj
   echo b.baz, " ", o.x.baz, " ", b.baz()
+
+import sets
+
+var intset = initSet[int]()
+
+proc func*[T](a: T) =
+  if a in intset: echo("true")
+  else: echo("false")
diff --git a/tests/generics/tdotlookup.nim b/tests/generics/tdotlookup.nim
index b886cd8c91..d3deca7fcb 100644
--- a/tests/generics/tdotlookup.nim
+++ b/tests/generics/tdotlookup.nim
@@ -1,7 +1,10 @@
 discard """
-  output: '''5 5 5'''
+  output: '''5 5 5
+false'''
 """
 
 import mdotlookup
 
 foo(7)
+# bug #1444
+func(4)
diff --git a/tests/init/tuninit1.nim b/tests/init/tuninit1.nim
index 2a994b1879..57443a7d3d 100644
--- a/tests/init/tuninit1.nim
+++ b/tests/init/tuninit1.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "'y' might not have been initialized"
+  msg: "Warning: 'y' might not have been initialized [Uninit]"
   line:34
 """
 
diff --git a/tests/manyloc/keineschweine/lib/gl.nim b/tests/manyloc/keineschweine/lib/gl.nim
new file mode 100644
index 0000000000..9387b5bc9e
--- /dev/null
+++ b/tests/manyloc/keineschweine/lib/gl.nim
@@ -0,0 +1,1536 @@
+#
+#
+#  Adaption of the delphi3d.net OpenGL units to FreePascal
+#  Sebastian Guenther (sg@freepascal.org) in 2002
+#  These units are free to use
+#
+#******************************************************************************
+# Converted to Delphi by Tom Nuydens (tom@delphi3d.net)                        
+# For the latest updates, visit Delphi3D: http://www.delphi3d.net              
+#******************************************************************************
+
+when defined(windows): 
+  {.push, callconv: stdcall.}
+else: 
+  {.push, callconv: cdecl.}
+when defined(windows): 
+  const 
+    dllname* = "opengl32.dll"
+elif defined(macosx): 
+  const 
+    dllname* = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
+else: 
+  const 
+    dllname* = "libGL.so.1"
+type 
+  PGLenum* = ptr TGLenum
+  PGLboolean* = ptr TGLboolean
+  PGLbitfield* = ptr TGLbitfield
+  TGLbyte* = int8
+  PGLbyte* = ptr TGlbyte
+  PGLshort* = ptr TGLshort
+  PGLint* = ptr TGLint
+  PGLsizei* = ptr TGLsizei
+  PGLubyte* = ptr TGLubyte
+  PGLushort* = ptr TGLushort
+  PGLuint* = ptr TGLuint
+  PGLfloat* = ptr TGLfloat
+  PGLclampf* = ptr TGLclampf
+  PGLdouble* = ptr TGLdouble
+  PGLclampd* = ptr TGLclampd
+  PGLvoid* = Pointer
+  PPGLvoid* = ptr PGLvoid
+  TGLenum* = cint
+  TGLboolean* = bool
+  TGLbitfield* = cint
+  TGLshort* = int16
+  TGLint* = cint
+  TGLsizei* = int
+  TGLubyte* = int8
+  TGLushort* = int16
+  TGLuint* = cint
+  TGLfloat* = float32
+  TGLclampf* = float32
+  TGLdouble* = float
+  TGLclampd* = float
+
+const                         # Version
+  GL_VERSION_1_1* = 1         # AccumOp
+  constGL_ACCUM* = 0x00000100
+  GL_LOAD* = 0x00000101
+  GL_RETURN* = 0x00000102
+  GL_MULT* = 0x00000103
+  GL_ADD* = 0x00000104        # AlphaFunction
+  GL_NEVER* = 0x00000200
+  GL_LESS* = 0x00000201
+  GL_EQUAL* = 0x00000202
+  GL_LEQUAL* = 0x00000203
+  GL_GREATER* = 0x00000204
+  GL_NOTEQUAL* = 0x00000205
+  GL_GEQUAL* = 0x00000206
+  GL_ALWAYS* = 0x00000207     # AttribMask
+  GL_CURRENT_BIT* = 0x00000001
+  GL_POINT_BIT* = 0x00000002
+  GL_LINE_BIT* = 0x00000004
+  GL_POLYGON_BIT* = 0x00000008
+  GL_POLYGON_STIPPLE_BIT* = 0x00000010
+  GL_PIXEL_MODE_BIT* = 0x00000020
+  GL_LIGHTING_BIT* = 0x00000040
+  GL_FOG_BIT* = 0x00000080
+  GL_DEPTH_BUFFER_BIT* = 0x00000100
+  GL_ACCUM_BUFFER_BIT* = 0x00000200
+  GL_STENCIL_BUFFER_BIT* = 0x00000400
+  GL_VIEWPORT_BIT* = 0x00000800
+  GL_TRANSFORM_BIT* = 0x00001000
+  GL_ENABLE_BIT* = 0x00002000
+  GL_COLOR_BUFFER_BIT* = 0x00004000
+  GL_HINT_BIT* = 0x00008000
+  GL_EVAL_BIT* = 0x00010000
+  GL_LIST_BIT* = 0x00020000
+  GL_TEXTURE_BIT* = 0x00040000
+  GL_SCISSOR_BIT* = 0x00080000
+  GL_ALL_ATTRIB_BITS* = 0x000FFFFF # BeginMode
+  GL_POINTS* = 0x00000000
+  GL_LINES* = 0x00000001
+  GL_LINE_LOOP* = 0x00000002
+  GL_LINE_STRIP* = 0x00000003
+  GL_TRIANGLES* = 0x00000004
+  GL_TRIANGLE_STRIP* = 0x00000005
+  GL_TRIANGLE_FAN* = 0x00000006
+  GL_QUADS* = 0x00000007
+  GL_QUAD_STRIP* = 0x00000008
+  GL_POLYGON* = 0x00000009    # BlendingFactorDest
+  GL_ZERO* = 0
+  GL_ONE* = 1
+  GL_SRC_COLOR* = 0x00000300
+  GL_ONE_MINUS_SRC_COLOR* = 0x00000301
+  GL_SRC_ALPHA* = 0x00000302
+  GL_ONE_MINUS_SRC_ALPHA* = 0x00000303
+  GL_DST_ALPHA* = 0x00000304
+  GL_ONE_MINUS_DST_ALPHA* = 0x00000305 # BlendingFactorSrc
+                                       #      GL_ZERO
+                                       #      GL_ONE
+  GL_DST_COLOR* = 0x00000306
+  GL_ONE_MINUS_DST_COLOR* = 0x00000307
+  GL_SRC_ALPHA_SATURATE* = 0x00000308 #      GL_SRC_ALPHA
+                                      #      GL_ONE_MINUS_SRC_ALPHA
+                                      #      GL_DST_ALPHA
+                                      #      GL_ONE_MINUS_DST_ALPHA
+                                      # Boolean
+  GL_TRUE* = 1
+  GL_FALSE* = 0               # ClearBufferMask
+                              #      GL_COLOR_BUFFER_BIT
+                              #      GL_ACCUM_BUFFER_BIT
+                              #      GL_STENCIL_BUFFER_BIT
+                              #      GL_DEPTH_BUFFER_BIT
+                              # ClientArrayType
+                              #      GL_VERTEX_ARRAY
+                              #      GL_NORMAL_ARRAY
+                              #      GL_COLOR_ARRAY
+                              #      GL_INDEX_ARRAY
+                              #      GL_TEXTURE_COORD_ARRAY
+                              #      GL_EDGE_FLAG_ARRAY
+                              # ClipPlaneName
+  GL_CLIP_PLANE0* = 0x00003000
+  GL_CLIP_PLANE1* = 0x00003001
+  GL_CLIP_PLANE2* = 0x00003002
+  GL_CLIP_PLANE3* = 0x00003003
+  GL_CLIP_PLANE4* = 0x00003004
+  GL_CLIP_PLANE5* = 0x00003005 # ColorMaterialFace
+                               #      GL_FRONT
+                               #      GL_BACK
+                               #      GL_FRONT_AND_BACK
+                               # ColorMaterialParameter
+                               #      GL_AMBIENT
+                               #      GL_DIFFUSE
+                               #      GL_SPECULAR
+                               #      GL_EMISSION
+                               #      GL_AMBIENT_AND_DIFFUSE
+                               # ColorPointerType
+                               #      GL_BYTE
+                               #      GL_UNSIGNED_BYTE
+                               #      GL_SHORT
+                               #      GL_UNSIGNED_SHORT
+                               #      GL_INT
+                               #      GL_UNSIGNED_INT
+                               #      GL_FLOAT
+                               #      GL_DOUBLE
+                               # CullFaceMode
+                               #      GL_FRONT
+                               #      GL_BACK
+                               #      GL_FRONT_AND_BACK
+                               # DataType
+  GL_BYTE* = 0x00001400
+  GL_UNSIGNED_BYTE* = 0x00001401
+  GL_SHORT* = 0x00001402
+  GL_UNSIGNED_SHORT* = 0x00001403
+  GL_INT* = 0x00001404
+  GL_UNSIGNED_INT* = 0x00001405
+  GL_FLOAT* = 0x00001406
+  GL_2_BYTES* = 0x00001407
+  GL_3_BYTES* = 0x00001408
+  GL_4_BYTES* = 0x00001409
+  GL_DOUBLE* = 0x0000140A     # DepthFunction
+                              #      GL_NEVER
+                              #      GL_LESS
+                              #      GL_EQUAL
+                              #      GL_LEQUAL
+                              #      GL_GREATER
+                              #      GL_NOTEQUAL
+                              #      GL_GEQUAL
+                              #      GL_ALWAYS
+                              # DrawBufferMode
+  GL_NONE* = 0
+  GL_FRONT_LEFT* = 0x00000400
+  GL_FRONT_RIGHT* = 0x00000401
+  GL_BACK_LEFT* = 0x00000402
+  GL_BACK_RIGHT* = 0x00000403
+  GL_FRONT* = 0x00000404
+  GL_BACK* = 0x00000405
+  GL_LEFT* = 0x00000406
+  GL_RIGHT* = 0x00000407
+  GL_FRONT_AND_BACK* = 0x00000408
+  GL_AUX0* = 0x00000409
+  GL_AUX1* = 0x0000040A
+  GL_AUX2* = 0x0000040B
+  GL_AUX3* = 0x0000040C       # Enable
+                              #      GL_FOG
+                              #      GL_LIGHTING
+                              #      GL_TEXTURE_1D
+                              #      GL_TEXTURE_2D
+                              #      GL_LINE_STIPPLE
+                              #      GL_POLYGON_STIPPLE
+                              #      GL_CULL_FACE
+                              #      GL_ALPHA_TEST
+                              #      GL_BLEND
+                              #      GL_INDEX_LOGIC_OP
+                              #      GL_COLOR_LOGIC_OP
+                              #      GL_DITHER
+                              #      GL_STENCIL_TEST
+                              #      GL_DEPTH_TEST
+                              #      GL_CLIP_PLANE0
+                              #      GL_CLIP_PLANE1
+                              #      GL_CLIP_PLANE2
+                              #      GL_CLIP_PLANE3
+                              #      GL_CLIP_PLANE4
+                              #      GL_CLIP_PLANE5
+                              #      GL_LIGHT0
+                              #      GL_LIGHT1
+                              #      GL_LIGHT2
+                              #      GL_LIGHT3
+                              #      GL_LIGHT4
+                              #      GL_LIGHT5
+                              #      GL_LIGHT6
+                              #      GL_LIGHT7
+                              #      GL_TEXTURE_GEN_S
+                              #      GL_TEXTURE_GEN_T
+                              #      GL_TEXTURE_GEN_R
+                              #      GL_TEXTURE_GEN_Q
+                              #      GL_MAP1_VERTEX_3
+                              #      GL_MAP1_VERTEX_4
+                              #      GL_MAP1_COLOR_4
+                              #      GL_MAP1_INDEX
+                              #      GL_MAP1_NORMAL
+                              #      GL_MAP1_TEXTURE_COORD_1
+                              #      GL_MAP1_TEXTURE_COORD_2
+                              #      GL_MAP1_TEXTURE_COORD_3
+                              #      GL_MAP1_TEXTURE_COORD_4
+                              #      GL_MAP2_VERTEX_3
+                              #      GL_MAP2_VERTEX_4
+                              #      GL_MAP2_COLOR_4
+                              #      GL_MAP2_INDEX
+                              #      GL_MAP2_NORMAL
+                              #      GL_MAP2_TEXTURE_COORD_1
+                              #      GL_MAP2_TEXTURE_COORD_2
+                              #      GL_MAP2_TEXTURE_COORD_3
+                              #      GL_MAP2_TEXTURE_COORD_4
+                              #      GL_POINT_SMOOTH
+                              #      GL_LINE_SMOOTH
+                              #      GL_POLYGON_SMOOTH
+                              #      GL_SCISSOR_TEST
+                              #      GL_COLOR_MATERIAL
+                              #      GL_NORMALIZE
+                              #      GL_AUTO_NORMAL
+                              #      GL_VERTEX_ARRAY
+                              #      GL_NORMAL_ARRAY
+                              #      GL_COLOR_ARRAY
+                              #      GL_INDEX_ARRAY
+                              #      GL_TEXTURE_COORD_ARRAY
+                              #      GL_EDGE_FLAG_ARRAY
+                              #      GL_POLYGON_OFFSET_POINT
+                              #      GL_POLYGON_OFFSET_LINE
+                              #      GL_POLYGON_OFFSET_FILL
+                              # ErrorCode
+  GL_NO_ERROR* = 0
+  GL_INVALID_ENUM* = 0x00000500
+  GL_INVALID_VALUE* = 0x00000501
+  GL_INVALID_OPERATION* = 0x00000502
+  GL_STACK_OVERFLOW* = 0x00000503
+  GL_STACK_UNDERFLOW* = 0x00000504
+  GL_OUT_OF_MEMORY* = 0x00000505 # FeedBackMode
+  GL_2D* = 0x00000600
+  GL_3D* = 0x00000601
+  GL_3D_COLOR* = 0x00000602
+  GL_3D_COLOR_TEXTURE* = 0x00000603
+  GL_4D_COLOR_TEXTURE* = 0x00000604 # FeedBackToken
+  GL_PASS_THROUGH_TOKEN* = 0x00000700
+  GL_POINT_TOKEN* = 0x00000701
+  GL_LINE_TOKEN* = 0x00000702
+  GL_POLYGON_TOKEN* = 0x00000703
+  GL_BITMAP_TOKEN* = 0x00000704
+  GL_DRAW_PIXEL_TOKEN* = 0x00000705
+  GL_COPY_PIXEL_TOKEN* = 0x00000706
+  GL_LINE_RESET_TOKEN* = 0x00000707 # FogMode
+                                    #      GL_LINEAR
+  GL_EXP* = 0x00000800
+  GL_EXP2* = 0x00000801       # FogParameter
+                              #      GL_FOG_COLOR
+                              #      GL_FOG_DENSITY
+                              #      GL_FOG_END
+                              #      GL_FOG_INDEX
+                              #      GL_FOG_MODE
+                              #      GL_FOG_START
+                              # FrontFaceDirection
+  GL_CW* = 0x00000900
+  GL_CCW* = 0x00000901        # GetMapTarget
+  GL_COEFF* = 0x00000A00
+  GL_ORDER* = 0x00000A01
+  GL_DOMAIN* = 0x00000A02     # GetPixelMap
+                              #      GL_PIXEL_MAP_I_TO_I
+                              #      GL_PIXEL_MAP_S_TO_S
+                              #      GL_PIXEL_MAP_I_TO_R
+                              #      GL_PIXEL_MAP_I_TO_G
+                              #      GL_PIXEL_MAP_I_TO_B
+                              #      GL_PIXEL_MAP_I_TO_A
+                              #      GL_PIXEL_MAP_R_TO_R
+                              #      GL_PIXEL_MAP_G_TO_G
+                              #      GL_PIXEL_MAP_B_TO_B
+                              #      GL_PIXEL_MAP_A_TO_A
+                              # GetPointerTarget
+                              #      GL_VERTEX_ARRAY_POINTER
+                              #      GL_NORMAL_ARRAY_POINTER
+                              #      GL_COLOR_ARRAY_POINTER
+                              #      GL_INDEX_ARRAY_POINTER
+                              #      GL_TEXTURE_COORD_ARRAY_POINTER
+                              #      GL_EDGE_FLAG_ARRAY_POINTER
+                              # GetTarget
+  GL_CURRENT_COLOR* = 0x00000B00
+  GL_CURRENT_INDEX* = 0x00000B01
+  GL_CURRENT_NORMAL* = 0x00000B02
+  GL_CURRENT_TEXTURE_COORDS* = 0x00000B03
+  GL_CURRENT_RASTER_COLOR* = 0x00000B04
+  GL_CURRENT_RASTER_INDEX* = 0x00000B05
+  GL_CURRENT_RASTER_TEXTURE_COORDS* = 0x00000B06
+  GL_CURRENT_RASTER_POSITION* = 0x00000B07
+  GL_CURRENT_RASTER_POSITION_VALID* = 0x00000B08
+  GL_CURRENT_RASTER_DISTANCE* = 0x00000B09
+  GL_POINT_SMOOTH* = 0x00000B10
+  constGL_POINT_SIZE* = 0x00000B11
+  GL_POINT_SIZE_RANGE* = 0x00000B12
+  GL_POINT_SIZE_GRANULARITY* = 0x00000B13
+  GL_LINE_SMOOTH* = 0x00000B20
+  constGL_LINE_WIDTH* = 0x00000B21
+  GL_LINE_WIDTH_RANGE* = 0x00000B22
+  GL_LINE_WIDTH_GRANULARITY* = 0x00000B23
+  constGL_LINE_STIPPLE* = 0x00000B24
+  GL_LINE_STIPPLE_PATTERN* = 0x00000B25
+  GL_LINE_STIPPLE_REPEAT* = 0x00000B26
+  GL_LIST_MODE* = 0x00000B30
+  GL_MAX_LIST_NESTING* = 0x00000B31
+  constGL_LIST_BASE* = 0x00000B32
+  GL_LIST_INDEX* = 0x00000B33
+  constGL_POLYGON_MODE* = 0x00000B40
+  GL_POLYGON_SMOOTH* = 0x00000B41
+  constGL_POLYGON_STIPPLE* = 0x00000B42
+  constGL_EDGE_FLAG* = 0x00000B43
+  constGL_CULL_FACE* = 0x00000B44
+  GL_CULL_FACE_MODE* = 0x00000B45
+  constGL_FRONT_FACE* = 0x00000B46
+  GL_LIGHTING* = 0x00000B50
+  GL_LIGHT_MODEL_LOCAL_VIEWER* = 0x00000B51
+  GL_LIGHT_MODEL_TWO_SIDE* = 0x00000B52
+  GL_LIGHT_MODEL_AMBIENT* = 0x00000B53
+  constGL_SHADE_MODEL* = 0x00000B54
+  GL_COLOR_MATERIAL_FACE* = 0x00000B55
+  GL_COLOR_MATERIAL_PARAMETER* = 0x00000B56
+  constGL_COLOR_MATERIAL* = 0x00000B57
+  GL_FOG* = 0x00000B60
+  GL_FOG_INDEX* = 0x00000B61
+  GL_FOG_DENSITY* = 0x00000B62
+  GL_FOG_START* = 0x00000B63
+  GL_FOG_END* = 0x00000B64
+  GL_FOG_MODE* = 0x00000B65
+  GL_FOG_COLOR* = 0x00000B66
+  constGL_DEPTH_RANGE* = 0x00000B70
+  GL_DEPTH_TEST* = 0x00000B71
+  GL_DEPTH_WRITEMASK* = 0x00000B72
+  GL_DEPTH_CLEAR_VALUE* = 0x00000B73
+  constGL_DEPTH_FUNC* = 0x00000B74
+  GL_ACCUM_CLEAR_VALUE* = 0x00000B80
+  GL_STENCIL_TEST* = 0x00000B90
+  GL_STENCIL_CLEAR_VALUE* = 0x00000B91
+  constGL_STENCIL_FUNC* = 0x00000B92
+  GL_STENCIL_VALUE_MASK* = 0x00000B93
+  GL_STENCIL_FAIL* = 0x00000B94
+  GL_STENCIL_PASS_DEPTH_FAIL* = 0x00000B95
+  GL_STENCIL_PASS_DEPTH_PASS* = 0x00000B96
+  GL_STENCIL_REF* = 0x00000B97
+  GL_STENCIL_WRITEMASK* = 0x00000B98
+  constGL_MATRIX_MODE* = 0x00000BA0
+  GL_NORMALIZE* = 0x00000BA1
+  constGL_VIEWPORT* = 0x00000BA2
+  GL_MODELVIEW_STACK_DEPTH* = 0x00000BA3
+  GL_PROJECTION_STACK_DEPTH* = 0x00000BA4
+  GL_TEXTURE_STACK_DEPTH* = 0x00000BA5
+  GL_MODELVIEW_MATRIX* = 0x00000BA6
+  GL_PROJECTION_MATRIX* = 0x00000BA7
+  GL_TEXTURE_MATRIX* = 0x00000BA8
+  GL_ATTRIB_STACK_DEPTH* = 0x00000BB0
+  GL_CLIENT_ATTRIB_STACK_DEPTH* = 0x00000BB1
+  GL_ALPHA_TEST* = 0x00000BC0
+  GL_ALPHA_TEST_FUNC* = 0x00000BC1
+  GL_ALPHA_TEST_REF* = 0x00000BC2
+  GL_DITHER* = 0x00000BD0
+  GL_BLEND_DST* = 0x00000BE0
+  GL_BLEND_SRC* = 0x00000BE1
+  GL_BLEND* = 0x00000BE2
+  GL_LOGIC_OP_MODE* = 0x00000BF0
+  GL_INDEX_LOGIC_OP* = 0x00000BF1
+  GL_COLOR_LOGIC_OP* = 0x00000BF2
+  GL_AUX_BUFFERS* = 0x00000C00
+  constGL_DRAW_BUFFER* = 0x00000C01
+  constGL_READ_BUFFER* = 0x00000C02
+  GL_SCISSOR_BOX* = 0x00000C10
+  GL_SCISSOR_TEST* = 0x00000C11
+  GL_INDEX_CLEAR_VALUE* = 0x00000C20
+  GL_INDEX_WRITEMASK* = 0x00000C21
+  GL_COLOR_CLEAR_VALUE* = 0x00000C22
+  GL_COLOR_WRITEMASK* = 0x00000C23
+  GL_INDEX_MODE* = 0x00000C30
+  GL_RGBA_MODE* = 0x00000C31
+  GL_DOUBLEBUFFER* = 0x00000C32
+  GL_STEREO* = 0x00000C33
+  constGL_RENDER_MODE* = 0x00000C40
+  GL_PERSPECTIVE_CORRECTION_HINT* = 0x00000C50
+  GL_POINT_SMOOTH_HINT* = 0x00000C51
+  GL_LINE_SMOOTH_HINT* = 0x00000C52
+  GL_POLYGON_SMOOTH_HINT* = 0x00000C53
+  GL_FOG_HINT* = 0x00000C54
+  GL_TEXTURE_GEN_S* = 0x00000C60
+  GL_TEXTURE_GEN_T* = 0x00000C61
+  GL_TEXTURE_GEN_R* = 0x00000C62
+  GL_TEXTURE_GEN_Q* = 0x00000C63
+  GL_PIXEL_MAP_I_TO_I* = 0x00000C70
+  GL_PIXEL_MAP_S_TO_S* = 0x00000C71
+  GL_PIXEL_MAP_I_TO_R* = 0x00000C72
+  GL_PIXEL_MAP_I_TO_G* = 0x00000C73
+  GL_PIXEL_MAP_I_TO_B* = 0x00000C74
+  GL_PIXEL_MAP_I_TO_A* = 0x00000C75
+  GL_PIXEL_MAP_R_TO_R* = 0x00000C76
+  GL_PIXEL_MAP_G_TO_G* = 0x00000C77
+  GL_PIXEL_MAP_B_TO_B* = 0x00000C78
+  GL_PIXEL_MAP_A_TO_A* = 0x00000C79
+  GL_PIXEL_MAP_I_TO_I_SIZE* = 0x00000CB0
+  GL_PIXEL_MAP_S_TO_S_SIZE* = 0x00000CB1
+  GL_PIXEL_MAP_I_TO_R_SIZE* = 0x00000CB2
+  GL_PIXEL_MAP_I_TO_G_SIZE* = 0x00000CB3
+  GL_PIXEL_MAP_I_TO_B_SIZE* = 0x00000CB4
+  GL_PIXEL_MAP_I_TO_A_SIZE* = 0x00000CB5
+  GL_PIXEL_MAP_R_TO_R_SIZE* = 0x00000CB6
+  GL_PIXEL_MAP_G_TO_G_SIZE* = 0x00000CB7
+  GL_PIXEL_MAP_B_TO_B_SIZE* = 0x00000CB8
+  GL_PIXEL_MAP_A_TO_A_SIZE* = 0x00000CB9
+  GL_UNPACK_SWAP_BYTES* = 0x00000CF0
+  GL_UNPACK_LSB_FIRST* = 0x00000CF1
+  GL_UNPACK_ROW_LENGTH* = 0x00000CF2
+  GL_UNPACK_SKIP_ROWS* = 0x00000CF3
+  GL_UNPACK_SKIP_PIXELS* = 0x00000CF4
+  GL_UNPACK_ALIGNMENT* = 0x00000CF5
+  GL_PACK_SWAP_BYTES* = 0x00000D00
+  GL_PACK_LSB_FIRST* = 0x00000D01
+  GL_PACK_ROW_LENGTH* = 0x00000D02
+  GL_PACK_SKIP_ROWS* = 0x00000D03
+  GL_PACK_SKIP_PIXELS* = 0x00000D04
+  GL_PACK_ALIGNMENT* = 0x00000D05
+  GL_MAP_COLOR* = 0x00000D10
+  GL_MAP_STENCIL* = 0x00000D11
+  GL_INDEX_SHIFT* = 0x00000D12
+  GL_INDEX_OFFSET* = 0x00000D13
+  GL_RED_SCALE* = 0x00000D14
+  GL_RED_BIAS* = 0x00000D15
+  GL_ZOOM_X* = 0x00000D16
+  GL_ZOOM_Y* = 0x00000D17
+  GL_GREEN_SCALE* = 0x00000D18
+  GL_GREEN_BIAS* = 0x00000D19
+  GL_BLUE_SCALE* = 0x00000D1A
+  GL_BLUE_BIAS* = 0x00000D1B
+  GL_ALPHA_SCALE* = 0x00000D1C
+  GL_ALPHA_BIAS* = 0x00000D1D
+  GL_DEPTH_SCALE* = 0x00000D1E
+  GL_DEPTH_BIAS* = 0x00000D1F
+  GL_MAX_EVAL_ORDER* = 0x00000D30
+  GL_MAX_LIGHTS* = 0x00000D31
+  GL_MAX_CLIP_PLANES* = 0x00000D32
+  GL_MAX_TEXTURE_SIZE* = 0x00000D33
+  GL_MAX_PIXEL_MAP_TABLE* = 0x00000D34
+  GL_MAX_ATTRIB_STACK_DEPTH* = 0x00000D35
+  GL_MAX_MODELVIEW_STACK_DEPTH* = 0x00000D36
+  GL_MAX_NAME_STACK_DEPTH* = 0x00000D37
+  GL_MAX_PROJECTION_STACK_DEPTH* = 0x00000D38
+  GL_MAX_TEXTURE_STACK_DEPTH* = 0x00000D39
+  GL_MAX_VIEWPORT_DIMS* = 0x00000D3A
+  GL_MAX_CLIENT_ATTRIB_STACK_DEPTH* = 0x00000D3B
+  GL_SUBPIXEL_BITS* = 0x00000D50
+  GL_INDEX_BITS* = 0x00000D51
+  GL_RED_BITS* = 0x00000D52
+  GL_GREEN_BITS* = 0x00000D53
+  GL_BLUE_BITS* = 0x00000D54
+  GL_ALPHA_BITS* = 0x00000D55
+  GL_DEPTH_BITS* = 0x00000D56
+  GL_STENCIL_BITS* = 0x00000D57
+  GL_ACCUM_RED_BITS* = 0x00000D58
+  GL_ACCUM_GREEN_BITS* = 0x00000D59
+  GL_ACCUM_BLUE_BITS* = 0x00000D5A
+  GL_ACCUM_ALPHA_BITS* = 0x00000D5B
+  GL_NAME_STACK_DEPTH* = 0x00000D70
+  GL_AUTO_NORMAL* = 0x00000D80
+  GL_MAP1_COLOR_4* = 0x00000D90
+  GL_MAP1_INDEX* = 0x00000D91
+  GL_MAP1_NORMAL* = 0x00000D92
+  GL_MAP1_TEXTURE_COORD_1* = 0x00000D93
+  GL_MAP1_TEXTURE_COORD_2* = 0x00000D94
+  GL_MAP1_TEXTURE_COORD_3* = 0x00000D95
+  GL_MAP1_TEXTURE_COORD_4* = 0x00000D96
+  GL_MAP1_VERTEX_3* = 0x00000D97
+  GL_MAP1_VERTEX_4* = 0x00000D98
+  GL_MAP2_COLOR_4* = 0x00000DB0
+  GL_MAP2_INDEX* = 0x00000DB1
+  GL_MAP2_NORMAL* = 0x00000DB2
+  GL_MAP2_TEXTURE_COORD_1* = 0x00000DB3
+  GL_MAP2_TEXTURE_COORD_2* = 0x00000DB4
+  GL_MAP2_TEXTURE_COORD_3* = 0x00000DB5
+  GL_MAP2_TEXTURE_COORD_4* = 0x00000DB6
+  GL_MAP2_VERTEX_3* = 0x00000DB7
+  GL_MAP2_VERTEX_4* = 0x00000DB8
+  GL_MAP1_GRID_DOMAIN* = 0x00000DD0
+  GL_MAP1_GRID_SEGMENTS* = 0x00000DD1
+  GL_MAP2_GRID_DOMAIN* = 0x00000DD2
+  GL_MAP2_GRID_SEGMENTS* = 0x00000DD3
+  GL_TEXTURE_1D* = 0x00000DE0
+  GL_TEXTURE_2D* = 0x00000DE1
+  GL_FEEDBACK_BUFFER_POINTER* = 0x00000DF0
+  GL_FEEDBACK_BUFFER_SIZE* = 0x00000DF1
+  GL_FEEDBACK_BUFFER_TYPE* = 0x00000DF2
+  GL_SELECTION_BUFFER_POINTER* = 0x00000DF3
+  GL_SELECTION_BUFFER_SIZE* = 0x00000DF4 #      GL_TEXTURE_BINDING_1D
+                                         #      GL_TEXTURE_BINDING_2D
+                                         #      GL_VERTEX_ARRAY
+                                         #      GL_NORMAL_ARRAY
+                                         #      GL_COLOR_ARRAY
+                                         #      GL_INDEX_ARRAY
+                                         #      GL_TEXTURE_COORD_ARRAY
+                                         #      GL_EDGE_FLAG_ARRAY
+                                         #      GL_VERTEX_ARRAY_SIZE
+                                         #      GL_VERTEX_ARRAY_TYPE
+                                         #      GL_VERTEX_ARRAY_STRIDE
+                                         #      GL_NORMAL_ARRAY_TYPE
+                                         #      GL_NORMAL_ARRAY_STRIDE
+                                         #      GL_COLOR_ARRAY_SIZE
+                                         #      GL_COLOR_ARRAY_TYPE
+                                         #      GL_COLOR_ARRAY_STRIDE
+                                         #      GL_INDEX_ARRAY_TYPE
+                                         #      GL_INDEX_ARRAY_STRIDE
+                                         #      GL_TEXTURE_COORD_ARRAY_SIZE
+                                         #      GL_TEXTURE_COORD_ARRAY_TYPE
+                                         #      GL_TEXTURE_COORD_ARRAY_STRIDE
+                                         #      GL_EDGE_FLAG_ARRAY_STRIDE
+                                         #      GL_POLYGON_OFFSET_FACTOR
+                                         #      GL_POLYGON_OFFSET_UNITS
+                                         # GetTextureParameter
+                                         #      GL_TEXTURE_MAG_FILTER
+                                         #      GL_TEXTURE_MIN_FILTER
+                                         #      GL_TEXTURE_WRAP_S
+                                         #      GL_TEXTURE_WRAP_T
+  GL_TEXTURE_WIDTH* = 0x00001000
+  GL_TEXTURE_HEIGHT* = 0x00001001
+  GL_TEXTURE_INTERNAL_FORMAT* = 0x00001003
+  GL_TEXTURE_BORDER_COLOR* = 0x00001004
+  GL_TEXTURE_BORDER* = 0x00001005 #      GL_TEXTURE_RED_SIZE
+                                  #      GL_TEXTURE_GREEN_SIZE
+                                  #      GL_TEXTURE_BLUE_SIZE
+                                  #      GL_TEXTURE_ALPHA_SIZE
+                                  #      GL_TEXTURE_LUMINANCE_SIZE
+                                  #      GL_TEXTURE_INTENSITY_SIZE
+                                  #      GL_TEXTURE_PRIORITY
+                                  #      GL_TEXTURE_RESIDENT
+                                  # HintMode
+  GL_DONT_CARE* = 0x00001100
+  GL_FASTEST* = 0x00001101
+  GL_NICEST* = 0x00001102     # HintTarget
+                              #      GL_PERSPECTIVE_CORRECTION_HINT
+                              #      GL_POINT_SMOOTH_HINT
+                              #      GL_LINE_SMOOTH_HINT
+                              #      GL_POLYGON_SMOOTH_HINT
+                              #      GL_FOG_HINT
+                              # IndexPointerType
+                              #      GL_SHORT
+                              #      GL_INT
+                              #      GL_FLOAT
+                              #      GL_DOUBLE
+                              # LightModelParameter
+                              #      GL_LIGHT_MODEL_AMBIENT
+                              #      GL_LIGHT_MODEL_LOCAL_VIEWER
+                              #      GL_LIGHT_MODEL_TWO_SIDE
+                              # LightName
+  GL_LIGHT0* = 0x00004000
+  GL_LIGHT1* = 0x00004001
+  GL_LIGHT2* = 0x00004002
+  GL_LIGHT3* = 0x00004003
+  GL_LIGHT4* = 0x00004004
+  GL_LIGHT5* = 0x00004005
+  GL_LIGHT6* = 0x00004006
+  GL_LIGHT7* = 0x00004007     # LightParameter
+  GL_AMBIENT* = 0x00001200
+  GL_DIFFUSE* = 0x00001201
+  GL_SPECULAR* = 0x00001202
+  GL_POSITION* = 0x00001203
+  GL_SPOT_DIRECTION* = 0x00001204
+  GL_SPOT_EXPONENT* = 0x00001205
+  GL_SPOT_CUTOFF* = 0x00001206
+  GL_CONSTANT_ATTENUATION* = 0x00001207
+  GL_LINEAR_ATTENUATION* = 0x00001208
+  GL_QUADRATIC_ATTENUATION* = 0x00001209 # InterleavedArrays
+                                         #      GL_V2F
+                                         #      GL_V3F
+                                         #      GL_C4UB_V2F
+                                         #      GL_C4UB_V3F
+                                         #      GL_C3F_V3F
+                                         #      GL_N3F_V3F
+                                         #      GL_C4F_N3F_V3F
+                                         #      GL_T2F_V3F
+                                         #      GL_T4F_V4F
+                                         #      GL_T2F_C4UB_V3F
+                                         #      GL_T2F_C3F_V3F
+                                         #      GL_T2F_N3F_V3F
+                                         #      GL_T2F_C4F_N3F_V3F
+                                         #      GL_T4F_C4F_N3F_V4F
+                                         # ListMode
+  GL_COMPILE* = 0x00001300
+  GL_COMPILE_AND_EXECUTE* = 0x00001301 # ListNameType
+                                       #      GL_BYTE
+                                       #      GL_UNSIGNED_BYTE
+                                       #      GL_SHORT
+                                       #      GL_UNSIGNED_SHORT
+                                       #      GL_INT
+                                       #      GL_UNSIGNED_INT
+                                       #      GL_FLOAT
+                                       #      GL_2_BYTES
+                                       #      GL_3_BYTES
+                                       #      GL_4_BYTES
+                                       # LogicOp
+  constGL_CLEAR* = 0x00001500
+  GL_AND* = 0x00001501
+  GL_AND_REVERSE* = 0x00001502
+  GL_COPY* = 0x00001503
+  GL_AND_INVERTED* = 0x00001504
+  GL_NOOP* = 0x00001505
+  GL_XOR* = 0x00001506
+  GL_OR* = 0x00001507
+  GL_NOR* = 0x00001508
+  GL_EQUIV* = 0x00001509
+  GL_INVERT* = 0x0000150A
+  GL_OR_REVERSE* = 0x0000150B
+  GL_COPY_INVERTED* = 0x0000150C
+  GL_OR_INVERTED* = 0x0000150D
+  GL_NAND* = 0x0000150E
+  GL_SET* = 0x0000150F        # MapTarget
+                              #      GL_MAP1_COLOR_4
+                              #      GL_MAP1_INDEX
+                              #      GL_MAP1_NORMAL
+                              #      GL_MAP1_TEXTURE_COORD_1
+                              #      GL_MAP1_TEXTURE_COORD_2
+                              #      GL_MAP1_TEXTURE_COORD_3
+                              #      GL_MAP1_TEXTURE_COORD_4
+                              #      GL_MAP1_VERTEX_3
+                              #      GL_MAP1_VERTEX_4
+                              #      GL_MAP2_COLOR_4
+                              #      GL_MAP2_INDEX
+                              #      GL_MAP2_NORMAL
+                              #      GL_MAP2_TEXTURE_COORD_1
+                              #      GL_MAP2_TEXTURE_COORD_2
+                              #      GL_MAP2_TEXTURE_COORD_3
+                              #      GL_MAP2_TEXTURE_COORD_4
+                              #      GL_MAP2_VERTEX_3
+                              #      GL_MAP2_VERTEX_4
+                              # MaterialFace
+                              #      GL_FRONT
+                              #      GL_BACK
+                              #      GL_FRONT_AND_BACK
+                              # MaterialParameter
+  GL_EMISSION* = 0x00001600
+  GL_SHININESS* = 0x00001601
+  GL_AMBIENT_AND_DIFFUSE* = 0x00001602
+  GL_COLOR_INDEXES* = 0x00001603 #      GL_AMBIENT
+                                 #      GL_DIFFUSE
+                                 #      GL_SPECULAR
+                                 # MatrixMode
+  GL_MODELVIEW* = 0x00001700
+  GL_PROJECTION* = 0x00001701
+  GL_TEXTURE* = 0x00001702    # MeshMode1
+                              #      GL_POINT
+                              #      GL_LINE
+                              # MeshMode2
+                              #      GL_POINT
+                              #      GL_LINE
+                              #      GL_FILL
+                              # NormalPointerType
+                              #      GL_BYTE
+                              #      GL_SHORT
+                              #      GL_INT
+                              #      GL_FLOAT
+                              #      GL_DOUBLE
+                              # PixelCopyType
+  GL_COLOR* = 0x00001800
+  GL_DEPTH* = 0x00001801
+  GL_STENCIL* = 0x00001802    # PixelFormat
+  GL_COLOR_INDEX* = 0x00001900
+  GL_STENCIL_INDEX* = 0x00001901
+  GL_DEPTH_COMPONENT* = 0x00001902
+  GL_RED* = 0x00001903
+  GL_GREEN* = 0x00001904
+  GL_BLUE* = 0x00001905
+  GL_ALPHA* = 0x00001906
+  GL_RGB* = 0x00001907
+  GL_RGBA* = 0x00001908
+  GL_LUMINANCE* = 0x00001909
+  GL_LUMINANCE_ALPHA* = 0x0000190A # PixelMap
+                                   #      GL_PIXEL_MAP_I_TO_I
+                                   #      GL_PIXEL_MAP_S_TO_S
+                                   #      GL_PIXEL_MAP_I_TO_R
+                                   #      GL_PIXEL_MAP_I_TO_G
+                                   #      GL_PIXEL_MAP_I_TO_B
+                                   #      GL_PIXEL_MAP_I_TO_A
+                                   #      GL_PIXEL_MAP_R_TO_R
+                                   #      GL_PIXEL_MAP_G_TO_G
+                                   #      GL_PIXEL_MAP_B_TO_B
+                                   #      GL_PIXEL_MAP_A_TO_A
+                                   # PixelStore
+                                   #      GL_UNPACK_SWAP_BYTES
+                                   #      GL_UNPACK_LSB_FIRST
+                                   #      GL_UNPACK_ROW_LENGTH
+                                   #      GL_UNPACK_SKIP_ROWS
+                                   #      GL_UNPACK_SKIP_PIXELS
+                                   #      GL_UNPACK_ALIGNMENT
+                                   #      GL_PACK_SWAP_BYTES
+                                   #      GL_PACK_LSB_FIRST
+                                   #      GL_PACK_ROW_LENGTH
+                                   #      GL_PACK_SKIP_ROWS
+                                   #      GL_PACK_SKIP_PIXELS
+                                   #      GL_PACK_ALIGNMENT
+                                   # PixelTransfer
+                                   #      GL_MAP_COLOR
+                                   #      GL_MAP_STENCIL
+                                   #      GL_INDEX_SHIFT
+                                   #      GL_INDEX_OFFSET
+                                   #      GL_RED_SCALE
+                                   #      GL_RED_BIAS
+                                   #      GL_GREEN_SCALE
+                                   #      GL_GREEN_BIAS
+                                   #      GL_BLUE_SCALE
+                                   #      GL_BLUE_BIAS
+                                   #      GL_ALPHA_SCALE
+                                   #      GL_ALPHA_BIAS
+                                   #      GL_DEPTH_SCALE
+                                   #      GL_DEPTH_BIAS
+                                   # PixelType
+  constGL_BITMAP* = 0x00001A00
+  GL_POINT* = 0x00001B00
+  GL_LINE* = 0x00001B01
+  GL_FILL* = 0x00001B02       # ReadBufferMode
+                              #      GL_FRONT_LEFT
+                              #      GL_FRONT_RIGHT
+                              #      GL_BACK_LEFT
+                              #      GL_BACK_RIGHT
+                              #      GL_FRONT
+                              #      GL_BACK
+                              #      GL_LEFT
+                              #      GL_RIGHT
+                              #      GL_AUX0
+                              #      GL_AUX1
+                              #      GL_AUX2
+                              #      GL_AUX3
+                              # RenderingMode
+  GL_RENDER* = 0x00001C00
+  GL_FEEDBACK* = 0x00001C01
+  GL_SELECT* = 0x00001C02     # ShadingModel
+  GL_FLAT* = 0x00001D00
+  GL_SMOOTH* = 0x00001D01     # StencilFunction
+                              #      GL_NEVER
+                              #      GL_LESS
+                              #      GL_EQUAL
+                              #      GL_LEQUAL
+                              #      GL_GREATER
+                              #      GL_NOTEQUAL
+                              #      GL_GEQUAL
+                              #      GL_ALWAYS
+                              # StencilOp
+                              #      GL_ZERO
+  GL_KEEP* = 0x00001E00
+  GL_REPLACE* = 0x00001E01
+  GL_INCR* = 0x00001E02
+  GL_DECR* = 0x00001E03       #      GL_INVERT
+                              # StringName
+  GL_VENDOR* = 0x00001F00
+  GL_RENDERER* = 0x00001F01
+  GL_VERSION* = 0x00001F02
+  GL_EXTENSIONS* = 0x00001F03 # TextureCoordName
+  GL_S* = 0x00002000
+  GL_T* = 0x00002001
+  GL_R* = 0x00002002
+  GL_Q* = 0x00002003          # TexCoordPointerType
+                              #      GL_SHORT
+                              #      GL_INT
+                              #      GL_FLOAT
+                              #      GL_DOUBLE
+                              # TextureEnvMode
+  GL_MODULATE* = 0x00002100
+  GL_DECAL* = 0x00002101      #      GL_BLEND
+                              #      GL_REPLACE
+                              # TextureEnvParameter
+  GL_TEXTURE_ENV_MODE* = 0x00002200
+  GL_TEXTURE_ENV_COLOR* = 0x00002201 # TextureEnvTarget
+  GL_TEXTURE_ENV* = 0x00002300 # TextureGenMode
+  GL_EYE_LINEAR* = 0x00002400
+  GL_OBJECT_LINEAR* = 0x00002401
+  GL_SPHERE_MAP* = 0x00002402 # TextureGenParameter
+  GL_TEXTURE_GEN_MODE* = 0x00002500
+  GL_OBJECT_PLANE* = 0x00002501
+  GL_EYE_PLANE* = 0x00002502  # TextureMagFilter
+  GL_NEAREST* = 0x00002600
+  GL_LINEAR* = 0x00002601     # TextureMinFilter
+                              #      GL_NEAREST
+                              #      GL_LINEAR
+  GL_NEAREST_MIPMAP_NEAREST* = 0x00002700
+  GL_LINEAR_MIPMAP_NEAREST* = 0x00002701
+  GL_NEAREST_MIPMAP_LINEAR* = 0x00002702
+  GL_LINEAR_MIPMAP_LINEAR* = 0x00002703 # TextureParameterName
+  GL_TEXTURE_MAG_FILTER* = 0x00002800
+  GL_TEXTURE_MIN_FILTER* = 0x00002801
+  GL_TEXTURE_WRAP_S* = 0x00002802
+  GL_TEXTURE_WRAP_T* = 0x00002803 #      GL_TEXTURE_BORDER_COLOR
+                                  #      GL_TEXTURE_PRIORITY
+                                  # TextureTarget
+                                  #      GL_TEXTURE_1D
+                                  #      GL_TEXTURE_2D
+                                  #      GL_PROXY_TEXTURE_1D
+                                  #      GL_PROXY_TEXTURE_2D
+                                  # TextureWrapMode
+  GL_CLAMP* = 0x00002900
+  GL_REPEAT* = 0x00002901     # VertexPointerType
+                              #      GL_SHORT
+                              #      GL_INT
+                              #      GL_FLOAT
+                              #      GL_DOUBLE
+                              # ClientAttribMask
+  GL_CLIENT_PIXEL_STORE_BIT* = 0x00000001
+  GL_CLIENT_VERTEX_ARRAY_BIT* = 0x00000002
+  GL_CLIENT_ALL_ATTRIB_BITS* = 0xFFFFFFFF # polygon_offset
+  GL_POLYGON_OFFSET_FACTOR* = 0x00008038
+  GL_POLYGON_OFFSET_UNITS* = 0x00002A00
+  GL_POLYGON_OFFSET_POINT* = 0x00002A01
+  GL_POLYGON_OFFSET_LINE* = 0x00002A02
+  GL_POLYGON_OFFSET_FILL* = 0x00008037 # texture
+  GL_ALPHA4* = 0x0000803B
+  GL_ALPHA8* = 0x0000803C
+  GL_ALPHA12* = 0x0000803D
+  GL_ALPHA16* = 0x0000803E
+  GL_LUMINANCE4* = 0x0000803F
+  GL_LUMINANCE8* = 0x00008040
+  GL_LUMINANCE12* = 0x00008041
+  GL_LUMINANCE16* = 0x00008042
+  GL_LUMINANCE4_ALPHA4* = 0x00008043
+  GL_LUMINANCE6_ALPHA2* = 0x00008044
+  GL_LUMINANCE8_ALPHA8* = 0x00008045
+  GL_LUMINANCE12_ALPHA4* = 0x00008046
+  GL_LUMINANCE12_ALPHA12* = 0x00008047
+  GL_LUMINANCE16_ALPHA16* = 0x00008048
+  GL_INTENSITY* = 0x00008049
+  GL_INTENSITY4* = 0x0000804A
+  GL_INTENSITY8* = 0x0000804B
+  GL_INTENSITY12* = 0x0000804C
+  GL_INTENSITY16* = 0x0000804D
+  GL_R3_G3_B2* = 0x00002A10
+  GL_RGB4* = 0x0000804F
+  GL_RGB5* = 0x00008050
+  GL_RGB8* = 0x00008051
+  GL_RGB10* = 0x00008052
+  GL_RGB12* = 0x00008053
+  GL_RGB16* = 0x00008054
+  GL_RGBA2* = 0x00008055
+  GL_RGBA4* = 0x00008056
+  GL_RGB5_A1* = 0x00008057
+  GL_RGBA8* = 0x00008058
+  GL_RGB10_A2* = 0x00008059
+  GL_RGBA12* = 0x0000805A
+  GL_RGBA16* = 0x0000805B
+  GL_TEXTURE_RED_SIZE* = 0x0000805C
+  GL_TEXTURE_GREEN_SIZE* = 0x0000805D
+  GL_TEXTURE_BLUE_SIZE* = 0x0000805E
+  GL_TEXTURE_ALPHA_SIZE* = 0x0000805F
+  GL_TEXTURE_LUMINANCE_SIZE* = 0x00008060
+  GL_TEXTURE_INTENSITY_SIZE* = 0x00008061
+  GL_PROXY_TEXTURE_1D* = 0x00008063
+  GL_PROXY_TEXTURE_2D* = 0x00008064 # texture_object
+  GL_TEXTURE_PRIORITY* = 0x00008066
+  GL_TEXTURE_RESIDENT* = 0x00008067
+  GL_TEXTURE_BINDING_1D* = 0x00008068
+  GL_TEXTURE_BINDING_2D* = 0x00008069 # vertex_array
+  GL_VERTEX_ARRAY* = 0x00008074
+  GL_NORMAL_ARRAY* = 0x00008075
+  GL_COLOR_ARRAY* = 0x00008076
+  GL_INDEX_ARRAY* = 0x00008077
+  GL_TEXTURE_COORD_ARRAY* = 0x00008078
+  GL_EDGE_FLAG_ARRAY* = 0x00008079
+  GL_VERTEX_ARRAY_SIZE* = 0x0000807A
+  GL_VERTEX_ARRAY_TYPE* = 0x0000807B
+  GL_VERTEX_ARRAY_STRIDE* = 0x0000807C
+  GL_NORMAL_ARRAY_TYPE* = 0x0000807E
+  GL_NORMAL_ARRAY_STRIDE* = 0x0000807F
+  GL_COLOR_ARRAY_SIZE* = 0x00008081
+  GL_COLOR_ARRAY_TYPE* = 0x00008082
+  GL_COLOR_ARRAY_STRIDE* = 0x00008083
+  GL_INDEX_ARRAY_TYPE* = 0x00008085
+  GL_INDEX_ARRAY_STRIDE* = 0x00008086
+  GL_TEXTURE_COORD_ARRAY_SIZE* = 0x00008088
+  GL_TEXTURE_COORD_ARRAY_TYPE* = 0x00008089
+  GL_TEXTURE_COORD_ARRAY_STRIDE* = 0x0000808A
+  GL_EDGE_FLAG_ARRAY_STRIDE* = 0x0000808C
+  GL_VERTEX_ARRAY_POINTER* = 0x0000808E
+  GL_NORMAL_ARRAY_POINTER* = 0x0000808F
+  GL_COLOR_ARRAY_POINTER* = 0x00008090
+  GL_INDEX_ARRAY_POINTER* = 0x00008091
+  GL_TEXTURE_COORD_ARRAY_POINTER* = 0x00008092
+  GL_EDGE_FLAG_ARRAY_POINTER* = 0x00008093
+  GL_V2F* = 0x00002A20
+  GL_V3F* = 0x00002A21
+  GL_C4UB_V2F* = 0x00002A22
+  GL_C4UB_V3F* = 0x00002A23
+  GL_C3F_V3F* = 0x00002A24
+  GL_N3F_V3F* = 0x00002A25
+  GL_C4F_N3F_V3F* = 0x00002A26
+  GL_T2F_V3F* = 0x00002A27
+  GL_T4F_V4F* = 0x00002A28
+  GL_T2F_C4UB_V3F* = 0x00002A29
+  GL_T2F_C3F_V3F* = 0x00002A2A
+  GL_T2F_N3F_V3F* = 0x00002A2B
+  GL_T2F_C4F_N3F_V3F* = 0x00002A2C
+  GL_T4F_C4F_N3F_V4F* = 0x00002A2D # Extensions
+  GL_EXT_vertex_array* = 1
+  GL_WIN_swap_hint* = 1
+  GL_EXT_bgra* = 1
+  GL_EXT_paletted_texture* = 1 # EXT_vertex_array
+  GL_VERTEX_ARRAY_EXT* = 0x00008074
+  GL_NORMAL_ARRAY_EXT* = 0x00008075
+  GL_COLOR_ARRAY_EXT* = 0x00008076
+  GL_INDEX_ARRAY_EXT* = 0x00008077
+  GL_TEXTURE_COORD_ARRAY_EXT* = 0x00008078
+  GL_EDGE_FLAG_ARRAY_EXT* = 0x00008079
+  GL_VERTEX_ARRAY_SIZE_EXT* = 0x0000807A
+  GL_VERTEX_ARRAY_TYPE_EXT* = 0x0000807B
+  GL_VERTEX_ARRAY_STRIDE_EXT* = 0x0000807C
+  GL_VERTEX_ARRAY_COUNT_EXT* = 0x0000807D
+  GL_NORMAL_ARRAY_TYPE_EXT* = 0x0000807E
+  GL_NORMAL_ARRAY_STRIDE_EXT* = 0x0000807F
+  GL_NORMAL_ARRAY_COUNT_EXT* = 0x00008080
+  GL_COLOR_ARRAY_SIZE_EXT* = 0x00008081
+  GL_COLOR_ARRAY_TYPE_EXT* = 0x00008082
+  GL_COLOR_ARRAY_STRIDE_EXT* = 0x00008083
+  GL_COLOR_ARRAY_COUNT_EXT* = 0x00008084
+  GL_INDEX_ARRAY_TYPE_EXT* = 0x00008085
+  GL_INDEX_ARRAY_STRIDE_EXT* = 0x00008086
+  GL_INDEX_ARRAY_COUNT_EXT* = 0x00008087
+  GL_TEXTURE_COORD_ARRAY_SIZE_EXT* = 0x00008088
+  GL_TEXTURE_COORD_ARRAY_TYPE_EXT* = 0x00008089
+  GL_TEXTURE_COORD_ARRAY_STRIDE_EXT* = 0x0000808A
+  GL_TEXTURE_COORD_ARRAY_COUNT_EXT* = 0x0000808B
+  GL_EDGE_FLAG_ARRAY_STRIDE_EXT* = 0x0000808C
+  GL_EDGE_FLAG_ARRAY_COUNT_EXT* = 0x0000808D
+  GL_VERTEX_ARRAY_POINTER_EXT* = 0x0000808E
+  GL_NORMAL_ARRAY_POINTER_EXT* = 0x0000808F
+  GL_COLOR_ARRAY_POINTER_EXT* = 0x00008090
+  GL_INDEX_ARRAY_POINTER_EXT* = 0x00008091
+  GL_TEXTURE_COORD_ARRAY_POINTER_EXT* = 0x00008092
+  GL_EDGE_FLAG_ARRAY_POINTER_EXT* = 0x00008093
+  GL_DOUBLE_EXT* = GL_DOUBLE  # EXT_bgra
+  GL_BGR_EXT* = 0x000080E0
+  GL_BGRA_EXT* = 0x000080E1   # EXT_paletted_texture
+                              # These must match the GL_COLOR_TABLE_*_SGI enumerants
+  GL_COLOR_TABLE_FORMAT_EXT* = 0x000080D8
+  GL_COLOR_TABLE_WIDTH_EXT* = 0x000080D9
+  GL_COLOR_TABLE_RED_SIZE_EXT* = 0x000080DA
+  GL_COLOR_TABLE_GREEN_SIZE_EXT* = 0x000080DB
+  GL_COLOR_TABLE_BLUE_SIZE_EXT* = 0x000080DC
+  GL_COLOR_TABLE_ALPHA_SIZE_EXT* = 0x000080DD
+  GL_COLOR_TABLE_LUMINANCE_SIZE_EXT* = 0x000080DE
+  GL_COLOR_TABLE_INTENSITY_SIZE_EXT* = 0x000080DF
+  GL_COLOR_INDEX1_EXT* = 0x000080E2
+  GL_COLOR_INDEX2_EXT* = 0x000080E3
+  GL_COLOR_INDEX4_EXT* = 0x000080E4
+  GL_COLOR_INDEX8_EXT* = 0x000080E5
+  GL_COLOR_INDEX12_EXT* = 0x000080E6
+  GL_COLOR_INDEX16_EXT* = 0x000080E7 # For compatibility with OpenGL v1.0
+  constGL_LOGIC_OP* = GL_INDEX_LOGIC_OP
+  GL_TEXTURE_COMPONENTS* = GL_TEXTURE_INTERNAL_FORMAT
+
+proc glAccum*(op: TGLenum, value: TGLfloat){.dynlib: dllname, importc: "glAccum".}
+proc glAlphaFunc*(func: TGLenum, theref: TGLclampf){.dynlib: dllname, 
+    importc: "glAlphaFunc".}
+proc glAreTexturesResident*(n: TGLsizei, textures: PGLuint, 
+                            residences: PGLboolean): TGLboolean{.
+    dynlib: dllname, importc: "glAreTexturesResident".}
+proc glArrayElement*(i: TGLint){.dynlib: dllname, importc: "glArrayElement".}
+proc glBegin*(mode: TGLenum){.dynlib: dllname, importc: "glBegin".}
+proc glBindTexture*(target: TGLenum, texture: TGLuint){.dynlib: dllname, 
+    importc: "glBindTexture".}
+proc glBitmap*(width, height: TGLsizei, xorig, yorig: TGLfloat, 
+               xmove, ymove: TGLfloat, bitmap: PGLubyte){.dynlib: dllname, 
+    importc: "glBitmap".}
+proc glBlendFunc*(sfactor, dfactor: TGLenum){.dynlib: dllname, 
+    importc: "glBlendFunc".}
+proc glCallList*(list: TGLuint){.dynlib: dllname, importc: "glCallList".}
+proc glCallLists*(n: TGLsizei, atype: TGLenum, lists: Pointer){.dynlib: dllname, 
+    importc: "glCallLists".}
+proc glClear*(mask: TGLbitfield){.dynlib: dllname, importc: "glClear".}
+proc glClearAccum*(red, green, blue, alpha: TGLfloat){.dynlib: dllname, 
+    importc: "glClearAccum".}
+proc glClearColor*(red, green, blue, alpha: TGLclampf){.dynlib: dllname, 
+    importc: "glClearColor".}
+proc glClearDepth*(depth: TGLclampd){.dynlib: dllname, importc: "glClearDepth".}
+proc glClearIndex*(c: TGLfloat){.dynlib: dllname, importc: "glClearIndex".}
+proc glClearStencil*(s: TGLint){.dynlib: dllname, importc: "glClearStencil".}
+proc glClipPlane*(plane: TGLenum, equation: PGLdouble){.dynlib: dllname, 
+    importc: "glClipPlane".}
+proc glColor3b*(red, green, blue: TGlbyte){.dynlib: dllname, 
+    importc: "glColor3b".}
+proc glColor3bv*(v: PGLbyte){.dynlib: dllname, importc: "glColor3bv".}
+proc glColor3d*(red, green, blue: TGLdouble){.dynlib: dllname, 
+    importc: "glColor3d".}
+proc glColor3dv*(v: PGLdouble){.dynlib: dllname, importc: "glColor3dv".}
+proc glColor3f*(red, green, blue: TGLfloat){.dynlib: dllname, 
+    importc: "glColor3f".}
+proc glColor3fv*(v: PGLfloat){.dynlib: dllname, importc: "glColor3fv".}
+proc glColor3i*(red, green, blue: TGLint){.dynlib: dllname, importc: "glColor3i".}
+proc glColor3iv*(v: PGLint){.dynlib: dllname, importc: "glColor3iv".}
+proc glColor3s*(red, green, blue: TGLshort){.dynlib: dllname, 
+    importc: "glColor3s".}
+proc glColor3sv*(v: PGLshort){.dynlib: dllname, importc: "glColor3sv".}
+proc glColor3ub*(red, green, blue: TGLubyte){.dynlib: dllname, 
+    importc: "glColor3ub".}
+proc glColor3ubv*(v: PGLubyte){.dynlib: dllname, importc: "glColor3ubv".}
+proc glColor3ui*(red, green, blue: TGLuint){.dynlib: dllname, 
+    importc: "glColor3ui".}
+proc glColor3uiv*(v: PGLuint){.dynlib: dllname, importc: "glColor3uiv".}
+proc glColor3us*(red, green, blue: TGLushort){.dynlib: dllname, 
+    importc: "glColor3us".}
+proc glColor3usv*(v: PGLushort){.dynlib: dllname, importc: "glColor3usv".}
+proc glColor4b*(red, green, blue, alpha: TGlbyte){.dynlib: dllname, 
+    importc: "glColor4b".}
+proc glColor4bv*(v: PGLbyte){.dynlib: dllname, importc: "glColor4bv".}
+proc glColor4d*(red, green, blue, alpha: TGLdouble){.dynlib: dllname, 
+    importc: "glColor4d".}
+proc glColor4dv*(v: PGLdouble){.dynlib: dllname, importc: "glColor4dv".}
+proc glColor4f*(red, green, blue, alpha: TGLfloat){.dynlib: dllname, 
+    importc: "glColor4f".}
+proc glColor4fv*(v: PGLfloat){.dynlib: dllname, importc: "glColor4fv".}
+proc glColor4i*(red, green, blue, alpha: TGLint){.dynlib: dllname, 
+    importc: "glColor4i".}
+proc glColor4iv*(v: PGLint){.dynlib: dllname, importc: "glColor4iv".}
+proc glColor4s*(red, green, blue, alpha: TGLshort){.dynlib: dllname, 
+    importc: "glColor4s".}
+proc glColor4sv*(v: PGLshort){.dynlib: dllname, importc: "glColor4sv".}
+proc glColor4ub*(red, green, blue, alpha: TGLubyte){.dynlib: dllname, 
+    importc: "glColor4ub".}
+proc glColor4ubv*(v: PGLubyte){.dynlib: dllname, importc: "glColor4ubv".}
+proc glColor4ui*(red, green, blue, alpha: TGLuint){.dynlib: dllname, 
+    importc: "glColor4ui".}
+proc glColor4uiv*(v: PGLuint){.dynlib: dllname, importc: "glColor4uiv".}
+proc glColor4us*(red, green, blue, alpha: TGLushort){.dynlib: dllname, 
+    importc: "glColor4us".}
+proc glColor4usv*(v: PGLushort){.dynlib: dllname, importc: "glColor4usv".}
+proc glColorMask*(red, green, blue, alpha: TGLboolean){.dynlib: dllname, 
+    importc: "glColorMask".}
+proc glColorMaterial*(face, mode: TGLenum){.dynlib: dllname, 
+    importc: "glColorMaterial".}
+proc glColorPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, 
+                     pointer: Pointer){.dynlib: dllname, 
+                                        importc: "glColorPointer".}
+proc glCopyPixels*(x, y: TGLint, width, height: TGLsizei, atype: TGLenum){.
+    dynlib: dllname, importc: "glCopyPixels".}
+proc glCopyTexImage1D*(target: TGLenum, level: TGLint, internalFormat: TGLenum, 
+                       x, y: TGLint, width: TGLsizei, border: TGLint){.
+    dynlib: dllname, importc: "glCopyTexImage1D".}
+proc glCopyTexImage2D*(target: TGLenum, level: TGLint, internalFormat: TGLenum, 
+                       x, y: TGLint, width, height: TGLsizei, border: TGLint){.
+    dynlib: dllname, importc: "glCopyTexImage2D".}
+proc glCopyTexSubImage1D*(target: TGLenum, level, xoffset, x, y: TGLint, 
+                          width: TGLsizei){.dynlib: dllname, 
+    importc: "glCopyTexSubImage1D".}
+proc glCopyTexSubImage2D*(target: TGLenum, 
+                          level, xoffset, yoffset, x, y: TGLint, 
+                          width, height: TGLsizei){.dynlib: dllname, 
+    importc: "glCopyTexSubImage2D".}
+proc glCullFace*(mode: TGLenum){.dynlib: dllname, importc: "glCullFace".}
+proc glDeleteLists*(list: TGLuint, range: TGLsizei){.dynlib: dllname, 
+    importc: "glDeleteLists".}
+proc glDeleteTextures*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteTextures".}
+proc glDepthFunc*(func: TGLenum){.dynlib: dllname, importc: "glDepthFunc".}
+proc glDepthMask*(flag: TGLboolean){.dynlib: dllname, importc: "glDepthMask".}
+proc glDepthRange*(zNear, zFar: TGLclampd){.dynlib: dllname, 
+    importc: "glDepthRange".}
+proc glDisable*(cap: TGLenum){.dynlib: dllname, importc: "glDisable".}
+proc glDisableClientState*(aarray: TGLenum){.dynlib: dllname, 
+    importc: "glDisableClientState".}
+proc glDrawArrays*(mode: TGLenum, first: TGLint, count: TGLsizei){.
+    dynlib: dllname, importc: "glDrawArrays".}
+proc glDrawBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glDrawBuffer".}
+proc glDrawElements*(mode: TGLenum, count: TGLsizei, atype: TGLenum, 
+                     indices: Pointer){.dynlib: dllname, 
+                                        importc: "glDrawElements".}
+proc glDrawPixels*(width, height: TGLsizei, format, atype: TGLenum, 
+                   pixels: Pointer){.dynlib: dllname, importc: "glDrawPixels".}
+proc glEdgeFlag*(flag: TGLboolean){.dynlib: dllname, importc: "glEdgeFlag".}
+proc glEdgeFlagPointer*(stride: TGLsizei, pointer: Pointer){.dynlib: dllname, 
+    importc: "glEdgeFlagPointer".}
+proc glEdgeFlagv*(flag: PGLboolean){.dynlib: dllname, importc: "glEdgeFlagv".}
+proc glEnable*(cap: TGLenum){.dynlib: dllname, importc: "glEnable".}
+proc glEnableClientState*(aarray: TGLenum){.dynlib: dllname, 
+    importc: "glEnableClientState".}
+proc glEnd*(){.dynlib: dllname, importc: "glEnd".}
+proc glEndList*(){.dynlib: dllname, importc: "glEndList".}
+proc glEvalCoord1d*(u: TGLdouble){.dynlib: dllname, importc: "glEvalCoord1d".}
+proc glEvalCoord1dv*(u: PGLdouble){.dynlib: dllname, importc: "glEvalCoord1dv".}
+proc glEvalCoord1f*(u: TGLfloat){.dynlib: dllname, importc: "glEvalCoord1f".}
+proc glEvalCoord1fv*(u: PGLfloat){.dynlib: dllname, importc: "glEvalCoord1fv".}
+proc glEvalCoord2d*(u, v: TGLdouble){.dynlib: dllname, importc: "glEvalCoord2d".}
+proc glEvalCoord2dv*(u: PGLdouble){.dynlib: dllname, importc: "glEvalCoord2dv".}
+proc glEvalCoord2f*(u, v: TGLfloat){.dynlib: dllname, importc: "glEvalCoord2f".}
+proc glEvalCoord2fv*(u: PGLfloat){.dynlib: dllname, importc: "glEvalCoord2fv".}
+proc glEvalMesh1*(mode: TGLenum, i1, i2: TGLint){.dynlib: dllname, 
+    importc: "glEvalMesh1".}
+proc glEvalMesh2*(mode: TGLenum, i1, i2, j1, j2: TGLint){.dynlib: dllname, 
+    importc: "glEvalMesh2".}
+proc glEvalPoint1*(i: TGLint){.dynlib: dllname, importc: "glEvalPoint1".}
+proc glEvalPoint2*(i, j: TGLint){.dynlib: dllname, importc: "glEvalPoint2".}
+proc glFeedbackBuffer*(size: TGLsizei, atype: TGLenum, buffer: PGLfloat){.
+    dynlib: dllname, importc: "glFeedbackBuffer".}
+proc glFinish*(){.dynlib: dllname, importc: "glFinish".}
+proc glFlush*(){.dynlib: dllname, importc: "glFlush".}
+proc glFogf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glFogf".}
+proc glFogfv*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glFogfv".}
+proc glFogi*(pname: TGLenum, param: TGLint){.dynlib: dllname, importc: "glFogi".}
+proc glFogiv*(pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glFogiv".}
+proc glFrontFace*(mode: TGLenum){.dynlib: dllname, importc: "glFrontFace".}
+proc glFrustum*(left, right, bottom, top, zNear, zFar: TGLdouble){.
+    dynlib: dllname, importc: "glFrustum".}
+proc glGenLists*(range: TGLsizei): TGLuint{.dynlib: dllname, 
+    importc: "glGenLists".}
+proc glGenTextures*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, 
+    importc: "glGenTextures".}
+proc glGetBooleanv*(pname: TGLenum, params: PGLboolean){.dynlib: dllname, 
+    importc: "glGetBooleanv".}
+proc glGetClipPlane*(plane: TGLenum, equation: PGLdouble){.dynlib: dllname, 
+    importc: "glGetClipPlane".}
+proc glGetDoublev*(pname: TGLenum, params: PGLdouble){.dynlib: dllname, 
+    importc: "glGetDoublev".}
+proc glGetError*(): TGLenum{.dynlib: dllname, importc: "glGetError".}
+proc glGetFloatv*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetFloatv".}
+proc glGetIntegerv*(pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glGetIntegerv".}
+proc glGetLightfv*(light, pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetLightfv".}
+proc glGetLightiv*(light, pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glGetLightiv".}
+proc glGetMapdv*(target, query: TGLenum, v: PGLdouble){.dynlib: dllname, 
+    importc: "glGetMapdv".}
+proc glGetMapfv*(target, query: TGLenum, v: PGLfloat){.dynlib: dllname, 
+    importc: "glGetMapfv".}
+proc glGetMapiv*(target, query: TGLenum, v: PGLint){.dynlib: dllname, 
+    importc: "glGetMapiv".}
+proc glGetMaterialfv*(face, pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetMaterialfv".}
+proc glGetMaterialiv*(face, pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glGetMaterialiv".}
+proc glGetPixelMapfv*(map: TGLenum, values: PGLfloat){.dynlib: dllname, 
+    importc: "glGetPixelMapfv".}
+proc glGetPixelMapuiv*(map: TGLenum, values: PGLuint){.dynlib: dllname, 
+    importc: "glGetPixelMapuiv".}
+proc glGetPixelMapusv*(map: TGLenum, values: PGLushort){.dynlib: dllname, 
+    importc: "glGetPixelMapusv".}
+proc glGetPointerv*(pname: TGLenum, params: Pointer){.dynlib: dllname, 
+    importc: "glGetPointerv".}
+proc glGetPolygonStipple*(mask: PGLubyte){.dynlib: dllname, 
+    importc: "glGetPolygonStipple".}
+proc glGetString*(name: TGLenum): cstring{.dynlib: dllname, 
+    importc: "glGetString".}
+proc glGetTexEnvfv*(target, pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetTexEnvfv".}
+proc glGetTexEnviv*(target, pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glGetTexEnviv".}
+proc glGetTexGendv*(coord, pname: TGLenum, params: PGLdouble){.dynlib: dllname, 
+    importc: "glGetTexGendv".}
+proc glGetTexGenfv*(coord, pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetTexGenfv".}
+proc glGetTexGeniv*(coord, pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glGetTexGeniv".}
+proc glGetTexImage*(target: TGLenum, level: TGLint, format: TGLenum, 
+                    atype: TGLenum, pixels: Pointer){.dynlib: dllname, 
+    importc: "glGetTexImage".}
+proc glGetTexLevelParameterfv*(target: TGLenum, level: TGLint, pname: TGLenum, 
+                               params: Pointer){.dynlib: dllname, 
+    importc: "glGetTexLevelParameterfv".}
+proc glGetTexLevelParameteriv*(target: TGLenum, level: TGLint, pname: TGLenum, 
+                               params: PGLint){.dynlib: dllname, 
+    importc: "glGetTexLevelParameteriv".}
+proc glGetTexParameterfv*(target, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetTexParameterfv".}
+proc glGetTexParameteriv*(target, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetTexParameteriv".}
+proc glHint*(target, mode: TGLenum){.dynlib: dllname, importc: "glHint".}
+proc glIndexMask*(mask: TGLuint){.dynlib: dllname, importc: "glIndexMask".}
+proc glIndexPointer*(atype: TGLenum, stride: TGLsizei, pointer: Pointer){.
+    dynlib: dllname, importc: "glIndexPointer".}
+proc glIndexd*(c: TGLdouble){.dynlib: dllname, importc: "glIndexd".}
+proc glIndexdv*(c: PGLdouble){.dynlib: dllname, importc: "glIndexdv".}
+proc glIndexf*(c: TGLfloat){.dynlib: dllname, importc: "glIndexf".}
+proc glIndexfv*(c: PGLfloat){.dynlib: dllname, importc: "glIndexfv".}
+proc glIndexi*(c: TGLint){.dynlib: dllname, importc: "glIndexi".}
+proc glIndexiv*(c: PGLint){.dynlib: dllname, importc: "glIndexiv".}
+proc glIndexs*(c: TGLshort){.dynlib: dllname, importc: "glIndexs".}
+proc glIndexsv*(c: PGLshort){.dynlib: dllname, importc: "glIndexsv".}
+proc glIndexub*(c: TGLubyte){.dynlib: dllname, importc: "glIndexub".}
+proc glIndexubv*(c: PGLubyte){.dynlib: dllname, importc: "glIndexubv".}
+proc glInitNames*(){.dynlib: dllname, importc: "glInitNames".}
+proc glInterleavedArrays*(format: TGLenum, stride: TGLsizei, pointer: Pointer){.
+    dynlib: dllname, importc: "glInterleavedArrays".}
+proc glIsEnabled*(cap: TGLenum): TGLboolean{.dynlib: dllname, 
+    importc: "glIsEnabled".}
+proc glIsList*(list: TGLuint): TGLboolean{.dynlib: dllname, importc: "glIsList".}
+proc glIsTexture*(texture: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsTexture".}
+proc glLightModelf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glLightModelf".}
+proc glLightModelfv*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glLightModelfv".}
+proc glLightModeli*(pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glLightModeli".}
+proc glLightModeliv*(pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glLightModeliv".}
+proc glLightf*(light, pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glLightf".}
+proc glLightfv*(light, pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glLightfv".}
+proc glLighti*(light, pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glLighti".}
+proc glLightiv*(light, pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glLightiv".}
+proc glLineStipple*(factor: TGLint, pattern: TGLushort){.dynlib: dllname, 
+    importc: "glLineStipple".}
+proc glLineWidth*(width: TGLfloat){.dynlib: dllname, importc: "glLineWidth".}
+proc glListBase*(base: TGLuint){.dynlib: dllname, importc: "glListBase".}
+proc glLoadIdentity*(){.dynlib: dllname, importc: "glLoadIdentity".}
+proc glLoadMatrixd*(m: PGLdouble){.dynlib: dllname, importc: "glLoadMatrixd".}
+proc glLoadMatrixf*(m: PGLfloat){.dynlib: dllname, importc: "glLoadMatrixf".}
+proc glLoadName*(name: TGLuint){.dynlib: dllname, importc: "glLoadName".}
+proc glLogicOp*(opcode: TGLenum){.dynlib: dllname, importc: "glLogicOp".}
+proc glMap1d*(target: TGLenum, u1, u2: TGLdouble, stride, order: TGLint, 
+              points: PGLdouble){.dynlib: dllname, importc: "glMap1d".}
+proc glMap1f*(target: TGLenum, u1, u2: TGLfloat, stride, order: TGLint, 
+              points: PGLfloat){.dynlib: dllname, importc: "glMap1f".}
+proc glMap2d*(target: TGLenum, u1, u2: TGLdouble, ustride, uorder: TGLint, 
+              v1, v2: TGLdouble, vstride, vorder: TGLint, points: PGLdouble){.
+    dynlib: dllname, importc: "glMap2d".}
+proc glMap2f*(target: TGLenum, u1, u2: TGLfloat, ustride, uorder: TGLint, 
+              v1, v2: TGLfloat, vstride, vorder: TGLint, points: PGLfloat){.
+    dynlib: dllname, importc: "glMap2f".}
+proc glMapGrid1d*(un: TGLint, u1, u2: TGLdouble){.dynlib: dllname, 
+    importc: "glMapGrid1d".}
+proc glMapGrid1f*(un: TGLint, u1, u2: TGLfloat){.dynlib: dllname, 
+    importc: "glMapGrid1f".}
+proc glMapGrid2d*(un: TGLint, u1, u2: TGLdouble, vn: TGLint, v1, v2: TGLdouble){.
+    dynlib: dllname, importc: "glMapGrid2d".}
+proc glMapGrid2f*(un: TGLint, u1, u2: TGLfloat, vn: TGLint, v1, v2: TGLfloat){.
+    dynlib: dllname, importc: "glMapGrid2f".}
+proc glMaterialf*(face, pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glMaterialf".}
+proc glMaterialfv*(face, pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glMaterialfv".}
+proc glMateriali*(face, pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glMateriali".}
+proc glMaterialiv*(face, pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glMaterialiv".}
+proc glMatrixMode*(mode: TGLenum){.dynlib: dllname, importc: "glMatrixMode".}
+proc glMultMatrixd*(m: PGLdouble){.dynlib: dllname, importc: "glMultMatrixd".}
+proc glMultMatrixf*(m: PGLfloat){.dynlib: dllname, importc: "glMultMatrixf".}
+proc glNewList*(list: TGLuint, mode: TGLenum){.dynlib: dllname, 
+    importc: "glNewList".}
+proc glNormal3b*(nx, ny, nz: TGlbyte){.dynlib: dllname, importc: "glNormal3b".}
+proc glNormal3bv*(v: PGLbyte){.dynlib: dllname, importc: "glNormal3bv".}
+proc glNormal3d*(nx, ny, nz: TGLdouble){.dynlib: dllname, importc: "glNormal3d".}
+proc glNormal3dv*(v: PGLdouble){.dynlib: dllname, importc: "glNormal3dv".}
+proc glNormal3f*(nx, ny, nz: TGLfloat){.dynlib: dllname, importc: "glNormal3f".}
+proc glNormal3fv*(v: PGLfloat){.dynlib: dllname, importc: "glNormal3fv".}
+proc glNormal3i*(nx, ny, nz: TGLint){.dynlib: dllname, importc: "glNormal3i".}
+proc glNormal3iv*(v: PGLint){.dynlib: dllname, importc: "glNormal3iv".}
+proc glNormal3s*(nx, ny, nz: TGLshort){.dynlib: dllname, importc: "glNormal3s".}
+proc glNormal3sv*(v: PGLshort){.dynlib: dllname, importc: "glNormal3sv".}
+proc glNormalPointer*(atype: TGLenum, stride: TGLsizei, pointer: Pointer){.
+    dynlib: dllname, importc: "glNormalPointer".}
+proc glOrtho*(left, right, bottom, top, zNear, zFar: TGLdouble){.
+    dynlib: dllname, importc: "glOrtho".}
+proc glPassThrough*(token: TGLfloat){.dynlib: dllname, importc: "glPassThrough".}
+proc glPixelMapfv*(map: TGLenum, mapsize: TGLsizei, values: PGLfloat){.
+    dynlib: dllname, importc: "glPixelMapfv".}
+proc glPixelMapuiv*(map: TGLenum, mapsize: TGLsizei, values: PGLuint){.
+    dynlib: dllname, importc: "glPixelMapuiv".}
+proc glPixelMapusv*(map: TGLenum, mapsize: TGLsizei, values: PGLushort){.
+    dynlib: dllname, importc: "glPixelMapusv".}
+proc glPixelStoref*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glPixelStoref".}
+proc glPixelStorei*(pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glPixelStorei".}
+proc glPixelTransferf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glPixelTransferf".}
+proc glPixelTransferi*(pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glPixelTransferi".}
+proc glPixelZoom*(xfactor, yfactor: TGLfloat){.dynlib: dllname, 
+    importc: "glPixelZoom".}
+proc glPointSize*(size: TGLfloat){.dynlib: dllname, importc: "glPointSize".}
+proc glPolygonMode*(face, mode: TGLenum){.dynlib: dllname, 
+    importc: "glPolygonMode".}
+proc glPolygonOffset*(factor, units: TGLfloat){.dynlib: dllname, 
+    importc: "glPolygonOffset".}
+proc glPolygonStipple*(mask: PGLubyte){.dynlib: dllname, 
+                                        importc: "glPolygonStipple".}
+proc glPopAttrib*(){.dynlib: dllname, importc: "glPopAttrib".}
+proc glPopClientAttrib*(){.dynlib: dllname, importc: "glPopClientAttrib".}
+proc glPopMatrix*(){.dynlib: dllname, importc: "glPopMatrix".}
+proc glPopName*(){.dynlib: dllname, importc: "glPopName".}
+proc glPrioritizeTextures*(n: TGLsizei, textures: PGLuint, priorities: PGLclampf){.
+    dynlib: dllname, importc: "glPrioritizeTextures".}
+proc glPushAttrib*(mask: TGLbitfield){.dynlib: dllname, importc: "glPushAttrib".}
+proc glPushClientAttrib*(mask: TGLbitfield){.dynlib: dllname, 
+    importc: "glPushClientAttrib".}
+proc glPushMatrix*(){.dynlib: dllname, importc: "glPushMatrix".}
+proc glPushName*(name: TGLuint){.dynlib: dllname, importc: "glPushName".}
+proc glRasterPos2d*(x, y: TGLdouble){.dynlib: dllname, importc: "glRasterPos2d".}
+proc glRasterPos2dv*(v: PGLdouble){.dynlib: dllname, importc: "glRasterPos2dv".}
+proc glRasterPos2f*(x, y: TGLfloat){.dynlib: dllname, importc: "glRasterPos2f".}
+proc glRasterPos2fv*(v: PGLfloat){.dynlib: dllname, importc: "glRasterPos2fv".}
+proc glRasterPos2i*(x, y: TGLint){.dynlib: dllname, importc: "glRasterPos2i".}
+proc glRasterPos2iv*(v: PGLint){.dynlib: dllname, importc: "glRasterPos2iv".}
+proc glRasterPos2s*(x, y: TGLshort){.dynlib: dllname, importc: "glRasterPos2s".}
+proc glRasterPos2sv*(v: PGLshort){.dynlib: dllname, importc: "glRasterPos2sv".}
+proc glRasterPos3d*(x, y, z: TGLdouble){.dynlib: dllname, 
+    importc: "glRasterPos3d".}
+proc glRasterPos3dv*(v: PGLdouble){.dynlib: dllname, importc: "glRasterPos3dv".}
+proc glRasterPos3f*(x, y, z: TGLfloat){.dynlib: dllname, 
+                                        importc: "glRasterPos3f".}
+proc glRasterPos3fv*(v: PGLfloat){.dynlib: dllname, importc: "glRasterPos3fv".}
+proc glRasterPos3i*(x, y, z: TGLint){.dynlib: dllname, importc: "glRasterPos3i".}
+proc glRasterPos3iv*(v: PGLint){.dynlib: dllname, importc: "glRasterPos3iv".}
+proc glRasterPos3s*(x, y, z: TGLshort){.dynlib: dllname, 
+                                        importc: "glRasterPos3s".}
+proc glRasterPos3sv*(v: PGLshort){.dynlib: dllname, importc: "glRasterPos3sv".}
+proc glRasterPos4d*(x, y, z, w: TGLdouble){.dynlib: dllname, 
+    importc: "glRasterPos4d".}
+proc glRasterPos4dv*(v: PGLdouble){.dynlib: dllname, importc: "glRasterPos4dv".}
+proc glRasterPos4f*(x, y, z, w: TGLfloat){.dynlib: dllname, 
+    importc: "glRasterPos4f".}
+proc glRasterPos4fv*(v: PGLfloat){.dynlib: dllname, importc: "glRasterPos4fv".}
+proc glRasterPos4i*(x, y, z, w: TGLint){.dynlib: dllname, 
+    importc: "glRasterPos4i".}
+proc glRasterPos4iv*(v: PGLint){.dynlib: dllname, importc: "glRasterPos4iv".}
+proc glRasterPos4s*(x, y, z, w: TGLshort){.dynlib: dllname, 
+    importc: "glRasterPos4s".}
+proc glRasterPos4sv*(v: PGLshort){.dynlib: dllname, importc: "glRasterPos4sv".}
+proc glReadBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glReadBuffer".}
+proc glReadPixels*(x, y: TGLint, width, height: TGLsizei, 
+                   format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, 
+    importc: "glReadPixels".}
+proc glRectd*(x1, y1, x2, y2: TGLdouble){.dynlib: dllname, importc: "glRectd".}
+proc glRectdv*(v1: PGLdouble, v2: PGLdouble){.dynlib: dllname, 
+    importc: "glRectdv".}
+proc glRectf*(x1, y1, x2, y2: TGLfloat){.dynlib: dllname, importc: "glRectf".}
+proc glRectfv*(v1: PGLfloat, v2: PGLfloat){.dynlib: dllname, importc: "glRectfv".}
+proc glRecti*(x1, y1, x2, y2: TGLint){.dynlib: dllname, importc: "glRecti".}
+proc glRectiv*(v1: PGLint, v2: PGLint){.dynlib: dllname, importc: "glRectiv".}
+proc glRects*(x1, y1, x2, y2: TGLshort){.dynlib: dllname, importc: "glRects".}
+proc glRectsv*(v1: PGLshort, v2: PGLshort){.dynlib: dllname, importc: "glRectsv".}
+proc glRenderMode*(mode: TGLint): TGLint{.dynlib: dllname, 
+    importc: "glRenderMode".}
+proc glRotated*(angle, x, y, z: TGLdouble){.dynlib: dllname, 
+    importc: "glRotated".}
+proc glRotatef*(angle, x, y, z: TGLfloat){.dynlib: dllname, importc: "glRotatef".}
+proc glScaled*(x, y, z: TGLdouble){.dynlib: dllname, importc: "glScaled".}
+proc glScalef*(x, y, z: TGLfloat){.dynlib: dllname, importc: "glScalef".}
+proc glScissor*(x, y: TGLint, width, height: TGLsizei){.dynlib: dllname, 
+    importc: "glScissor".}
+proc glSelectBuffer*(size: TGLsizei, buffer: PGLuint){.dynlib: dllname, 
+    importc: "glSelectBuffer".}
+proc glShadeModel*(mode: TGLenum){.dynlib: dllname, importc: "glShadeModel".}
+proc glStencilFunc*(func: TGLenum, theref: TGLint, mask: TGLuint){.
+    dynlib: dllname, importc: "glStencilFunc".}
+proc glStencilMask*(mask: TGLuint){.dynlib: dllname, importc: "glStencilMask".}
+proc glStencilOp*(fail, zfail, zpass: TGLenum){.dynlib: dllname, 
+    importc: "glStencilOp".}
+proc glTexCoord1d*(s: TGLdouble){.dynlib: dllname, importc: "glTexCoord1d".}
+proc glTexCoord1dv*(v: PGLdouble){.dynlib: dllname, importc: "glTexCoord1dv".}
+proc glTexCoord1f*(s: TGLfloat){.dynlib: dllname, importc: "glTexCoord1f".}
+proc glTexCoord1fv*(v: PGLfloat){.dynlib: dllname, importc: "glTexCoord1fv".}
+proc glTexCoord1i*(s: TGLint){.dynlib: dllname, importc: "glTexCoord1i".}
+proc glTexCoord1iv*(v: PGLint){.dynlib: dllname, importc: "glTexCoord1iv".}
+proc glTexCoord1s*(s: TGLshort){.dynlib: dllname, importc: "glTexCoord1s".}
+proc glTexCoord1sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord1sv".}
+proc glTexCoord2d*(s, t: TGLdouble){.dynlib: dllname, importc: "glTexCoord2d".}
+proc glTexCoord2dv*(v: PGLdouble){.dynlib: dllname, importc: "glTexCoord2dv".}
+proc glTexCoord2f*(s, t: TGLfloat){.dynlib: dllname, importc: "glTexCoord2f".}
+proc glTexCoord2fv*(v: PGLfloat){.dynlib: dllname, importc: "glTexCoord2fv".}
+proc glTexCoord2i*(s, t: TGLint){.dynlib: dllname, importc: "glTexCoord2i".}
+proc glTexCoord2iv*(v: PGLint){.dynlib: dllname, importc: "glTexCoord2iv".}
+proc glTexCoord2s*(s, t: TGLshort){.dynlib: dllname, importc: "glTexCoord2s".}
+proc glTexCoord2sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord2sv".}
+proc glTexCoord3d*(s, t, r: TGLdouble){.dynlib: dllname, importc: "glTexCoord3d".}
+proc glTexCoord3dv*(v: PGLdouble){.dynlib: dllname, importc: "glTexCoord3dv".}
+proc glTexCoord3f*(s, t, r: TGLfloat){.dynlib: dllname, importc: "glTexCoord3f".}
+proc glTexCoord3fv*(v: PGLfloat){.dynlib: dllname, importc: "glTexCoord3fv".}
+proc glTexCoord3i*(s, t, r: TGLint){.dynlib: dllname, importc: "glTexCoord3i".}
+proc glTexCoord3iv*(v: PGLint){.dynlib: dllname, importc: "glTexCoord3iv".}
+proc glTexCoord3s*(s, t, r: TGLshort){.dynlib: dllname, importc: "glTexCoord3s".}
+proc glTexCoord3sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord3sv".}
+proc glTexCoord4d*(s, t, r, q: TGLdouble){.dynlib: dllname, 
+    importc: "glTexCoord4d".}
+proc glTexCoord4dv*(v: PGLdouble){.dynlib: dllname, importc: "glTexCoord4dv".}
+proc glTexCoord4f*(s, t, r, q: TGLfloat){.dynlib: dllname, 
+    importc: "glTexCoord4f".}
+proc glTexCoord4fv*(v: PGLfloat){.dynlib: dllname, importc: "glTexCoord4fv".}
+proc glTexCoord4i*(s, t, r, q: TGLint){.dynlib: dllname, importc: "glTexCoord4i".}
+proc glTexCoord4iv*(v: PGLint){.dynlib: dllname, importc: "glTexCoord4iv".}
+proc glTexCoord4s*(s, t, r, q: TGLshort){.dynlib: dllname, 
+    importc: "glTexCoord4s".}
+proc glTexCoord4sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord4sv".}
+proc glTexCoordPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, 
+                        pointer: Pointer){.dynlib: dllname, 
+    importc: "glTexCoordPointer".}
+proc glTexEnvf*(target: TGLenum, pname: TGLenum, param: TGLfloat){.
+    dynlib: dllname, importc: "glTexEnvf".}
+proc glTexEnvfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glTexEnvfv".}
+proc glTexEnvi*(target: TGLenum, pname: TGLenum, param: TGLint){.
+    dynlib: dllname, importc: "glTexEnvi".}
+proc glTexEnviv*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glTexEnviv".}
+proc glTexGend*(coord: TGLenum, pname: TGLenum, param: TGLdouble){.
+    dynlib: dllname, importc: "glTexGend".}
+proc glTexGendv*(coord: TGLenum, pname: TGLenum, params: PGLdouble){.
+    dynlib: dllname, importc: "glTexGendv".}
+proc glTexGenf*(coord: TGLenum, pname: TGLenum, param: TGLfloat){.
+    dynlib: dllname, importc: "glTexGenf".}
+proc glTexGenfv*(coord: TGLenum, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glTexGenfv".}
+proc glTexGeni*(coord: TGLenum, pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glTexGeni".}
+proc glTexGeniv*(coord: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glTexGeniv".}
+proc glTexImage1D*(target: TGLenum, level, internalformat: TGLint, 
+                   width: TGLsizei, border: TGLint, format, atype: TGLenum, 
+                   pixels: Pointer){.dynlib: dllname, importc: "glTexImage1D".}
+proc glTexImage2D*(target: TGLenum, level, internalformat: TGLint, 
+                   width, height: TGLsizei, border: TGLint, 
+                   format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, 
+    importc: "glTexImage2D".}
+proc glTexParameterf*(target: TGLenum, pname: TGLenum, param: TGLfloat){.
+    dynlib: dllname, importc: "glTexParameterf".}
+proc glTexParameterfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glTexParameterfv".}
+proc glTexParameteri*(target: TGLenum, pname: TGLenum, param: TGLint){.
+    dynlib: dllname, importc: "glTexParameteri".}
+proc glTexParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glTexParameteriv".}
+proc glTexSubImage1D*(target: TGLenum, level, xoffset: TGLint, width: TGLsizei, 
+                      format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, 
+    importc: "glTexSubImage1D".}
+proc glTexSubImage2D*(target: TGLenum, level, xoffset, yoffset: TGLint, 
+                      width, height: TGLsizei, format, atype: TGLenum, 
+                      pixels: Pointer){.dynlib: dllname, 
+                                        importc: "glTexSubImage2D".}
+proc glTranslated*(x, y, z: TGLdouble){.dynlib: dllname, importc: "glTranslated".}
+proc glTranslatef*(x, y, z: TGLfloat){.dynlib: dllname, importc: "glTranslatef".}
+proc glVertex2d*(x, y: TGLdouble){.dynlib: dllname, importc: "glVertex2d".}
+proc glVertex2dv*(v: PGLdouble){.dynlib: dllname, importc: "glVertex2dv".}
+proc glVertex2f*(x, y: TGLfloat){.dynlib: dllname, importc: "glVertex2f".}
+proc glVertex2fv*(v: PGLfloat){.dynlib: dllname, importc: "glVertex2fv".}
+proc glVertex2i*(x, y: TGLint){.dynlib: dllname, importc: "glVertex2i".}
+proc glVertex2iv*(v: PGLint){.dynlib: dllname, importc: "glVertex2iv".}
+proc glVertex2s*(x, y: TGLshort){.dynlib: dllname, importc: "glVertex2s".}
+proc glVertex2sv*(v: PGLshort){.dynlib: dllname, importc: "glVertex2sv".}
+proc glVertex3d*(x, y, z: TGLdouble){.dynlib: dllname, importc: "glVertex3d".}
+proc glVertex3dv*(v: PGLdouble){.dynlib: dllname, importc: "glVertex3dv".}
+proc glVertex3f*(x, y, z: TGLfloat){.dynlib: dllname, importc: "glVertex3f".}
+proc glVertex3fv*(v: PGLfloat){.dynlib: dllname, importc: "glVertex3fv".}
+proc glVertex3i*(x, y, z: TGLint){.dynlib: dllname, importc: "glVertex3i".}
+proc glVertex3iv*(v: PGLint){.dynlib: dllname, importc: "glVertex3iv".}
+proc glVertex3s*(x, y, z: TGLshort){.dynlib: dllname, importc: "glVertex3s".}
+proc glVertex3sv*(v: PGLshort){.dynlib: dllname, importc: "glVertex3sv".}
+proc glVertex4d*(x, y, z, w: TGLdouble){.dynlib: dllname, importc: "glVertex4d".}
+proc glVertex4dv*(v: PGLdouble){.dynlib: dllname, importc: "glVertex4dv".}
+proc glVertex4f*(x, y, z, w: TGLfloat){.dynlib: dllname, importc: "glVertex4f".}
+proc glVertex4fv*(v: PGLfloat){.dynlib: dllname, importc: "glVertex4fv".}
+proc glVertex4i*(x, y, z, w: TGLint){.dynlib: dllname, importc: "glVertex4i".}
+proc glVertex4iv*(v: PGLint){.dynlib: dllname, importc: "glVertex4iv".}
+proc glVertex4s*(x, y, z, w: TGLshort){.dynlib: dllname, importc: "glVertex4s".}
+proc glVertex4sv*(v: PGLshort){.dynlib: dllname, importc: "glVertex4sv".}
+proc glVertexPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, 
+                      pointer: Pointer){.dynlib: dllname, 
+    importc: "glVertexPointer".}
+proc glViewport*(x, y: TGLint, width, height: TGLsizei){.dynlib: dllname, 
+    importc: "glViewport".}
+type 
+  PFN_GLARRAY_ELEMENT_EXTPROC* = proc (i: TGLint)
+  PFN_GLDRAW_ARRAYS_EXTPROC* = proc (mode: TGLenum, first: TGLint, 
+                                     count: TGLsizei)
+  PFN_GLVERTEX_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, 
+                                        stride, count: TGLsizei, 
+                                        pointer: Pointer)
+  PFN_GLNORMAL_POINTER_EXTPROC* = proc (atype: TGLenum, stride, count: TGLsizei, 
+                                        pointer: Pointer)
+  PFN_GLCOLOR_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, 
+                                       stride, count: TGLsizei, pointer: Pointer)
+  PFN_GLINDEX_POINTER_EXTPROC* = proc (atype: TGLenum, stride, count: TGLsizei, 
+                                       pointer: Pointer)
+  PFN_GLTEXCOORD_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, 
+      stride, count: TGLsizei, pointer: Pointer)
+  PFN_GLEDGEFLAG_POINTER_EXTPROC* = proc (stride, count: TGLsizei, 
+      pointer: PGLboolean)
+  PFN_GLGET_POINTER_VEXT_PROC* = proc (pname: TGLenum, params: Pointer)
+  PFN_GLARRAY_ELEMENT_ARRAY_EXTPROC* = proc (mode: TGLenum, count: TGLsizei, 
+      pi: Pointer)            # WIN_swap_hint
+  PFN_GLADDSWAPHINT_RECT_WINPROC* = proc (x, y: TGLint, width, height: TGLsizei)
+  PFN_GLCOLOR_TABLE_EXTPROC* = proc (target, internalFormat: TGLenum, 
+                                     width: TGLsizei, format, atype: TGLenum, 
+                                     data: Pointer)
+  PFN_GLCOLOR_SUBTABLE_EXTPROC* = proc (target: TGLenum, start, count: TGLsizei, 
+                                        format, atype: TGLenum, data: Pointer)
+  PFN_GLGETCOLOR_TABLE_EXTPROC* = proc (target, format, atype: TGLenum, 
+                                        data: Pointer)
+  PFN_GLGETCOLOR_TABLE_PARAMETER_IVEXTPROC* = proc (target, pname: TGLenum, 
+      params: PGLint)
+  PFN_GLGETCOLOR_TABLE_PARAMETER_FVEXTPROC* = proc (target, pname: TGLenum, 
+      params: PGLfloat)
+
+{.pop.}
+# implementation
diff --git a/tests/manyloc/keineschweine/lib/glext.nim b/tests/manyloc/keineschweine/lib/glext.nim
new file mode 100644
index 0000000000..32871df0e4
--- /dev/null
+++ b/tests/manyloc/keineschweine/lib/glext.nim
@@ -0,0 +1,4673 @@
+#
+#
+#  Adaption of the delphi3d.net OpenGL units to FreePascal
+#  Sebastian Guenther (sg@freepascal.org) in 2002
+#  These units are free to use
+#
+#
+
+#*************************************************
+# *        OpenGL extension loading library        *
+# * Generated by MetaGLext, written by Tom Nuydens *
+# *  (tom@delphi3d.net -- http://www.delphi3d.net  *
+# *************************************************
+#*** Generated on 10/11/2002
+
+when defined(windows): 
+  {.push, callconv: stdcall.}
+else: 
+  {.push, callconv: cdecl.}
+import 
+  gl
+
+type 
+  GLcharARB* = Char
+  TGLcharARB* = GLcharARB
+  PGLcharARB* = ptr GLcharARB
+  GLhandleARB* = int
+  TGLhandleARB* = GLhandleARB
+  PGLhandleARB* = ptr GLhandleARB
+  GLintptr* = int
+  TGLintptr* = GLintptr
+  PGLintptr* = ptr GLintptr
+  GLsizeiptr* = int
+  TGLsizeiptr* = GLsizeiptr
+  PGLsizeiptr* = ptr GLsizeiptr
+  GLchar* = Char
+  TGLchar* = GLchar
+  PGLchar* = cstring          #***** GL_version_1_2 *****//
+
+const 
+  GL_UNSIGNED_BYTE_3_3_2* = 0x00008032
+  GL_UNSIGNED_SHORT_4_4_4_4* = 0x00008033
+  GL_UNSIGNED_SHORT_5_5_5_1* = 0x00008034
+  GL_UNSIGNED_INT_8_8_8_8* = 0x00008035
+  GL_UNSIGNED_INT_10_10_10_2* = 0x00008036
+  GL_RESCALE_NORMAL* = 0x0000803A
+  GL_UNSIGNED_BYTE_2_3_3_REV* = 0x00008362
+  GL_UNSIGNED_SHORT_5_6_5* = 0x00008363
+  GL_UNSIGNED_SHORT_5_6_5_REV* = 0x00008364
+  GL_UNSIGNED_SHORT_4_4_4_4_REV* = 0x00008365
+  GL_UNSIGNED_SHORT_1_5_5_5_REV* = 0x00008366
+  GL_UNSIGNED_INT_8_8_8_8_REV* = 0x00008367
+  GL_UNSIGNED_INT_2_10_10_10_REV* = 0x00008368
+  GL_BGR* = 0x000080E0
+  GL_BGRA* = 0x000080E1
+  GL_MAX_ELEMENTS_VERTICES* = 0x000080E8
+  GL_MAX_ELEMENTS_INDICES* = 0x000080E9
+  GL_CLAMP_TO_EDGE* = 0x0000812F
+  GL_TEXTURE_MIN_LOD* = 0x0000813A
+  GL_TEXTURE_MAX_LOD* = 0x0000813B
+  GL_TEXTURE_BASE_LEVEL* = 0x0000813C
+  GL_TEXTURE_MAX_LEVEL* = 0x0000813D
+  GL_LIGHT_MODEL_COLOR_CONTROL* = 0x000081F8
+  GL_SINGLE_COLOR* = 0x000081F9
+  GL_SEPARATE_SPECULAR_COLOR* = 0x000081FA
+  GL_SMOOTH_POINT_SIZE_RANGE* = 0x00000B12
+  GL_SMOOTH_POINT_SIZE_GRANULARITY* = 0x00000B13
+  GL_SMOOTH_LINE_WIDTH_RANGE* = 0x00000B22
+  GL_SMOOTH_LINE_WIDTH_GRANULARITY* = 0x00000B23
+  GL_ALIASED_POINT_SIZE_RANGE* = 0x0000846D
+  GL_ALIASED_LINE_WIDTH_RANGE* = 0x0000846E
+  GL_PACK_SKIP_IMAGES* = 0x0000806B
+  GL_PACK_IMAGE_HEIGHT* = 0x0000806C
+  GL_UNPACK_SKIP_IMAGES* = 0x0000806D
+  GL_UNPACK_IMAGE_HEIGHT* = 0x0000806E
+  GL_TEXTURE_3D* = 0x0000806F
+  GL_PROXY_TEXTURE_3D* = 0x00008070
+  GL_TEXTURE_DEPTH* = 0x00008071
+  GL_TEXTURE_WRAP_R* = 0x00008072
+  GL_MAX_3D_TEXTURE_SIZE* = 0x00008073
+
+proc glBlendColor*(red: TGLclampf, green: TGLclampf, blue: TGLclampf, 
+                   alpha: TGLclampf){.dynlib: dllname, importc: "glBlendColor".}
+proc glBlendEquation*(mode: TGLenum){.dynlib: dllname, 
+                                      importc: "glBlendEquation".}
+proc glDrawRangeElements*(mode: TGLenum, start: TGLuint, theend: TGLuint, 
+                          count: TGLsizei, thetype: TGLenum, indices: PGLvoid){.
+    dynlib: dllname, importc: "glDrawRangeElements".}
+proc glColorTable*(target: TGLenum, internalformat: TGLenum, width: TGLsizei, 
+                   format: TGLenum, thetype: TGLenum, table: PGLvoid){.
+    dynlib: dllname, importc: "glColorTable".}
+proc glColorTableParameterfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glColorTableParameterfv".}
+proc glColorTableParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glColorTableParameteriv".}
+proc glCopyColorTable*(target: TGLenum, internalformat: TGLenum, x: TGLint, 
+                       y: TGLint, width: TGLsizei){.dynlib: dllname, 
+    importc: "glCopyColorTable".}
+proc glGetColorTable*(target: TGLenum, format: TGLenum, thetype: TGLenum, 
+                      table: PGLvoid){.dynlib: dllname, 
+                                       importc: "glGetColorTable".}
+proc glGetColorTableParameterfv*(target: TGLenum, pname: TGLenum, 
+                                 params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetColorTableParameterfv".}
+proc glGetColorTableParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetColorTableParameteriv".}
+proc glColorSubTable*(target: TGLenum, start: TGLsizei, count: TGLsizei, 
+                      format: TGLenum, thetype: TGLenum, data: PGLvoid){.
+    dynlib: dllname, importc: "glColorSubTable".}
+proc glCopyColorSubTable*(target: TGLenum, start: TGLsizei, x: TGLint, 
+                          y: TGLint, width: TGLsizei){.dynlib: dllname, 
+    importc: "glCopyColorSubTable".}
+proc glConvolutionFilter1D*(target: TGLenum, internalformat: TGLenum, 
+                            width: TGLsizei, format: TGLenum, thetype: TGLenum, 
+                            image: PGLvoid){.dynlib: dllname, 
+    importc: "glConvolutionFilter1D".}
+proc glConvolutionFilter2D*(target: TGLenum, internalformat: TGLenum, 
+                            width: TGLsizei, height: TGLsizei, format: TGLenum, 
+                            thetype: TGLenum, image: PGLvoid){.dynlib: dllname, 
+    importc: "glConvolutionFilter2D".}
+proc glConvolutionParameterf*(target: TGLenum, pname: TGLenum, params: TGLfloat){.
+    dynlib: dllname, importc: "glConvolutionParameterf".}
+proc glConvolutionParameterfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glConvolutionParameterfv".}
+proc glConvolutionParameteri*(target: TGLenum, pname: TGLenum, params: TGLint){.
+    dynlib: dllname, importc: "glConvolutionParameteri".}
+proc glConvolutionParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glConvolutionParameteriv".}
+proc glCopyConvolutionFilter1D*(target: TGLenum, internalformat: TGLenum, 
+                                x: TGLint, y: TGLint, width: TGLsizei){.
+    dynlib: dllname, importc: "glCopyConvolutionFilter1D".}
+proc glCopyConvolutionFilter2D*(target: TGLenum, internalformat: TGLenum, 
+                                x: TGLint, y: TGLint, width: TGLsizei, 
+                                height: TGLsizei){.dynlib: dllname, 
+    importc: "glCopyConvolutionFilter2D".}
+proc glGetConvolutionFilter*(target: TGLenum, format: TGLenum, thetype: TGLenum, 
+                             image: PGLvoid){.dynlib: dllname, 
+    importc: "glGetConvolutionFilter".}
+proc glGetConvolutionParameterfv*(target: TGLenum, pname: TGLenum, 
+                                  params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetConvolutionParameterfv".}
+proc glGetConvolutionParameteriv*(target: TGLenum, pname: TGLenum, 
+                                  params: PGLint){.dynlib: dllname, 
+    importc: "glGetConvolutionParameteriv".}
+proc glGetSeparableFilter*(target: TGLenum, format: TGLenum, thetype: TGLenum, 
+                           row: PGLvoid, column: PGLvoid, span: PGLvoid){.
+    dynlib: dllname, importc: "glGetSeparableFilter".}
+proc glSeparableFilter2D*(target: TGLenum, internalformat: TGLenum, 
+                          width: TGLsizei, height: TGLsizei, format: TGLenum, 
+                          thetype: TGLenum, row: PGLvoid, column: PGLvoid){.
+    dynlib: dllname, importc: "glSeparableFilter2D".}
+proc glGetHistogram*(target: TGLenum, reset: TGLboolean, format: TGLenum, 
+                     thetype: TGLenum, values: PGLvoid){.dynlib: dllname, 
+    importc: "glGetHistogram".}
+proc glGetHistogramParameterfv*(target: TGLenum, pname: TGLenum, 
+                                params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetHistogramParameterfv".}
+proc glGetHistogramParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetHistogramParameteriv".}
+proc glGetMinmax*(target: TGLenum, reset: TGLboolean, format: TGLenum, 
+                  thetype: TGLenum, values: PGLvoid){.dynlib: dllname, 
+    importc: "glGetMinmax".}
+proc glGetMinmaxParameterfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetMinmaxParameterfv".}
+proc glGetMinmaxParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetMinmaxParameteriv".}
+proc glHistogram*(target: TGLenum, width: TGLsizei, internalformat: TGLenum, 
+                  sink: TGLboolean){.dynlib: dllname, importc: "glHistogram".}
+proc glMinmax*(target: TGLenum, internalformat: TGLenum, sink: TGLboolean){.
+    dynlib: dllname, importc: "glMinmax".}
+proc glResetHistogram*(target: TGLenum){.dynlib: dllname, 
+    importc: "glResetHistogram".}
+proc glResetMinmax*(target: TGLenum){.dynlib: dllname, importc: "glResetMinmax".}
+proc glTexImage3D*(target: TGLenum, level: TGLint, internalformat: TGLint, 
+                   width: TGLsizei, height: TGLsizei, depth: TGLsizei, 
+                   border: TGLint, format: TGLenum, thetype: TGLenum, 
+                   pixels: PGLvoid){.dynlib: dllname, importc: "glTexImage3D".}
+proc glTexSubImage3D*(target: TGLenum, level: TGLint, xoffset: TGLint, 
+                      yoffset: TGLint, zoffset: TGLint, width: TGLsizei, 
+                      height: TGLsizei, depth: TGLsizei, format: TGLenum, 
+                      thetype: TGLenum, pixels: PGLvoid){.dynlib: dllname, 
+    importc: "glTexSubImage3D".}
+proc glCopyTexSubImage3D*(target: TGLenum, level: TGLint, xoffset: TGLint, 
+                          yoffset: TGLint, zoffset: TGLint, x: TGLint, 
+                          y: TGLint, width: TGLsizei, height: TGLsizei){.
+    dynlib: dllname, importc: "glCopyTexSubImage3D".}
+proc glActiveTextureARB*(texture: TGLenum){.dynlib: dllname, 
+    importc: "glActiveTextureARB".}
+proc glClientActiveTextureARB*(texture: TGLenum){.dynlib: dllname, 
+    importc: "glClientActiveTextureARB".}
+proc glMultiTexCoord1dARB*(target: TGLenum, s: TGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord1dARB".}
+proc glMultiTexCoord1dvARB*(target: TGLenum, v: PGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord1dvARB".}
+proc glMultiTexCoord1fARB*(target: TGLenum, s: TGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord1fARB".}
+proc glMultiTexCoord1fvARB*(target: TGLenum, v: PGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord1fvARB".}
+proc glMultiTexCoord1iARB*(target: TGLenum, s: TGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord1iARB".}
+proc glMultiTexCoord1ivARB*(target: TGLenum, v: PGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord1ivARB".}
+proc glMultiTexCoord1sARB*(target: TGLenum, s: TGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord1sARB".}
+proc glMultiTexCoord1svARB*(target: TGLenum, v: PGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord1svARB".}
+proc glMultiTexCoord2dARB*(target: TGLenum, s: TGLdouble, t: TGLdouble){.
+    dynlib: dllname, importc: "glMultiTexCoord2dARB".}
+proc glMultiTexCoord2dvARB*(target: TGLenum, v: PGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord2dvARB".}
+proc glMultiTexCoord2fARB*(target: TGLenum, s: TGLfloat, t: TGLfloat){.
+    dynlib: dllname, importc: "glMultiTexCoord2fARB".}
+proc glMultiTexCoord2fvARB*(target: TGLenum, v: PGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord2fvARB".}
+proc glMultiTexCoord2iARB*(target: TGLenum, s: TGLint, t: TGLint){.
+    dynlib: dllname, importc: "glMultiTexCoord2iARB".}
+proc glMultiTexCoord2ivARB*(target: TGLenum, v: PGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord2ivARB".}
+proc glMultiTexCoord2sARB*(target: TGLenum, s: TGLshort, t: TGLshort){.
+    dynlib: dllname, importc: "glMultiTexCoord2sARB".}
+proc glMultiTexCoord2svARB*(target: TGLenum, v: PGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord2svARB".}
+proc glMultiTexCoord3dARB*(target: TGLenum, s: TGLdouble, t: TGLdouble, 
+                           r: TGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord3dARB".}
+proc glMultiTexCoord3dvARB*(target: TGLenum, v: PGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord3dvARB".}
+proc glMultiTexCoord3fARB*(target: TGLenum, s: TGLfloat, t: TGLfloat, 
+                           r: TGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord3fARB".}
+proc glMultiTexCoord3fvARB*(target: TGLenum, v: PGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord3fvARB".}
+proc glMultiTexCoord3iARB*(target: TGLenum, s: TGLint, t: TGLint, r: TGLint){.
+    dynlib: dllname, importc: "glMultiTexCoord3iARB".}
+proc glMultiTexCoord3ivARB*(target: TGLenum, v: PGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord3ivARB".}
+proc glMultiTexCoord3sARB*(target: TGLenum, s: TGLshort, t: TGLshort, 
+                           r: TGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord3sARB".}
+proc glMultiTexCoord3svARB*(target: TGLenum, v: PGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord3svARB".}
+proc glMultiTexCoord4dARB*(target: TGLenum, s: TGLdouble, t: TGLdouble, 
+                           r: TGLdouble, q: TGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord4dARB".}
+proc glMultiTexCoord4dvARB*(target: TGLenum, v: PGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord4dvARB".}
+proc glMultiTexCoord4fARB*(target: TGLenum, s: TGLfloat, t: TGLfloat, 
+                           r: TGLfloat, q: TGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord4fARB".}
+proc glMultiTexCoord4fvARB*(target: TGLenum, v: PGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord4fvARB".}
+proc glMultiTexCoord4iARB*(target: TGLenum, s: TGLint, t: TGLint, r: TGLint, 
+                           q: TGLint){.dynlib: dllname, 
+                                       importc: "glMultiTexCoord4iARB".}
+proc glMultiTexCoord4ivARB*(target: TGLenum, v: PGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord4ivARB".}
+proc glMultiTexCoord4sARB*(target: TGLenum, s: TGLshort, t: TGLshort, 
+                           r: TGLshort, q: TGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord4sARB".}
+proc glMultiTexCoord4svARB*(target: TGLenum, v: PGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord4svARB".}
+proc glSampleCoverageARB*(value: TGLclampf, invert: TGLboolean){.
+    dynlib: dllname, importc: "glSampleCoverageARB".}
+  #***** GL_ARB_texture_env_add *****//
+proc glWeightbvARB*(size: TGLint, weights: PGLbyte){.dynlib: dllname, 
+    importc: "glWeightbvARB".}
+proc glWeightsvARB*(size: TGLint, weights: PGLshort){.dynlib: dllname, 
+    importc: "glWeightsvARB".}
+proc glWeightivARB*(size: TGLint, weights: PGLint){.dynlib: dllname, 
+    importc: "glWeightivARB".}
+proc glWeightfvARB*(size: TGLint, weights: PGLfloat){.dynlib: dllname, 
+    importc: "glWeightfvARB".}
+proc glWeightdvARB*(size: TGLint, weights: PGLdouble){.dynlib: dllname, 
+    importc: "glWeightdvARB".}
+proc glWeightvARB*(size: TGLint, weights: PGLdouble){.dynlib: dllname, 
+    importc: "glWeightvARB".}
+proc glWeightubvARB*(size: TGLint, weights: PGLubyte){.dynlib: dllname, 
+    importc: "glWeightubvARB".}
+proc glWeightusvARB*(size: TGLint, weights: PGLushort){.dynlib: dllname, 
+    importc: "glWeightusvARB".}
+proc glWeightuivARB*(size: TGLint, weights: PGLuint){.dynlib: dllname, 
+    importc: "glWeightuivARB".}
+proc glWeightPointerARB*(size: TGLint, thetype: TGLenum, stride: TGLsizei, 
+                         pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glWeightPointerARB".}
+proc glVertexBlendARB*(count: TGLint){.dynlib: dllname, 
+                                       importc: "glVertexBlendARB".}
+proc glVertexAttrib1sARB*(index: TGLuint, x: TGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib1sARB".}
+proc glVertexAttrib1fARB*(index: TGLuint, x: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib1fARB".}
+proc glVertexAttrib1dARB*(index: TGLuint, x: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib1dARB".}
+proc glVertexAttrib2sARB*(index: TGLuint, x: TGLshort, y: TGLshort){.
+    dynlib: dllname, importc: "glVertexAttrib2sARB".}
+proc glVertexAttrib2fARB*(index: TGLuint, x: TGLfloat, y: TGLfloat){.
+    dynlib: dllname, importc: "glVertexAttrib2fARB".}
+proc glVertexAttrib2dARB*(index: TGLuint, x: TGLdouble, y: TGLdouble){.
+    dynlib: dllname, importc: "glVertexAttrib2dARB".}
+proc glVertexAttrib3sARB*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort){.
+    dynlib: dllname, importc: "glVertexAttrib3sARB".}
+proc glVertexAttrib3fARB*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glVertexAttrib3fARB".}
+proc glVertexAttrib3dARB*(index: TGLuint, x: TGLdouble, y: TGLdouble, 
+                          z: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib3dARB".}
+proc glVertexAttrib4sARB*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort, 
+                          w: TGLshort){.dynlib: dllname, 
+                                        importc: "glVertexAttrib4sARB".}
+proc glVertexAttrib4fARB*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat, 
+                          w: TGLfloat){.dynlib: dllname, 
+                                        importc: "glVertexAttrib4fARB".}
+proc glVertexAttrib4dARB*(index: TGLuint, x: TGLdouble, y: TGLdouble, 
+                          z: TGLdouble, w: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib4dARB".}
+proc glVertexAttrib4NubARB*(index: TGLuint, x: TGLubyte, y: TGLubyte, 
+                            z: TGLubyte, w: TGLubyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4NubARB".}
+proc glVertexAttrib1svARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib1svARB".}
+proc glVertexAttrib1fvARB*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib1fvARB".}
+proc glVertexAttrib1dvARB*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib1dvARB".}
+proc glVertexAttrib2svARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib2svARB".}
+proc glVertexAttrib2fvARB*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib2fvARB".}
+proc glVertexAttrib2dvARB*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib2dvARB".}
+proc glVertexAttrib3svARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib3svARB".}
+proc glVertexAttrib3fvARB*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib3fvARB".}
+proc glVertexAttrib3dvARB*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib3dvARB".}
+proc glVertexAttrib4bvARB*(index: TGLuint, v: PGLbyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4bvARB".}
+proc glVertexAttrib4svARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib4svARB".}
+proc glVertexAttrib4ivARB*(index: TGLuint, v: PGLint){.dynlib: dllname, 
+    importc: "glVertexAttrib4ivARB".}
+proc glVertexAttrib4ubvARB*(index: TGLuint, v: PGLubyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4ubvARB".}
+proc glVertexAttrib4usvARB*(index: TGLuint, v: PGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib4usvARB".}
+proc glVertexAttrib4uivARB*(index: TGLuint, v: PGLuint){.dynlib: dllname, 
+    importc: "glVertexAttrib4uivARB".}
+proc glVertexAttrib4fvARB*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib4fvARB".}
+proc glVertexAttrib4dvARB*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib4dvARB".}
+proc glVertexAttrib4NbvARB*(index: TGLuint, v: PGLbyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4NbvARB".}
+proc glVertexAttrib4NsvARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib4NsvARB".}
+proc glVertexAttrib4NivARB*(index: TGLuint, v: PGLint){.dynlib: dllname, 
+    importc: "glVertexAttrib4NivARB".}
+proc glVertexAttrib4NubvARB*(index: TGLuint, v: PGLubyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4NubvARB".}
+proc glVertexAttrib4NusvARB*(index: TGLuint, v: PGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib4NusvARB".}
+proc glVertexAttrib4NuivARB*(index: TGLuint, v: PGLuint){.dynlib: dllname, 
+    importc: "glVertexAttrib4NuivARB".}
+proc glVertexAttribPointerARB*(index: TGLuint, size: TGLint, thetype: TGLenum, 
+                               normalized: TGLboolean, stride: TGLsizei, 
+                               pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glVertexAttribPointerARB".}
+proc glEnableVertexAttribArrayARB*(index: TGLuint){.dynlib: dllname, 
+    importc: "glEnableVertexAttribArrayARB".}
+proc glDisableVertexAttribArrayARB*(index: TGLuint){.dynlib: dllname, 
+    importc: "glDisableVertexAttribArrayARB".}
+proc glProgramStringARB*(target: TGLenum, format: TGLenum, length: TGLsizei, 
+                         str: PGLvoid){.dynlib: dllname, 
+                                        importc: "glProgramStringARB".}
+proc glBindProgramARB*(target: TGLenum, theProgram: TGLuint){.dynlib: dllname, 
+    importc: "glBindProgramARB".}
+proc glDeleteProgramsARB*(n: TGLsizei, programs: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteProgramsARB".}
+proc glGenProgramsARB*(n: TGLsizei, programs: PGLuint){.dynlib: dllname, 
+    importc: "glGenProgramsARB".}
+proc glProgramEnvParameter4dARB*(target: TGLenum, index: TGLuint, x: TGLdouble, 
+                                 y: TGLdouble, z: TGLdouble, w: TGLdouble){.
+    dynlib: dllname, importc: "glProgramEnvParameter4dARB".}
+proc glProgramEnvParameter4dvARB*(target: TGLenum, index: TGLuint, 
+                                  params: PGLdouble){.dynlib: dllname, 
+    importc: "glProgramEnvParameter4dvARB".}
+proc glProgramEnvParameter4fARB*(target: TGLenum, index: TGLuint, x: TGLfloat, 
+                                 y: TGLfloat, z: TGLfloat, w: TGLfloat){.
+    dynlib: dllname, importc: "glProgramEnvParameter4fARB".}
+proc glProgramEnvParameter4fvARB*(target: TGLenum, index: TGLuint, 
+                                  params: PGLfloat){.dynlib: dllname, 
+    importc: "glProgramEnvParameter4fvARB".}
+proc glProgramLocalParameter4dARB*(target: TGLenum, index: TGLuint, 
+                                   x: TGLdouble, y: TGLdouble, z: TGLdouble, 
+                                   w: TGLdouble){.dynlib: dllname, 
+    importc: "glProgramLocalParameter4dARB".}
+proc glProgramLocalParameter4dvARB*(target: TGLenum, index: TGLuint, 
+                                    params: PGLdouble){.dynlib: dllname, 
+    importc: "glProgramLocalParameter4dvARB".}
+proc glProgramLocalParameter4fARB*(target: TGLenum, index: TGLuint, x: TGLfloat, 
+                                   y: TGLfloat, z: TGLfloat, w: TGLfloat){.
+    dynlib: dllname, importc: "glProgramLocalParameter4fARB".}
+proc glProgramLocalParameter4fvARB*(target: TGLenum, index: TGLuint, 
+                                    params: PGLfloat){.dynlib: dllname, 
+    importc: "glProgramLocalParameter4fvARB".}
+proc glGetProgramEnvParameterdvARB*(target: TGLenum, index: TGLuint, 
+                                    params: PGLdouble){.dynlib: dllname, 
+    importc: "glGetProgramEnvParameterdvARB".}
+proc glGetProgramEnvParameterfvARB*(target: TGLenum, index: TGLuint, 
+                                    params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetProgramEnvParameterfvARB".}
+proc glGetProgramLocalParameterdvARB*(target: TGLenum, index: TGLuint, 
+                                      params: PGLdouble){.dynlib: dllname, 
+    importc: "glGetProgramLocalParameterdvARB".}
+proc glGetProgramLocalParameterfvARB*(target: TGLenum, index: TGLuint, 
+                                      params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetProgramLocalParameterfvARB".}
+proc glGetProgramivARB*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetProgramivARB".}
+proc glGetProgramStringARB*(target: TGLenum, pname: TGLenum, str: PGLvoid){.
+    dynlib: dllname, importc: "glGetProgramStringARB".}
+proc glGetVertexAttribdvARB*(index: TGLuint, pname: TGLenum, params: PGLdouble){.
+    dynlib: dllname, importc: "glGetVertexAttribdvARB".}
+proc glGetVertexAttribfvARB*(index: TGLuint, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetVertexAttribfvARB".}
+proc glGetVertexAttribivARB*(index: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetVertexAttribivARB".}
+proc glGetVertexAttribPointervARB*(index: TGLuint, pname: TGLenum, 
+                                   pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glGetVertexAttribPointervARB".}
+proc glIsProgramARB*(theProgram: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsProgramARB".}
+  #***** GL_ARB_window_pos *****//
+proc glWindowPos2dARB*(x: TGLdouble, y: TGLdouble){.dynlib: dllname, 
+    importc: "glWindowPos2dARB".}
+proc glWindowPos2fARB*(x: TGLfloat, y: TGLfloat){.dynlib: dllname, 
+    importc: "glWindowPos2fARB".}
+proc glWindowPos2iARB*(x: TGLint, y: TGLint){.dynlib: dllname, 
+    importc: "glWindowPos2iARB".}
+proc glWindowPos2sARB*(x: TGLshort, y: TGLshort){.dynlib: dllname, 
+    importc: "glWindowPos2sARB".}
+proc glWindowPos2dvARB*(p: PGLdouble){.dynlib: dllname, 
+                                       importc: "glWindowPos2dvARB".}
+proc glWindowPos2fvARB*(p: PGLfloat){.dynlib: dllname, 
+                                      importc: "glWindowPos2fvARB".}
+proc glWindowPos2ivARB*(p: PGLint){.dynlib: dllname, 
+                                    importc: "glWindowPos2ivARB".}
+proc glWindowPos2svARB*(p: PGLshort){.dynlib: dllname, 
+                                      importc: "glWindowPos2svARB".}
+proc glWindowPos3dARB*(x: TGLdouble, y: TGLdouble, z: TGLdouble){.
+    dynlib: dllname, importc: "glWindowPos3dARB".}
+proc glWindowPos3fARB*(x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, 
+    importc: "glWindowPos3fARB".}
+proc glWindowPos3iARB*(x: TGLint, y: TGLint, z: TGLint){.dynlib: dllname, 
+    importc: "glWindowPos3iARB".}
+proc glWindowPos3sARB*(x: TGLshort, y: TGLshort, z: TGLshort){.dynlib: dllname, 
+    importc: "glWindowPos3sARB".}
+proc glWindowPos3dvARB*(p: PGLdouble){.dynlib: dllname, 
+                                       importc: "glWindowPos3dvARB".}
+proc glWindowPos3fvARB*(p: PGLfloat){.dynlib: dllname, 
+                                      importc: "glWindowPos3fvARB".}
+proc glWindowPos3ivARB*(p: PGLint){.dynlib: dllname, 
+                                    importc: "glWindowPos3ivARB".}
+proc glWindowPos3svARB*(p: PGLshort){.dynlib: dllname, 
+                                      importc: "glWindowPos3svARB".}
+proc glBlendEquationSeparate*(modeRGB: TGLenum, modeAlpha: TGLenum){.
+    dynlib: dllname, importc: "glBlendEquationSeparate".}
+proc glDrawBuffers*(n: TGLsizei, bufs: PGLenum){.dynlib: dllname, 
+    importc: "glDrawBuffers".}
+proc glStencilOpSeparate*(face: TGLenum, sfail: TGLenum, dpfail: TGLenum, 
+                          dppass: TGLenum){.dynlib: dllname, 
+    importc: "glStencilOpSeparate".}
+proc glStencilFuncSeparate*(frontfunc: TGLenum, backfunc: TGLenum, 
+                            theRef: TGLint, mask: TGLuint){.dynlib: dllname, 
+    importc: "glStencilFuncSeparate".}
+proc glStencilMaskSeparate*(face: TGLenum, mask: TGLuint){.dynlib: dllname, 
+    importc: "glStencilMaskSeparate".}
+proc glAttachShader*(theProgram: TGLuint, shader: TGLuint){.dynlib: dllname, 
+    importc: "glAttachShader".}
+proc glBindAttribLocation*(theProgram: TGLuint, index: TGLuint, name: PGLchar){.
+    dynlib: dllname, importc: "glBindAttribLocation".}
+proc glCompileShader*(shader: TGLuint){.dynlib: dllname, 
+                                        importc: "glCompileShader".}
+proc glCreateProgram*(): TGLuint{.dynlib: dllname, importc: "glCreateProgram".}
+proc glCreateShader*(thetype: TGLenum): TGLuint{.dynlib: dllname, 
+    importc: "glCreateShader".}
+proc glDeleteProgram*(theProgram: TGLuint){.dynlib: dllname, 
+    importc: "glDeleteProgram".}
+proc glDeleteShader*(shader: TGLuint){.dynlib: dllname, 
+                                       importc: "glDeleteShader".}
+proc glDetachShader*(theProgram: TGLuint, shader: TGLuint){.dynlib: dllname, 
+    importc: "glDetachShader".}
+proc glDisableVertexAttribArray*(index: TGLuint){.dynlib: dllname, 
+    importc: "glDisableVertexAttribArray".}
+proc glEnableVertexAttribArray*(index: TGLuint){.dynlib: dllname, 
+    importc: "glEnableVertexAttribArray".}
+proc glGetActiveAttrib*(theProgram: TGLuint, index: TGLuint, bufSize: TGLsizei, 
+                        len: PGLsizei, size: PGLint, thetype: PGLenum, 
+                        name: PGLchar){.dynlib: dllname, 
+                                        importc: "glGetActiveAttrib".}
+proc glGetActiveUniform*(theProgram: TGLuint, index: TGLuint, bufSize: TGLsizei, 
+                         len: PGLsizei, size: PGLint, thetype: PGLenum, 
+                         name: PGLchar){.dynlib: dllname, 
+    importc: "glGetActiveUniform".}
+proc glGetAttachedShaders*(theProgram: TGLuint, maxCount: TGLsizei, 
+                           count: PGLsizei, obj: PGLuint){.dynlib: dllname, 
+    importc: "glGetAttachedShaders".}
+proc glGetAttribLocation*(theProgram: TGLuint, name: PGLchar): TGLint{.
+    dynlib: dllname, importc: "glGetAttribLocation".}
+proc glGetProgramiv*(theProgram: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetProgramiv".}
+proc glGetProgramInfoLog*(theProgram: TGLuint, bufSize: TGLsizei, len: PGLsizei, 
+                          infoLog: PGLchar){.dynlib: dllname, 
+    importc: "glGetProgramInfoLog".}
+proc glGetShaderiv*(shader: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetShaderiv".}
+proc glGetShaderInfoLog*(shader: TGLuint, bufSize: TGLsizei, len: PGLsizei, 
+                         infoLog: PGLchar){.dynlib: dllname, 
+    importc: "glGetShaderInfoLog".}
+proc glGetShaderSource*(shader: TGLuint, bufSize: TGLsizei, len: PGLsizei, 
+                        source: PGLchar){.dynlib: dllname, 
+    importc: "glGetShaderSource".}
+proc glGetUniformLocation*(theProgram: TGLuint, name: PGLchar): TGLint{.
+    dynlib: dllname, importc: "glGetUniformLocation".}
+proc glGetUniformfv*(theProgram: TGLuint, location: TGLint, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetUniformfv".}
+proc glGetUniformiv*(theProgram: TGLuint, location: TGLint, params: PGLint){.
+    dynlib: dllname, importc: "glGetUniformiv".}
+proc glGetVertexAttribdv*(index: TGLuint, pname: TGLenum, params: PGLdouble){.
+    dynlib: dllname, importc: "glGetVertexAttribdv".}
+proc glGetVertexAttribfv*(index: TGLuint, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetVertexAttribfv".}
+proc glGetVertexAttribiv*(index: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetVertexAttribiv".}
+proc glGetVertexAttribPointerv*(index: TGLuint, pname: TGLenum, pointer: PGLvoid){.
+    dynlib: dllname, importc: "glGetVertexAttribPointerv".}
+proc glIsProgram*(theProgram: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsProgram".}
+proc glIsShader*(shader: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsShader".}
+proc glLinkProgram*(theProgram: TGLuint){.dynlib: dllname, 
+    importc: "glLinkProgram".}
+proc glShaderSource*(shader: TGLuint, count: TGLsizei, str: PGLchar, len: PGLint){.
+    dynlib: dllname, importc: "glShaderSource".}
+proc glUseProgram*(theProgram: TGLuint){.dynlib: dllname, 
+    importc: "glUseProgram".}
+proc glUniform1f*(location: TGLint, v0: TGLfloat){.dynlib: dllname, 
+    importc: "glUniform1f".}
+proc glUniform2f*(location: TGLint, v0: TGLfloat, v1: TGLfloat){.
+    dynlib: dllname, importc: "glUniform2f".}
+proc glUniform3f*(location: TGLint, v0: TGLfloat, v1: TGLfloat, v2: TGLfloat){.
+    dynlib: dllname, importc: "glUniform3f".}
+proc glUniform4f*(location: TGLint, v0: TGLfloat, v1: TGLfloat, v2: TGLfloat, 
+                  v3: TGLfloat){.dynlib: dllname, importc: "glUniform4f".}
+proc glUniform1i*(location: TGLint, v0: TGLint){.dynlib: dllname, 
+    importc: "glUniform1i".}
+proc glUniform2i*(location: TGLint, v0: TGLint, v1: TGLint){.dynlib: dllname, 
+    importc: "glUniform2i".}
+proc glUniform3i*(location: TGLint, v0: TGLint, v1: TGLint, v2: TGLint){.
+    dynlib: dllname, importc: "glUniform3i".}
+proc glUniform4i*(location: TGLint, v0: TGLint, v1: TGLint, v2: TGLint, 
+                  v3: TGLint){.dynlib: dllname, importc: "glUniform4i".}
+proc glUniform1fv*(location: TGLint, count: TGLsizei, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniform1fv".}
+proc glUniform2fv*(location: TGLint, count: TGLsizei, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniform2fv".}
+proc glUniform3fv*(location: TGLint, count: TGLsizei, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniform3fv".}
+proc glUniform4fv*(location: TGLint, count: TGLsizei, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniform4fv".}
+proc glUniform1iv*(location: TGLint, count: TGLsizei, value: PGLint){.
+    dynlib: dllname, importc: "glUniform1iv".}
+proc glUniform2iv*(location: TGLint, count: TGLsizei, value: PGLint){.
+    dynlib: dllname, importc: "glUniform2iv".}
+proc glUniform3iv*(location: TGLint, count: TGLsizei, value: PGLint){.
+    dynlib: dllname, importc: "glUniform3iv".}
+proc glUniform4iv*(location: TGLint, count: TGLsizei, value: PGLint){.
+    dynlib: dllname, importc: "glUniform4iv".}
+proc glUniformMatrix2fv*(location: TGLint, count: TGLsizei, 
+                         transpose: TGLboolean, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniformMatrix2fv".}
+proc glUniformMatrix3fv*(location: TGLint, count: TGLsizei, 
+                         transpose: TGLboolean, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniformMatrix3fv".}
+proc glUniformMatrix4fv*(location: TGLint, count: TGLsizei, 
+                         transpose: TGLboolean, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniformMatrix4fv".}
+proc glValidateProgram*(theProgram: TGLuint){.dynlib: dllname, 
+    importc: "glValidateProgram".}
+proc glVertexAttrib1d*(index: TGLuint, x: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib1d".}
+proc glVertexAttrib1dv*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib1dv".}
+proc glVertexAttrib1f*(index: TGLuint, x: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib1f".}
+proc glVertexAttrib1fv*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib1fv".}
+proc glVertexAttrib1s*(index: TGLuint, x: TGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib1s".}
+proc glVertexAttrib1sv*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib1sv".}
+proc glVertexAttrib2d*(index: TGLuint, x: TGLdouble, y: TGLdouble){.
+    dynlib: dllname, importc: "glVertexAttrib2d".}
+proc glVertexAttrib2dv*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib2dv".}
+proc glVertexAttrib2f*(index: TGLuint, x: TGLfloat, y: TGLfloat){.
+    dynlib: dllname, importc: "glVertexAttrib2f".}
+proc glVertexAttrib2fv*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib2fv".}
+proc glVertexAttrib2s*(index: TGLuint, x: TGLshort, y: TGLshort){.
+    dynlib: dllname, importc: "glVertexAttrib2s".}
+proc glVertexAttrib2sv*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib2sv".}
+proc glVertexAttrib3d*(index: TGLuint, x: TGLdouble, y: TGLdouble, z: TGLdouble){.
+    dynlib: dllname, importc: "glVertexAttrib3d".}
+proc glVertexAttrib3dv*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib3dv".}
+proc glVertexAttrib3f*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glVertexAttrib3f".}
+proc glVertexAttrib3fv*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib3fv".}
+proc glVertexAttrib3s*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort){.
+    dynlib: dllname, importc: "glVertexAttrib3s".}
+proc glVertexAttrib3sv*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib3sv".}
+proc glVertexAttrib4Nbv*(index: TGLuint, v: PGLbyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4Nbv".}
+proc glVertexAttrib4Niv*(index: TGLuint, v: PGLint){.dynlib: dllname, 
+    importc: "glVertexAttrib4Niv".}
+proc glVertexAttrib4Nsv*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib4Nsv".}
+proc glVertexAttrib4Nub*(index: TGLuint, x: TGLubyte, y: TGLubyte, z: TGLubyte, 
+                         w: TGLubyte){.dynlib: dllname, 
+                                       importc: "glVertexAttrib4Nub".}
+proc glVertexAttrib4Nubv*(index: TGLuint, v: PGLubyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4Nubv".}
+proc glVertexAttrib4Nuiv*(index: TGLuint, v: PGLuint){.dynlib: dllname, 
+    importc: "glVertexAttrib4Nuiv".}
+proc glVertexAttrib4Nusv*(index: TGLuint, v: PGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib4Nusv".}
+proc glVertexAttrib4bv*(index: TGLuint, v: PGLbyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4bv".}
+proc glVertexAttrib4d*(index: TGLuint, x: TGLdouble, y: TGLdouble, z: TGLdouble, 
+                       w: TGLdouble){.dynlib: dllname, 
+                                      importc: "glVertexAttrib4d".}
+proc glVertexAttrib4dv*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib4dv".}
+proc glVertexAttrib4f*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat, 
+                       w: TGLfloat){.dynlib: dllname, 
+                                     importc: "glVertexAttrib4f".}
+proc glVertexAttrib4fv*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib4fv".}
+proc glVertexAttrib4iv*(index: TGLuint, v: PGLint){.dynlib: dllname, 
+    importc: "glVertexAttrib4iv".}
+proc glVertexAttrib4s*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort, 
+                       w: TGLshort){.dynlib: dllname, 
+                                     importc: "glVertexAttrib4s".}
+proc glVertexAttrib4sv*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib4sv".}
+proc glVertexAttrib4ubv*(index: TGLuint, v: PGLubyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4ubv".}
+proc glVertexAttrib4uiv*(index: TGLuint, v: PGLuint){.dynlib: dllname, 
+    importc: "glVertexAttrib4uiv".}
+proc glVertexAttrib4usv*(index: TGLuint, v: PGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib4usv".}
+proc glVertexAttribPointer*(index: TGLuint, size: TGLint, thetype: TGLenum, 
+                            normalized: TGLboolean, stride: TGLsizei, 
+                            pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glVertexAttribPointer".}
+const 
+  GL_CONSTANT_COLOR* = 0x00008001
+  GL_ONE_MINUS_CONSTANT_COLOR* = 0x00008002
+  GL_CONSTANT_ALPHA* = 0x00008003
+  GL_ONE_MINUS_CONSTANT_ALPHA* = 0x00008004
+  constGL_BLEND_COLOR* = 0x00008005
+  GL_FUNC_ADD* = 0x00008006
+  GL_MIN* = 0x00008007
+  GL_MAX* = 0x00008008
+  constGL_BLEND_EQUATION* = 0x00008009
+  GL_FUNC_SUBTRACT* = 0x0000800A
+  GL_FUNC_REVERSE_SUBTRACT* = 0x0000800B
+  GL_CONVOLUTION_1D* = 0x00008010
+  GL_CONVOLUTION_2D* = 0x00008011
+  GL_SEPARABLE_2D* = 0x00008012
+  GL_CONVOLUTION_BORDER_MODE* = 0x00008013
+  GL_CONVOLUTION_FILTER_SCALE* = 0x00008014
+  GL_CONVOLUTION_FILTER_BIAS* = 0x00008015
+  GL_REDUCE* = 0x00008016
+  GL_CONVOLUTION_FORMAT* = 0x00008017
+  GL_CONVOLUTION_WIDTH* = 0x00008018
+  GL_CONVOLUTION_HEIGHT* = 0x00008019
+  GL_MAX_CONVOLUTION_WIDTH* = 0x0000801A
+  GL_MAX_CONVOLUTION_HEIGHT* = 0x0000801B
+  GL_POST_CONVOLUTION_RED_SCALE* = 0x0000801C
+  GL_POST_CONVOLUTION_GREEN_SCALE* = 0x0000801D
+  GL_POST_CONVOLUTION_BLUE_SCALE* = 0x0000801E
+  GL_POST_CONVOLUTION_ALPHA_SCALE* = 0x0000801F
+  GL_POST_CONVOLUTION_RED_BIAS* = 0x00008020
+  GL_POST_CONVOLUTION_GREEN_BIAS* = 0x00008021
+  GL_POST_CONVOLUTION_BLUE_BIAS* = 0x00008022
+  GL_POST_CONVOLUTION_ALPHA_BIAS* = 0x00008023
+  constGL_HISTOGRAM* = 0x00008024
+  GL_PROXY_HISTOGRAM* = 0x00008025
+  GL_HISTOGRAM_WIDTH* = 0x00008026
+  GL_HISTOGRAM_FORMAT* = 0x00008027
+  GL_HISTOGRAM_RED_SIZE* = 0x00008028
+  GL_HISTOGRAM_GREEN_SIZE* = 0x00008029
+  GL_HISTOGRAM_BLUE_SIZE* = 0x0000802A
+  GL_HISTOGRAM_ALPHA_SIZE* = 0x0000802B
+  GL_HISTOGRAM_LUMINANCE_SIZE* = 0x0000802C
+  GL_HISTOGRAM_SINK* = 0x0000802D
+  constGL_MINMAX* = 0x0000802E
+  GL_MINMAX_FORMAT* = 0x0000802F
+  GL_MINMAX_SINK* = 0x00008030
+  GL_TABLE_TOO_LARGE* = 0x00008031
+  GL_COLOR_MATRIX* = 0x000080B1
+  GL_COLOR_MATRIX_STACK_DEPTH* = 0x000080B2
+  GL_MAX_COLOR_MATRIX_STACK_DEPTH* = 0x000080B3
+  GL_POST_COLOR_MATRIX_RED_SCALE* = 0x000080B4
+  GL_POST_COLOR_MATRIX_GREEN_SCALE* = 0x000080B5
+  GL_POST_COLOR_MATRIX_BLUE_SCALE* = 0x000080B6
+  GL_POST_COLOR_MATRIX_ALPHA_SCALE* = 0x000080B7
+  GL_POST_COLOR_MATRIX_RED_BIAS* = 0x000080B8
+  GL_POST_COLOR_MATRIX_GREEN_BIAS* = 0x000080B9
+  GL_POST_COLOR_MATRIX_BLUE_BIAS* = 0x000080BA
+  GL_POST_COLOR_MATIX_ALPHA_BIAS* = 0x000080BB
+  constGL_COLOR_TABLE* = 0x000080D0
+  GL_POST_CONVOLUTION_COLOR_TABLE* = 0x000080D1
+  GL_POST_COLOR_MATRIX_COLOR_TABLE* = 0x000080D2
+  GL_PROXY_COLOR_TABLE* = 0x000080D3
+  GL_PROXY_POST_CONVOLUTION_COLOR_TABLE* = 0x000080D4
+  GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE* = 0x000080D5
+  GL_COLOR_TABLE_SCALE* = 0x000080D6
+  GL_COLOR_TABLE_BIAS* = 0x000080D7
+  GL_COLOR_TABLE_FORMAT* = 0x000080D8
+  GL_COLOR_TABLE_WIDTH* = 0x000080D9
+  GL_COLOR_TABLE_RED_SIZE* = 0x000080DA
+  GL_COLOR_TABLE_GREEN_SIZE* = 0x000080DB
+  GL_COLOR_TABLE_BLUE_SIZE* = 0x000080DC
+  GL_COLOR_TABLE_ALPHA_SIZE* = 0x000080DD
+  GL_COLOR_TABLE_LUMINANCE_SIZE* = 0x000080DE
+  GL_COLOR_TABLE_INTENSITY_SIZE* = 0x000080DF
+  GL_IGNORE_BORDER* = 0x00008150
+  GL_CONSTANT_BORDER* = 0x00008151
+  GL_WRAP_BORDER* = 0x00008152
+  GL_REPLICATE_BORDER* = 0x00008153
+  GL_CONVOLUTION_BORDER_COLOR* = 0x00008154
+
+proc glActiveTexture*(texture: TGLenum){.dynlib: dllname, 
+    importc: "glActiveTexture".}
+proc glClientActiveTexture*(texture: TGLenum){.dynlib: dllname, 
+    importc: "glClientActiveTexture".}
+proc glMultiTexCoord1d*(target: TGLenum, s: TGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord1d".}
+proc glMultiTexCoord1dv*(target: TGLenum, v: PGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord1dv".}
+proc glMultiTexCoord1f*(target: TGLenum, s: TGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord1f".}
+proc glMultiTexCoord1fv*(target: TGLenum, v: PGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord1fv".}
+proc glMultiTexCoord1i*(target: TGLenum, s: TGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord1i".}
+proc glMultiTexCoord1iv*(target: TGLenum, v: PGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord1iv".}
+proc glMultiTexCoord1s*(target: TGLenum, s: TGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord1s".}
+proc glMultiTexCoord1sv*(target: TGLenum, v: PGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord1sv".}
+proc glMultiTexCoord2d*(target: TGLenum, s: TGLdouble, t: TGLdouble){.
+    dynlib: dllname, importc: "glMultiTexCoord2d".}
+proc glMultiTexCoord2dv*(target: TGLenum, v: PGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord2dv".}
+proc glMultiTexCoord2f*(target: TGLenum, s: TGLfloat, t: TGLfloat){.
+    dynlib: dllname, importc: "glMultiTexCoord2f".}
+proc glMultiTexCoord2fv*(target: TGLenum, v: PGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord2fv".}
+proc glMultiTexCoord2i*(target: TGLenum, s: TGLint, t: TGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord2i".}
+proc glMultiTexCoord2iv*(target: TGLenum, v: PGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord2iv".}
+proc glMultiTexCoord2s*(target: TGLenum, s: TGLshort, t: TGLshort){.
+    dynlib: dllname, importc: "glMultiTexCoord2s".}
+proc glMultiTexCoord2sv*(target: TGLenum, v: PGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord2sv".}
+proc glMultiTexCoord3d*(target: TGLenum, s: TGLdouble, t: TGLdouble, 
+                        r: TGLdouble){.dynlib: dllname, 
+                                       importc: "glMultiTexCoord3d".}
+proc glMultiTexCoord3dv*(target: TGLenum, v: PGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord3dv".}
+proc glMultiTexCoord3f*(target: TGLenum, s: TGLfloat, t: TGLfloat, r: TGLfloat){.
+    dynlib: dllname, importc: "glMultiTexCoord3f".}
+proc glMultiTexCoord3fv*(target: TGLenum, v: PGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord3fv".}
+proc glMultiTexCoord3i*(target: TGLenum, s: TGLint, t: TGLint, r: TGLint){.
+    dynlib: dllname, importc: "glMultiTexCoord3i".}
+proc glMultiTexCoord3iv*(target: TGLenum, v: PGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord3iv".}
+proc glMultiTexCoord3s*(target: TGLenum, s: TGLshort, t: TGLshort, r: TGLshort){.
+    dynlib: dllname, importc: "glMultiTexCoord3s".}
+proc glMultiTexCoord3sv*(target: TGLenum, v: PGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord3sv".}
+proc glMultiTexCoord4d*(target: TGLenum, s: TGLdouble, t: TGLdouble, 
+                        r: TGLdouble, q: TGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord4d".}
+proc glMultiTexCoord4dv*(target: TGLenum, v: PGLdouble){.dynlib: dllname, 
+    importc: "glMultiTexCoord4dv".}
+proc glMultiTexCoord4f*(target: TGLenum, s: TGLfloat, t: TGLfloat, r: TGLfloat, 
+                        q: TGLfloat){.dynlib: dllname, 
+                                      importc: "glMultiTexCoord4f".}
+proc glMultiTexCoord4fv*(target: TGLenum, v: PGLfloat){.dynlib: dllname, 
+    importc: "glMultiTexCoord4fv".}
+proc glMultiTexCoord4i*(target: TGLenum, s: TGLint, t: TGLint, r: TGLint, 
+                        q: TGLint){.dynlib: dllname, 
+                                    importc: "glMultiTexCoord4i".}
+proc glMultiTexCoord4iv*(target: TGLenum, v: PGLint){.dynlib: dllname, 
+    importc: "glMultiTexCoord4iv".}
+proc glMultiTexCoord4s*(target: TGLenum, s: TGLshort, t: TGLshort, r: TGLshort, 
+                        q: TGLshort){.dynlib: dllname, 
+                                      importc: "glMultiTexCoord4s".}
+proc glMultiTexCoord4sv*(target: TGLenum, v: PGLshort){.dynlib: dllname, 
+    importc: "glMultiTexCoord4sv".}
+proc glLoadTransposeMatrixf*(m: PGLfloat){.dynlib: dllname, 
+    importc: "glLoadTransposeMatrixf".}
+proc glLoadTransposeMatrixd*(m: PGLdouble){.dynlib: dllname, 
+    importc: "glLoadTransposeMatrixd".}
+proc glMultTransposeMatrixf*(m: PGLfloat){.dynlib: dllname, 
+    importc: "glMultTransposeMatrixf".}
+proc glMultTransposeMatrixd*(m: PGLdouble){.dynlib: dllname, 
+    importc: "glMultTransposeMatrixd".}
+proc glSampleCoverage*(value: TGLclampf, invert: TGLboolean){.dynlib: dllname, 
+    importc: "glSampleCoverage".}
+proc glCompressedTexImage3D*(target: TGLenum, level: TGLint, 
+                             internalformat: TGLenum, width: TGLsizei, 
+                             height: TGLsizei, depth: TGLsizei, border: TGLint, 
+                             imageSize: TGLsizei, data: PGLvoid){.
+    dynlib: dllname, importc: "glCompressedTexImage3D".}
+proc glCompressedTexImage2D*(target: TGLenum, level: TGLint, 
+                             internalformat: TGLenum, width: TGLsizei, 
+                             height: TGLsizei, border: TGLint, 
+                             imageSize: TGLsizei, data: PGLvoid){.
+    dynlib: dllname, importc: "glCompressedTexImage2D".}
+proc glCompressedTexImage1D*(target: TGLenum, level: TGLint, 
+                             internalformat: TGLenum, width: TGLsizei, 
+                             border: TGLint, imageSize: TGLsizei, data: PGLvoid){.
+    dynlib: dllname, importc: "glCompressedTexImage1D".}
+proc glCompressedTexSubImage3D*(target: TGLenum, level: TGLint, xoffset: TGLint, 
+                                yoffset: TGLint, zoffset: TGLint, 
+                                width: TGLsizei, height: TGLsizei, 
+                                depth: TGLsizei, format: TGLenum, 
+                                imageSize: TGLsizei, data: PGLvoid){.
+    dynlib: dllname, importc: "glCompressedTexSubImage3D".}
+proc glCompressedTexSubImage2D*(target: TGLenum, level: TGLint, xoffset: TGLint, 
+                                yoffset: TGLint, width: TGLsizei, 
+                                height: TGLsizei, format: TGLenum, 
+                                imageSize: TGLsizei, data: PGLvoid){.
+    dynlib: dllname, importc: "glCompressedTexSubImage2D".}
+proc glCompressedTexSubImage1D*(target: TGLenum, level: TGLint, xoffset: TGLint, 
+                                width: TGLsizei, format: TGLenum, 
+                                imageSize: TGLsizei, data: PGLvoid){.
+    dynlib: dllname, importc: "glCompressedTexSubImage1D".}
+proc glGetCompressedTexImage*(target: TGLenum, level: TGLint, img: PGLvoid){.
+    dynlib: dllname, importc: "glGetCompressedTexImage".}
+  #***** GL_version_1_3 *****//
+const 
+  GL_TEXTURE0* = 0x000084C0
+  GL_TEXTURE1* = 0x000084C1
+  GL_TEXTURE2* = 0x000084C2
+  GL_TEXTURE3* = 0x000084C3
+  GL_TEXTURE4* = 0x000084C4
+  GL_TEXTURE5* = 0x000084C5
+  GL_TEXTURE6* = 0x000084C6
+  GL_TEXTURE7* = 0x000084C7
+  GL_TEXTURE8* = 0x000084C8
+  GL_TEXTURE9* = 0x000084C9
+  GL_TEXTURE10* = 0x000084CA
+  GL_TEXTURE11* = 0x000084CB
+  GL_TEXTURE12* = 0x000084CC
+  GL_TEXTURE13* = 0x000084CD
+  GL_TEXTURE14* = 0x000084CE
+  GL_TEXTURE15* = 0x000084CF
+  GL_TEXTURE16* = 0x000084D0
+  GL_TEXTURE17* = 0x000084D1
+  GL_TEXTURE18* = 0x000084D2
+  GL_TEXTURE19* = 0x000084D3
+  GL_TEXTURE20* = 0x000084D4
+  GL_TEXTURE21* = 0x000084D5
+  GL_TEXTURE22* = 0x000084D6
+  GL_TEXTURE23* = 0x000084D7
+  GL_TEXTURE24* = 0x000084D8
+  GL_TEXTURE25* = 0x000084D9
+  GL_TEXTURE26* = 0x000084DA
+  GL_TEXTURE27* = 0x000084DB
+  GL_TEXTURE28* = 0x000084DC
+  GL_TEXTURE29* = 0x000084DD
+  GL_TEXTURE30* = 0x000084DE
+  GL_TEXTURE31* = 0x000084DF
+  constGL_ACTIVE_TEXTURE* = 0x000084E0
+  constGL_CLIENT_ACTIVE_TEXTURE* = 0x000084E1
+  GL_MAX_TEXTURE_UNITS* = 0x000084E2
+  GL_TRANSPOSE_MODELVIEW_MATRIX* = 0x000084E3
+  GL_TRANSPOSE_PROJECTION_MATRIX* = 0x000084E4
+  GL_TRANSPOSE_TEXTURE_MATRIX* = 0x000084E5
+  GL_TRANSPOSE_COLOR_MATRIX* = 0x000084E6
+  GL_MULTISAMPLE* = 0x0000809D
+  GL_SAMPLE_ALPHA_TO_COVERAGE* = 0x0000809E
+  GL_SAMPLE_ALPHA_TO_ONE* = 0x0000809F
+  constGL_SAMPLE_COVERAGE* = 0x000080A0
+  GL_SAMPLE_BUFFERS* = 0x000080A8
+  GL_SAMPLES* = 0x000080A9
+  GL_SAMPLE_COVERAGE_VALUE* = 0x000080AA
+  GL_SAMPLE_COVERAGE_INVERT* = 0x000080AB
+  GL_MULTISAMPLE_BIT* = 0x20000000
+  GL_NORMAL_MAP* = 0x00008511
+  GL_REFLECTION_MAP* = 0x00008512
+  GL_TEXTURE_CUBE_MAP* = 0x00008513
+  GL_TEXTURE_BINDING_CUBE_MAP* = 0x00008514
+  GL_TEXTURE_CUBE_MAP_POSITIVE_X* = 0x00008515
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_X* = 0x00008516
+  GL_TEXTURE_CUBE_MAP_POSITIVE_Y* = 0x00008517
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_Y* = 0x00008518
+  GL_TEXTURE_CUBE_MAP_POSITIVE_Z* = 0x00008519
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_Z* = 0x0000851A
+  GL_PROXY_TEXTURE_CUBE_MAP* = 0x0000851B
+  GL_MAX_CUBE_MAP_TEXTURE_SIZE* = 0x0000851C
+  GL_COMPRESSED_ALPHA* = 0x000084E9
+  GL_COMPRESSED_LUMINANCE* = 0x000084EA
+  GL_COMPRESSED_LUMINANCE_ALPHA* = 0x000084EB
+  GL_COMPRESSED_INTENSITY* = 0x000084EC
+  GL_COMPRESSED_RGB* = 0x000084ED
+  GL_COMPRESSED_RGBA* = 0x000084EE
+  GL_TEXTURE_COMPRESSION_HINT* = 0x000084EF
+  GL_TEXTURE_COMPRESSED_IMAGE_SIZE* = 0x000086A0
+  GL_TEXTURE_COMPRESSED* = 0x000086A1
+  GL_NUM_COMPRESSED_TEXTURE_FORMATS* = 0x000086A2
+  GL_COMPRESSED_TEXTURE_FORMATS* = 0x000086A3
+  GL_CLAMP_TO_BORDER* = 0x0000812D
+  GL_CLAMP_TO_BORDER_SGIS* = 0x0000812D
+  GL_COMBINE* = 0x00008570
+  GL_COMBINE_RGB* = 0x00008571
+  GL_COMBINE_ALPHA* = 0x00008572
+  GL_SOURCE0_RGB* = 0x00008580
+  GL_SOURCE1_RGB* = 0x00008581
+  GL_SOURCE2_RGB* = 0x00008582
+  GL_SOURCE0_ALPHA* = 0x00008588
+  GL_SOURCE1_ALPHA* = 0x00008589
+  GL_SOURCE2_ALPHA* = 0x0000858A
+  GL_OPERAND0_RGB* = 0x00008590
+  GL_OPERAND1_RGB* = 0x00008591
+  GL_OPERAND2_RGB* = 0x00008592
+  GL_OPERAND0_ALPHA* = 0x00008598
+  GL_OPERAND1_ALPHA* = 0x00008599
+  GL_OPERAND2_ALPHA* = 0x0000859A
+  GL_RGB_SCALE* = 0x00008573
+  GL_ADD_SIGNED* = 0x00008574
+  GL_INTERPOLATE* = 0x00008575
+  GL_SUBTRACT* = 0x000084E7
+  GL_CONSTANT* = 0x00008576
+  GL_PRIMARY_COLOR* = 0x00008577
+  GL_PREVIOUS* = 0x00008578
+  GL_DOT3_RGB* = 0x000086AE
+  GL_DOT3_RGBA* = 0x000086AF
+
+const 
+  GL_TEXTURE0_ARB* = 0x000084C0
+  GL_TEXTURE1_ARB* = 0x000084C1
+  GL_TEXTURE2_ARB* = 0x000084C2
+  GL_TEXTURE3_ARB* = 0x000084C3
+  GL_TEXTURE4_ARB* = 0x000084C4
+  GL_TEXTURE5_ARB* = 0x000084C5
+  GL_TEXTURE6_ARB* = 0x000084C6
+  GL_TEXTURE7_ARB* = 0x000084C7
+  GL_TEXTURE8_ARB* = 0x000084C8
+  GL_TEXTURE9_ARB* = 0x000084C9
+  GL_TEXTURE10_ARB* = 0x000084CA
+  GL_TEXTURE11_ARB* = 0x000084CB
+  GL_TEXTURE12_ARB* = 0x000084CC
+  GL_TEXTURE13_ARB* = 0x000084CD
+  GL_TEXTURE14_ARB* = 0x000084CE
+  GL_TEXTURE15_ARB* = 0x000084CF
+  GL_TEXTURE16_ARB* = 0x000084D0
+  GL_TEXTURE17_ARB* = 0x000084D1
+  GL_TEXTURE18_ARB* = 0x000084D2
+  GL_TEXTURE19_ARB* = 0x000084D3
+  GL_TEXTURE20_ARB* = 0x000084D4
+  GL_TEXTURE21_ARB* = 0x000084D5
+  GL_TEXTURE22_ARB* = 0x000084D6
+  GL_TEXTURE23_ARB* = 0x000084D7
+  GL_TEXTURE24_ARB* = 0x000084D8
+  GL_TEXTURE25_ARB* = 0x000084D9
+  GL_TEXTURE26_ARB* = 0x000084DA
+  GL_TEXTURE27_ARB* = 0x000084DB
+  GL_TEXTURE28_ARB* = 0x000084DC
+  GL_TEXTURE29_ARB* = 0x000084DD
+  GL_TEXTURE30_ARB* = 0x000084DE
+  GL_TEXTURE31_ARB* = 0x000084DF
+  constGL_ACTIVE_TEXTURE_ARB* = 0x000084E0
+  constGL_CLIENT_ACTIVE_TEXTURE_ARB* = 0x000084E1
+  GL_MAX_TEXTURE_UNITS_ARB* = 0x000084E2
+  #***** GL_ARB_transpose_matrix *****//
+
+const 
+  GL_TRANSPOSE_MODELVIEW_MATRIX_ARB* = 0x000084E3
+  GL_TRANSPOSE_PROJECTION_MATRIX_ARB* = 0x000084E4
+  GL_TRANSPOSE_TEXTURE_MATRIX_ARB* = 0x000084E5
+  GL_TRANSPOSE_COLOR_MATRIX_ARB* = 0x000084E6
+
+proc glLoadTransposeMatrixfARB*(m: PGLfloat){.dynlib: dllname, 
+    importc: "glLoadTransposeMatrixfARB".}
+proc glLoadTransposeMatrixdARB*(m: PGLdouble){.dynlib: dllname, 
+    importc: "glLoadTransposeMatrixdARB".}
+proc glMultTransposeMatrixfARB*(m: PGLfloat){.dynlib: dllname, 
+    importc: "glMultTransposeMatrixfARB".}
+proc glMultTransposeMatrixdARB*(m: PGLdouble){.dynlib: dllname, 
+    importc: "glMultTransposeMatrixdARB".}
+const 
+  WGL_SAMPLE_BUFFERS_ARB* = 0x00002041
+  WGL_SAMPLES_ARB* = 0x00002042
+  GL_MULTISAMPLE_ARB* = 0x0000809D
+  GL_SAMPLE_ALPHA_TO_COVERAGE_ARB* = 0x0000809E
+  GL_SAMPLE_ALPHA_TO_ONE_ARB* = 0x0000809F
+  constGL_SAMPLE_COVERAGE_ARB* = 0x000080A0
+  GL_MULTISAMPLE_BIT_ARB* = 0x20000000
+  GL_SAMPLE_BUFFERS_ARB* = 0x000080A8
+  GL_SAMPLES_ARB* = 0x000080A9
+  GL_SAMPLE_COVERAGE_VALUE_ARB* = 0x000080AA
+  GL_SAMPLE_COVERAGE_INVERT_ARB* = 0x000080AB
+
+const 
+  GL_NORMAL_MAP_ARB* = 0x00008511
+  GL_REFLECTION_MAP_ARB* = 0x00008512
+  GL_TEXTURE_CUBE_MAP_ARB* = 0x00008513
+  GL_TEXTURE_BINDING_CUBE_MAP_ARB* = 0x00008514
+  GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB* = 0x00008515
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB* = 0x00008516
+  GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB* = 0x00008517
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB* = 0x00008518
+  GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB* = 0x00008519
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB* = 0x0000851A
+  GL_PROXY_TEXTURE_CUBE_MAP_ARB* = 0x0000851B
+  GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB* = 0x0000851C
+
+const 
+  GL_DEPTH_COMPONENT16_ARB* = 0x000081A5
+  GL_DEPTH_COMPONENT24_ARB* = 0x000081A6
+  GL_DEPTH_COMPONENT32_ARB* = 0x000081A7
+  GL_TEXTURE_DEPTH_SIZE_ARB* = 0x0000884A
+  GL_DEPTH_TEXTURE_MODE_ARB* = 0x0000884B
+  #***** GL_ARB_point_parameters *****//
+
+const 
+  GL_POINT_SIZE_MIN_ARB* = 0x00008126
+  GL_POINT_SIZE_MAX_ARB* = 0x00008127
+  GL_POINT_FADE_THRESHOLD_SIZE_ARB* = 0x00008128
+  GL_POINT_DISTANCE_ATTENUATION_ARB* = 0x00008129
+
+proc glPointParameterfARB*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glPointParameterfARB".}
+proc glPointParameterfvARB*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glPointParameterfvARB".}
+const 
+  GL_TEXTURE_COMPARE_MODE_ARB* = 0x0000884C
+  GL_TEXTURE_COMPARE_FUNC_ARB* = 0x0000884D
+  GL_COMPARE_R_TO_TEXTURE_ARB* = 0x0000884E
+
+const 
+  GL_TEXTURE_COMPARE_FAIL_VALUE_ARB* = 0x000080BF
+  GL_CLAMP_TO_BORDER_ARB* = 0x0000812D
+
+const 
+  GL_COMPRESSED_ALPHA_ARB* = 0x000084E9
+  GL_COMPRESSED_LUMINANCE_ARB* = 0x000084EA
+  GL_COMPRESSED_LUMINANCE_ALPHA_ARB* = 0x000084EB
+  GL_COMPRESSED_INTENSITY_ARB* = 0x000084EC
+  GL_COMPRESSED_RGB_ARB* = 0x000084ED
+  GL_COMPRESSED_RGBA_ARB* = 0x000084EE
+  GL_TEXTURE_COMPRESSION_HINT_ARB* = 0x000084EF
+  GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB* = 0x000086A0
+  GL_TEXTURE_COMPRESSED_ARB* = 0x000086A1
+  GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB* = 0x000086A2
+  GL_COMPRESSED_TEXTURE_FORMATS_ARB* = 0x000086A3
+
+proc glCompressedTexImage3DARB*(target: TGLenum, level: TGLint, 
+                                internalformat: TGLenum, width: TGLsizei, 
+                                height: TGLsizei, depth: TGLsizei, 
+                                border: TGLint, imageSize: TGLsizei, 
+                                data: PGLvoid){.dynlib: dllname, 
+    importc: "glCompressedTexImage3DARB".}
+proc glCompressedTexImage2DARB*(target: TGLenum, level: TGLint, 
+                                internalformat: TGLenum, width: TGLsizei, 
+                                height: TGLsizei, border: TGLint, 
+                                imageSize: TGLsizei, data: PGLvoid){.
+    dynlib: dllname, importc: "glCompressedTexImage2DARB".}
+proc glCompressedTexImage1DARB*(target: TGLenum, level: TGLint, 
+                                internalformat: TGLenum, width: TGLsizei, 
+                                border: TGLint, imageSize: TGLsizei, 
+                                data: PGLvoid){.dynlib: dllname, 
+    importc: "glCompressedTexImage1DARB".}
+proc glCompressedTexSubImage3DARB*(target: TGLenum, level: TGLint, 
+                                   xoffset: TGLint, yoffset: TGLint, 
+                                   zoffset: TGLint, width: TGLsizei, 
+                                   height: TGLsizei, depth: TGLsizei, 
+                                   format: TGLenum, imageSize: TGLsizei, 
+                                   data: PGLvoid){.dynlib: dllname, 
+    importc: "glCompressedTexSubImage3DARB".}
+proc glCompressedTexSubImage2DARB*(target: TGLenum, level: TGLint, 
+                                   xoffset: TGLint, yoffset: TGLint, 
+                                   width: TGLsizei, height: TGLsizei, 
+                                   format: TGLenum, imageSize: TGLsizei, 
+                                   data: PGLvoid){.dynlib: dllname, 
+    importc: "glCompressedTexSubImage2DARB".}
+proc glCompressedTexSubImage1DARB*(target: TGLenum, level: TGLint, 
+                                   xoffset: TGLint, width: TGLsizei, 
+                                   format: TGLenum, imageSize: TGLsizei, 
+                                   data: PGLvoid){.dynlib: dllname, 
+    importc: "glCompressedTexSubImage1DARB".}
+proc glGetCompressedTexImageARB*(target: TGLenum, lod: TGLint, img: PGLvoid){.
+    dynlib: dllname, importc: "glGetCompressedTexImageARB".}
+  #***** GL_ARB_texture_env_combine *****//
+const 
+  GL_COMBINE_ARB* = 0x00008570
+  GL_COMBINE_RGB_ARB* = 0x00008571
+  GL_COMBINE_ALPHA_ARB* = 0x00008572
+  GL_SOURCE0_RGB_ARB* = 0x00008580
+  GL_SOURCE1_RGB_ARB* = 0x00008581
+  GL_SOURCE2_RGB_ARB* = 0x00008582
+  GL_SOURCE0_ALPHA_ARB* = 0x00008588
+  GL_SOURCE1_ALPHA_ARB* = 0x00008589
+  GL_SOURCE2_ALPHA_ARB* = 0x0000858A
+  GL_OPERAND0_RGB_ARB* = 0x00008590
+  GL_OPERAND1_RGB_ARB* = 0x00008591
+  GL_OPERAND2_RGB_ARB* = 0x00008592
+  GL_OPERAND0_ALPHA_ARB* = 0x00008598
+  GL_OPERAND1_ALPHA_ARB* = 0x00008599
+  GL_OPERAND2_ALPHA_ARB* = 0x0000859A
+  GL_RGB_SCALE_ARB* = 0x00008573
+  GL_ADD_SIGNED_ARB* = 0x00008574
+  GL_INTERPOLATE_ARB* = 0x00008575
+  GL_SUBTRACT_ARB* = 0x000084E7
+  GL_CONSTANT_ARB* = 0x00008576
+  GL_PRIMARY_COLOR_ARB* = 0x00008577
+  GL_PREVIOUS_ARB* = 0x00008578
+  #***** GL_ARB_texture_env_crossbar *****//
+  #***** GL_ARB_texture_env_dot3 *****//
+
+const 
+  GL_DOT3_RGB_ARB* = 0x000086AE
+  GL_DOT3_RGBA_ARB* = 0x000086AF
+  #***** GL_ARB_texture_mirrored_repeat *****//
+
+const 
+  GL_MIRRORED_REPEAT_ARB* = 0x00008370
+  #***** GL_ARB_vertex_blend *****//
+
+const 
+  GL_MAX_VERTEX_UNITS_ARB* = 0x000086A4
+  GL_ACTIVE_VERTEX_UNITS_ARB* = 0x000086A5
+  GL_WEIGHT_SUM_UNITY_ARB* = 0x000086A6
+  constGL_VERTEX_BLEND_ARB* = 0x000086A7
+  GL_MODELVIEW0_ARB* = 0x00001700
+  GL_MODELVIEW1_ARB* = 0x0000850A
+  GL_MODELVIEW2_ARB* = 0x00008722
+  GL_MODELVIEW3_ARB* = 0x00008723
+  GL_MODELVIEW4_ARB* = 0x00008724
+  GL_MODELVIEW5_ARB* = 0x00008725
+  GL_MODELVIEW6_ARB* = 0x00008726
+  GL_MODELVIEW7_ARB* = 0x00008727
+  GL_MODELVIEW8_ARB* = 0x00008728
+  GL_MODELVIEW9_ARB* = 0x00008729
+  GL_MODELVIEW10_ARB* = 0x0000872A
+  GL_MODELVIEW11_ARB* = 0x0000872B
+  GL_MODELVIEW12_ARB* = 0x0000872C
+  GL_MODELVIEW13_ARB* = 0x0000872D
+  GL_MODELVIEW14_ARB* = 0x0000872E
+  GL_MODELVIEW15_ARB* = 0x0000872F
+  GL_MODELVIEW16_ARB* = 0x00008730
+  GL_MODELVIEW17_ARB* = 0x00008731
+  GL_MODELVIEW18_ARB* = 0x00008732
+  GL_MODELVIEW19_ARB* = 0x00008733
+  GL_MODELVIEW20_ARB* = 0x00008734
+  GL_MODELVIEW21_ARB* = 0x00008735
+  GL_MODELVIEW22_ARB* = 0x00008736
+  GL_MODELVIEW23_ARB* = 0x00008737
+  GL_MODELVIEW24_ARB* = 0x00008738
+  GL_MODELVIEW25_ARB* = 0x00008739
+  GL_MODELVIEW26_ARB* = 0x0000873A
+  GL_MODELVIEW27_ARB* = 0x0000873B
+  GL_MODELVIEW28_ARB* = 0x0000873C
+  GL_MODELVIEW29_ARB* = 0x0000873D
+  GL_MODELVIEW30_ARB* = 0x0000873E
+  GL_MODELVIEW31_ARB* = 0x0000873F
+  GL_CURRENT_WEIGHT_ARB* = 0x000086A8
+  GL_WEIGHT_ARRAY_TYPE_ARB* = 0x000086A9
+  GL_WEIGHT_ARRAY_STRIDE_ARB* = 0x000086AA
+  GL_WEIGHT_ARRAY_SIZE_ARB* = 0x000086AB
+  GL_WEIGHT_ARRAY_POINTER_ARB* = 0x000086AC
+  GL_WEIGHT_ARRAY_ARB* = 0x000086AD
+
+const 
+  GL_VERTEX_PROGRAM_ARB* = 0x00008620
+  GL_VERTEX_PROGRAM_POINT_SIZE_ARB* = 0x00008642
+  GL_VERTEX_PROGRAM_TWO_SIDE_ARB* = 0x00008643
+  GL_COLOR_SUM_ARB* = 0x00008458
+  GL_PROGRAM_FORMAT_ASCII_ARB* = 0x00008875
+  GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB* = 0x00008622
+  GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB* = 0x00008623
+  GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB* = 0x00008624
+  GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB* = 0x00008625
+  GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB* = 0x0000886A
+  GL_CURRENT_VERTEX_ATTRIB_ARB* = 0x00008626
+  GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB* = 0x00008645
+  GL_PROGRAM_LENGTH_ARB* = 0x00008627
+  GL_PROGRAM_FORMAT_ARB* = 0x00008876
+  GL_PROGRAM_BINDING_ARB* = 0x00008677
+  GL_PROGRAM_INSTRUCTIONS_ARB* = 0x000088A0
+  GL_MAX_PROGRAM_INSTRUCTIONS_ARB* = 0x000088A1
+  GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB* = 0x000088A2
+  GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB* = 0x000088A3
+  GL_PROGRAM_TEMPORARIES_ARB* = 0x000088A4
+  GL_MAX_PROGRAM_TEMPORARIES_ARB* = 0x000088A5
+  GL_PROGRAM_NATIVE_TEMPORARIES_ARB* = 0x000088A6
+  GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB* = 0x000088A7
+  GL_PROGRAM_PARAMETERS_ARB* = 0x000088A8
+  GL_MAX_PROGRAM_PARAMETERS_ARB* = 0x000088A9
+  GL_PROGRAM_NATIVE_PARAMETERS_ARB* = 0x000088AA
+  GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB* = 0x000088AB
+  GL_PROGRAM_ATTRIBS_ARB* = 0x000088AC
+  GL_MAX_PROGRAM_ATTRIBS_ARB* = 0x000088AD
+  GL_PROGRAM_NATIVE_ATTRIBS_ARB* = 0x000088AE
+  GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB* = 0x000088AF
+  GL_PROGRAM_ADDRESS_REGISTERS_ARB* = 0x000088B0
+  GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB* = 0x000088B1
+  GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB* = 0x000088B2
+  GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB* = 0x000088B3
+  GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB* = 0x000088B4
+  GL_MAX_PROGRAM_ENV_PARAMETERS_ARB* = 0x000088B5
+  GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB* = 0x000088B6
+  constGL_PROGRAM_STRING_ARB* = 0x00008628
+  GL_PROGRAM_ERROR_POSITION_ARB* = 0x0000864B
+  GL_CURRENT_MATRIX_ARB* = 0x00008641
+  GL_TRANSPOSE_CURRENT_MATRIX_ARB* = 0x000088B7
+  GL_CURRENT_MATRIX_STACK_DEPTH_ARB* = 0x00008640
+  GL_MAX_VERTEX_ATTRIBS_ARB* = 0x00008869
+  GL_MAX_PROGRAM_MATRICES_ARB* = 0x0000862F
+  GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB* = 0x0000862E
+  GL_PROGRAM_ERROR_STRING_ARB* = 0x00008874
+  GL_MATRIX0_ARB* = 0x000088C0
+  GL_MATRIX1_ARB* = 0x000088C1
+  GL_MATRIX2_ARB* = 0x000088C2
+  GL_MATRIX3_ARB* = 0x000088C3
+  GL_MATRIX4_ARB* = 0x000088C4
+  GL_MATRIX5_ARB* = 0x000088C5
+  GL_MATRIX6_ARB* = 0x000088C6
+  GL_MATRIX7_ARB* = 0x000088C7
+  GL_MATRIX8_ARB* = 0x000088C8
+  GL_MATRIX9_ARB* = 0x000088C9
+  GL_MATRIX10_ARB* = 0x000088CA
+  GL_MATRIX11_ARB* = 0x000088CB
+  GL_MATRIX12_ARB* = 0x000088CC
+  GL_MATRIX13_ARB* = 0x000088CD
+  GL_MATRIX14_ARB* = 0x000088CE
+  GL_MATRIX15_ARB* = 0x000088CF
+  GL_MATRIX16_ARB* = 0x000088D0
+  GL_MATRIX17_ARB* = 0x000088D1
+  GL_MATRIX18_ARB* = 0x000088D2
+  GL_MATRIX19_ARB* = 0x000088D3
+  GL_MATRIX20_ARB* = 0x000088D4
+  GL_MATRIX21_ARB* = 0x000088D5
+  GL_MATRIX22_ARB* = 0x000088D6
+  GL_MATRIX23_ARB* = 0x000088D7
+  GL_MATRIX24_ARB* = 0x000088D8
+  GL_MATRIX25_ARB* = 0x000088D9
+  GL_MATRIX26_ARB* = 0x000088DA
+  GL_MATRIX27_ARB* = 0x000088DB
+  GL_MATRIX28_ARB* = 0x000088DC
+  GL_MATRIX29_ARB* = 0x000088DD
+  GL_MATRIX30_ARB* = 0x000088DE
+  GL_MATRIX31_ARB* = 0x000088DF
+
+const 
+  GL_422_EXT* = 0x000080CC
+  GL_422_REV_EXT* = 0x000080CD
+  GL_422_AVERAGE_EXT* = 0x000080CE
+  GL_422_REV_AVERAGE_EXT* = 0x000080CF
+  #***** GL_EXT_abgr *****//
+
+const 
+  GL_ABGR_EXT* = 0x00008000
+  #***** GL_EXT_bgra *****//
+
+const 
+  GL_BGR_EXT* = 0x000080E0
+  GL_BGRA_EXT* = 0x000080E1
+  #***** GL_EXT_blend_color *****//
+
+const 
+  GL_CONSTANT_COLOR_EXT* = 0x00008001
+  GL_ONE_MINUS_CONSTANT_COLOR_EXT* = 0x00008002
+  GL_CONSTANT_ALPHA_EXT* = 0x00008003
+  GL_ONE_MINUS_CONSTANT_ALPHA_EXT* = 0x00008004
+  constGL_BLEND_COLOR_EXT* = 0x00008005
+
+proc glBlendColorEXT*(red: TGLclampf, green: TGLclampf, blue: TGLclampf, 
+                      alpha: TGLclampf){.dynlib: dllname, 
+    importc: "glBlendColorEXT".}
+  #***** GL_EXT_blend_func_separate *****//
+const 
+  GL_BLEND_DST_RGB_EXT* = 0x000080C8
+  GL_BLEND_SRC_RGB_EXT* = 0x000080C9
+  GL_BLEND_DST_ALPHA_EXT* = 0x000080CA
+  GL_BLEND_SRC_ALPHA_EXT* = 0x000080CB
+
+proc glBlendFuncSeparateEXT*(sfactorRGB: TGLenum, dfactorRGB: TGLenum, 
+                             sfactorAlpha: TGLenum, dfactorAlpha: TGLenum){.
+    dynlib: dllname, importc: "glBlendFuncSeparateEXT".}
+  #***** GL_EXT_blend_logic_op *****//
+  #***** GL_EXT_blend_minmax *****//
+const 
+  GL_FUNC_ADD_EXT* = 0x00008006
+  GL_MIN_EXT* = 0x00008007
+  GL_MAX_EXT* = 0x00008008
+  constGL_BLEND_EQUATION_EXT* = 0x00008009
+
+proc glBlendEquationEXT*(mode: TGLenum){.dynlib: dllname, 
+    importc: "glBlendEquationEXT".}
+  #***** GL_EXT_blend_subtract *****//
+const 
+  GL_FUNC_SUBTRACT_EXT* = 0x0000800A
+  GL_FUNC_REVERSE_SUBTRACT_EXT* = 0x0000800B
+  #***** GL_EXT_clip_volume_hint *****//
+
+const 
+  GL_CLIP_VOLUME_CLIPPING_HINT_EXT* = 0x000080F0
+  #***** GL_EXT_color_subtable *****//
+
+proc glColorSubTableEXT*(target: TGLenum, start: TGLsizei, count: TGLsizei, 
+                         format: TGLenum, thetype: TGLenum, data: PGLvoid){.
+    dynlib: dllname, importc: "glColorSubTableEXT".}
+proc glCopyColorSubTableEXT*(target: TGLenum, start: TGLsizei, x: TGLint, 
+                             y: TGLint, width: TGLsizei){.dynlib: dllname, 
+    importc: "glCopyColorSubTableEXT".}
+  #***** GL_EXT_compiled_vertex_array *****//
+const 
+  GL_ARRAY_ELEMENT_LOCK_FIRST_EXT* = 0x000081A8
+  GL_ARRAY_ELEMENT_LOCK_COUNT_EXT* = 0x000081A9
+
+proc glLockArraysEXT*(first: TGLint, count: TGLsizei){.dynlib: dllname, 
+    importc: "glLockArraysEXT".}
+proc glUnlockArraysEXT*(){.dynlib: dllname, importc: "glUnlockArraysEXT".}
+  #***** GL_EXT_convolution *****//
+const 
+  GL_CONVOLUTION_1D_EXT* = 0x00008010
+  GL_CONVOLUTION_2D_EXT* = 0x00008011
+  GL_SEPARABLE_2D_EXT* = 0x00008012
+  GL_CONVOLUTION_BORDER_MODE_EXT* = 0x00008013
+  GL_CONVOLUTION_FILTER_SCALE_EXT* = 0x00008014
+  GL_CONVOLUTION_FILTER_BIAS_EXT* = 0x00008015
+  GL_REDUCE_EXT* = 0x00008016
+  GL_CONVOLUTION_FORMAT_EXT* = 0x00008017
+  GL_CONVOLUTION_WIDTH_EXT* = 0x00008018
+  GL_CONVOLUTION_HEIGHT_EXT* = 0x00008019
+  GL_MAX_CONVOLUTION_WIDTH_EXT* = 0x0000801A
+  GL_MAX_CONVOLUTION_HEIGHT_EXT* = 0x0000801B
+  GL_POST_CONVOLUTION_RED_SCALE_EXT* = 0x0000801C
+  GL_POST_CONVOLUTION_GREEN_SCALE_EXT* = 0x0000801D
+  GL_POST_CONVOLUTION_BLUE_SCALE_EXT* = 0x0000801E
+  GL_POST_CONVOLUTION_ALPHA_SCALE_EXT* = 0x0000801F
+  GL_POST_CONVOLUTION_RED_BIAS_EXT* = 0x00008020
+  GL_POST_CONVOLUTION_GREEN_BIAS_EXT* = 0x00008021
+  GL_POST_CONVOLUTION_BLUE_BIAS_EXT* = 0x00008022
+  GL_POST_CONVOLUTION_ALPHA_BIAS_EXT* = 0x00008023
+
+proc glConvolutionFilter1DEXT*(target: TGLenum, internalformat: TGLenum, 
+                               width: TGLsizei, format: TGLenum, 
+                               thetype: TGLenum, image: PGLvoid){.
+    dynlib: dllname, importc: "glConvolutionFilter1DEXT".}
+proc glConvolutionFilter2DEXT*(target: TGLenum, internalformat: TGLenum, 
+                               width: TGLsizei, height: TGLsizei, 
+                               format: TGLenum, thetype: TGLenum, image: PGLvoid){.
+    dynlib: dllname, importc: "glConvolutionFilter2DEXT".}
+proc glCopyConvolutionFilter1DEXT*(target: TGLenum, internalformat: TGLenum, 
+                                   x: TGLint, y: TGLint, width: TGLsizei){.
+    dynlib: dllname, importc: "glCopyConvolutionFilter1DEXT".}
+proc glCopyConvolutionFilter2DEXT*(target: TGLenum, internalformat: TGLenum, 
+                                   x: TGLint, y: TGLint, width: TGLsizei, 
+                                   height: TGLsizei){.dynlib: dllname, 
+    importc: "glCopyConvolutionFilter2DEXT".}
+proc glGetConvolutionFilterEXT*(target: TGLenum, format: TGLenum, 
+                                thetype: TGLenum, image: PGLvoid){.
+    dynlib: dllname, importc: "glGetConvolutionFilterEXT".}
+proc glSeparableFilter2DEXT*(target: TGLenum, internalformat: TGLenum, 
+                             width: TGLsizei, height: TGLsizei, format: TGLenum, 
+                             thetype: TGLenum, row: PGLvoid, column: PGLvoid){.
+    dynlib: dllname, importc: "glSeparableFilter2DEXT".}
+proc glGetSeparableFilterEXT*(target: TGLenum, format: TGLenum, 
+                              thetype: TGLenum, row: PGLvoid, column: PGLvoid, 
+                              span: PGLvoid){.dynlib: dllname, 
+    importc: "glGetSeparableFilterEXT".}
+proc glConvolutionParameteriEXT*(target: TGLenum, pname: TGLenum, param: TGLint){.
+    dynlib: dllname, importc: "glConvolutionParameteriEXT".}
+proc glConvolutionParameterivEXT*(target: TGLenum, pname: TGLenum, 
+                                  params: PGLint){.dynlib: dllname, 
+    importc: "glConvolutionParameterivEXT".}
+proc glConvolutionParameterfEXT*(target: TGLenum, pname: TGLenum, 
+                                 param: TGLfloat){.dynlib: dllname, 
+    importc: "glConvolutionParameterfEXT".}
+proc glConvolutionParameterfvEXT*(target: TGLenum, pname: TGLenum, 
+                                  params: PGLfloat){.dynlib: dllname, 
+    importc: "glConvolutionParameterfvEXT".}
+proc glGetConvolutionParameterivEXT*(target: TGLenum, pname: TGLenum, 
+                                     params: PGLint){.dynlib: dllname, 
+    importc: "glGetConvolutionParameterivEXT".}
+proc glGetConvolutionParameterfvEXT*(target: TGLenum, pname: TGLenum, 
+                                     params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetConvolutionParameterfvEXT".}
+  #***** GL_EXT_fog_coord *****//
+const 
+  GL_FOG_COORDINATE_SOURCE_EXT* = 0x00008450
+  GL_FOG_COORDINATE_EXT* = 0x00008451
+  GL_FRAGMENT_DEPTH_EXT* = 0x00008452
+  GL_CURRENT_FOG_COORDINATE_EXT* = 0x00008453
+  GL_FOG_COORDINATE_ARRAY_TYPE_EXT* = 0x00008454
+  GL_FOG_COORDINATE_ARRAY_STRIDE_EXT* = 0x00008455
+  GL_FOG_COORDINATE_ARRAY_POINTER_EXT* = 0x00008456
+  GL_FOG_COORDINATE_ARRAY_EXT* = 0x00008457
+
+proc glFogCoordfEXfloat*(coord: TGLfloat){.dynlib: dllname, 
+    importc: "glFogCoordfEXfloat".}
+proc glFogCoorddEXdouble*(coord: TGLdouble){.dynlib: dllname, 
+    importc: "glFogCoorddEXdouble".}
+proc glFogCoordfvEXfloat*(coord: TGLfloat){.dynlib: dllname, 
+    importc: "glFogCoordfvEXfloat".}
+proc glFogCoorddvEXdouble*(coord: TGLdouble){.dynlib: dllname, 
+    importc: "glFogCoorddvEXdouble".}
+proc glFogCoordPointerEXT*(thetype: TGLenum, stride: TGLsizei, pointer: PGLvoid){.
+    dynlib: dllname, importc: "glFogCoordPointerEXT".}
+  #***** GL_EXT_histogram *****//
+const 
+  constGL_HISTOGRAM_EXT* = 0x00008024
+  GL_PROXY_HISTOGRAM_EXT* = 0x00008025
+  GL_HISTOGRAM_WIDTH_EXT* = 0x00008026
+  GL_HISTOGRAM_FORMAT_EXT* = 0x00008027
+  GL_HISTOGRAM_RED_SIZE_EXT* = 0x00008028
+  GL_HISTOGRAM_GREEN_SIZE_EXT* = 0x00008029
+  GL_HISTOGRAM_BLUE_SIZE_EXT* = 0x0000802A
+  GL_HISTOGRAM_ALPHA_SIZE_EXT* = 0x0000802B
+  GL_HISTOGRAM_LUMINANCE_SIZE_EXT* = 0x0000802C
+  GL_HISTOGRAM_SINK_EXT* = 0x0000802D
+  constGL_MINMAX_EXT* = 0x0000802E
+  GL_MINMAX_FORMAT_EXT* = 0x0000802F
+  GL_MINMAX_SINK_EXT* = 0x00008030
+
+proc glHistogramEXT*(target: TGLenum, width: TGLsizei, internalformat: TGLenum, 
+                     sink: TGLboolean){.dynlib: dllname, 
+                                        importc: "glHistogramEXT".}
+proc glResetHistogramEXT*(target: TGLenum){.dynlib: dllname, 
+    importc: "glResetHistogramEXT".}
+proc glGetHistogramEXT*(target: TGLenum, reset: TGLboolean, format: TGLenum, 
+                        thetype: TGLenum, values: PGLvoid){.dynlib: dllname, 
+    importc: "glGetHistogramEXT".}
+proc glGetHistogramParameterivEXT*(target: TGLenum, pname: TGLenum, 
+                                   params: PGLint){.dynlib: dllname, 
+    importc: "glGetHistogramParameterivEXT".}
+proc glGetHistogramParameterfvEXT*(target: TGLenum, pname: TGLenum, 
+                                   params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetHistogramParameterfvEXT".}
+proc glMinmaxEXT*(target: TGLenum, internalformat: TGLenum, sink: TGLboolean){.
+    dynlib: dllname, importc: "glMinmaxEXT".}
+proc glResetMinmaxEXT*(target: TGLenum){.dynlib: dllname, 
+    importc: "glResetMinmaxEXT".}
+proc glGetMinmaxEXT*(target: TGLenum, reset: TGLboolean, format: TGLenum, 
+                     thetype: TGLenum, values: PGLvoid){.dynlib: dllname, 
+    importc: "glGetMinmaxEXT".}
+proc glGetMinmaxParameterivEXT*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetMinmaxParameterivEXT".}
+proc glGetMinmaxParameterfvEXT*(target: TGLenum, pname: TGLenum, 
+                                params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetMinmaxParameterfvEXT".}
+  #***** GL_EXT_multi_draw_arrays *****//
+proc glMultiDrawArraysEXT*(mode: TGLenum, first: PGLint, count: PGLsizei, 
+                           primcount: TGLsizei){.dynlib: dllname, 
+    importc: "glMultiDrawArraysEXT".}
+proc glMultiDrawElementsEXT*(mode: TGLenum, count: PGLsizei, thetype: TGLenum, 
+                             indices: PGLvoid, primcount: TGLsizei){.
+    dynlib: dllname, importc: "glMultiDrawElementsEXT".}
+  #***** GL_EXT_packed_pixels *****//
+const 
+  GL_UNSIGNED_BYTE_3_3_2_EXT* = 0x00008032
+  GL_UNSIGNED_SHORT_4_4_4_4_EXT* = 0x00008033
+  GL_UNSIGNED_SHORT_5_5_5_1_EXT* = 0x00008034
+  GL_UNSIGNED_INT_8_8_8_8_EXT* = 0x00008035
+  GL_UNSIGNED_INT_10_10_10_2_EXT* = 0x00008036
+  #***** GL_EXT_paletted_texture *****//
+
+const 
+  GL_COLOR_INDEX1_EXT* = 0x000080E2
+  GL_COLOR_INDEX2_EXT* = 0x000080E3
+  GL_COLOR_INDEX4_EXT* = 0x000080E4
+  GL_COLOR_INDEX8_EXT* = 0x000080E5
+  GL_COLOR_INDEX12_EXT* = 0x000080E6
+  GL_COLOR_INDEX16_EXT* = 0x000080E7
+  GL_COLOR_TABLE_FORMAT_EXT* = 0x000080D8
+  GL_COLOR_TABLE_WIDTH_EXT* = 0x000080D9
+  GL_COLOR_TABLE_RED_SIZE_EXT* = 0x000080DA
+  GL_COLOR_TABLE_GREEN_SIZE_EXT* = 0x000080DB
+  GL_COLOR_TABLE_BLUE_SIZE_EXT* = 0x000080DC
+  GL_COLOR_TABLE_ALPHA_SIZE_EXT* = 0x000080DD
+  GL_COLOR_TABLE_LUMINANCE_SIZE_EXT* = 0x000080DE
+  GL_COLOR_TABLE_INTENSITY_SIZE_EXT* = 0x000080DF
+  GL_TEXTURE_INDEX_SIZE_EXT* = 0x000080ED
+  GL_TEXTURE_1D* = 0x00000DE0
+  GL_TEXTURE_2D* = 0x00000DE1
+  GL_TEXTURE_3D_EXT* = 0x0000806F # GL_TEXTURE_CUBE_MAP_ARB  { already defined }
+  GL_PROXY_TEXTURE_1D* = 0x00008063
+  GL_PROXY_TEXTURE_2D* = 0x00008064
+  GL_PROXY_TEXTURE_3D_EXT* = 0x00008070 # GL_PROXY_TEXTURE_CUBE_MAP_ARB  { already defined }
+                                        # GL_TEXTURE_1D  { already defined }
+                                        # GL_TEXTURE_2D  { already defined }
+                                        # GL_TEXTURE_3D_EXT  { already defined }
+                                        # GL_TEXTURE_CUBE_MAP_ARB  { already defined }
+
+proc glColorTableEXT*(target: TGLenum, internalFormat: TGLenum, width: TGLsizei, 
+                      format: TGLenum, thetype: TGLenum, data: PGLvoid){.
+    dynlib: dllname, importc: "glColorTableEXT".}
+  # glColorSubTableEXT  { already defined }
+proc glGetColorTableEXT*(target: TGLenum, format: TGLenum, thetype: TGLenum, 
+                         data: PGLvoid){.dynlib: dllname, 
+    importc: "glGetColorTableEXT".}
+proc glGetColorTableParameterivEXT*(target: TGLenum, pname: TGLenum, 
+                                    params: PGLint){.dynlib: dllname, 
+    importc: "glGetColorTableParameterivEXT".}
+proc glGetColorTableParameterfvEXT*(target: TGLenum, pname: TGLenum, 
+                                    params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetColorTableParameterfvEXT".}
+  #***** GL_EXT_point_parameters *****//
+const 
+  GL_POINT_SIZE_MIN_EXT* = 0x00008126
+  GL_POINT_SIZE_MAX_EXT* = 0x00008127
+  GL_POINT_FADE_THRESHOLD_SIZE_EXT* = 0x00008128
+  GL_DISTANCE_ATTENUATION_EXT* = 0x00008129
+
+proc glPointParameterfEXT*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glPointParameterfEXT".}
+proc glPointParameterfvEXT*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glPointParameterfvEXT".}
+  #***** GL_EXT_polygon_offset *****//
+const 
+  constGL_POLYGON_OFFSET_EXT* = 0x00008037
+  GL_POLYGON_OFFSET_FACTOR_EXT* = 0x00008038
+  GL_POLYGON_OFFSET_BIAS_EXT* = 0x00008039
+
+proc glPolygonOffsetEXT*(factor: TGLfloat, bias: TGLfloat){.dynlib: dllname, 
+    importc: "glPolygonOffsetEXT".}
+  #***** GL_EXT_secondary_color *****//
+const 
+  GL_COLOR_SUM_EXT* = 0x00008458
+  GL_CURRENT_SECONDARY_COLOR_EXT* = 0x00008459
+  GL_SECONDARY_COLOR_ARRAY_SIZE_EXT* = 0x0000845A
+  GL_SECONDARY_COLOR_ARRAY_TYPE_EXT* = 0x0000845B
+  GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT* = 0x0000845C
+  GL_SECONDARY_COLOR_ARRAY_POINTER_EXT* = 0x0000845D
+  GL_SECONDARY_COLOR_ARRAY_EXT* = 0x0000845E
+
+proc glSecondaryColor3bEXT*(components: TGLbyte){.dynlib: dllname, 
+    importc: "glSecondaryColor3bEXT".}
+proc glSecondaryColor3sEXT*(components: TGLshort){.dynlib: dllname, 
+    importc: "glSecondaryColor3sEXT".}
+proc glSecondaryColor3iEXT*(components: TGLint){.dynlib: dllname, 
+    importc: "glSecondaryColor3iEXT".}
+proc glSecondaryColor3fEXT*(components: TGLfloat){.dynlib: dllname, 
+    importc: "glSecondaryColor3fEXT".}
+proc glSecondaryColor3dEXT*(components: TGLdouble){.dynlib: dllname, 
+    importc: "glSecondaryColor3dEXT".}
+proc glSecondaryColor3ubEXT*(components: TGLubyte){.dynlib: dllname, 
+    importc: "glSecondaryColor3ubEXT".}
+proc glSecondaryColor3usEXT*(components: TGLushort){.dynlib: dllname, 
+    importc: "glSecondaryColor3usEXT".}
+proc glSecondaryColor3uiEXT*(components: TGLuint){.dynlib: dllname, 
+    importc: "glSecondaryColor3uiEXT".}
+proc glSecondaryColor3bvEXT*(components: TGLbyte){.dynlib: dllname, 
+    importc: "glSecondaryColor3bvEXT".}
+proc glSecondaryColor3svEXT*(components: TGLshort){.dynlib: dllname, 
+    importc: "glSecondaryColor3svEXT".}
+proc glSecondaryColor3ivEXT*(components: TGLint){.dynlib: dllname, 
+    importc: "glSecondaryColor3ivEXT".}
+proc glSecondaryColor3fvEXT*(components: TGLfloat){.dynlib: dllname, 
+    importc: "glSecondaryColor3fvEXT".}
+proc glSecondaryColor3dvEXT*(components: TGLdouble){.dynlib: dllname, 
+    importc: "glSecondaryColor3dvEXT".}
+proc glSecondaryColor3ubvEXT*(components: TGLubyte){.dynlib: dllname, 
+    importc: "glSecondaryColor3ubvEXT".}
+proc glSecondaryColor3usvEXT*(components: TGLushort){.dynlib: dllname, 
+    importc: "glSecondaryColor3usvEXT".}
+proc glSecondaryColor3uivEXT*(components: TGLuint){.dynlib: dllname, 
+    importc: "glSecondaryColor3uivEXT".}
+proc glSecondaryColorPointerEXT*(size: TGLint, thetype: TGLenum, 
+                                 stride: TGLsizei, pointer: PGLvoid){.
+    dynlib: dllname, importc: "glSecondaryColorPointerEXT".}
+  #***** GL_EXT_separate_specular_color *****//
+const 
+  GL_LIGHT_MODEL_COLOR_CONTROL_EXT* = 0x000081F8
+  GL_SINGLE_COLOR_EXT* = 0x000081F9
+  GL_SEPARATE_SPECULAR_COLOR_EXT* = 0x000081FA
+  #***** GL_EXT_shadow_funcs *****//
+  #***** GL_EXT_shared_texture_palette *****//
+
+const 
+  GL_SHARED_TEXTURE_PALETTE_EXT* = 0x000081FB
+  #***** GL_EXT_stencil_two_side *****//
+
+const 
+  GL_STENCIL_TEST_TWO_SIDE_EXT* = 0x00008910
+  constGL_ACTIVE_STENCIL_FACE_EXT* = 0x00008911
+
+proc glActiveStencilFaceEXT*(face: TGLenum){.dynlib: dllname, 
+    importc: "glActiveStencilFaceEXT".}
+  #***** GL_EXT_stencil_wrap *****//
+const 
+  GL_INCR_WRAP_EXT* = 0x00008507
+  GL_DECR_WRAP_EXT* = 0x00008508
+  #***** GL_EXT_subtexture *****//
+
+proc glTexSubImage1DEXT*(target: TGLenum, level: TGLint, xoffset: TGLint, 
+                         width: TGLsizei, format: TGLenum, thetype: TGLenum, 
+                         pixels: PGLvoid){.dynlib: dllname, 
+    importc: "glTexSubImage1DEXT".}
+proc glTexSubImage2DEXT*(target: TGLenum, level: TGLint, xoffset: TGLint, 
+                         yoffset: TGLint, width: TGLsizei, height: TGLsizei, 
+                         format: TGLenum, thetype: TGLenum, pixels: PGLvoid){.
+    dynlib: dllname, importc: "glTexSubImage2DEXT".}
+proc glTexSubImage3DEXT*(target: TGLenum, level: TGLint, xoffset: TGLint, 
+                         yoffset: TGLint, zoffset: TGLint, width: TGLsizei, 
+                         height: TGLsizei, depth: TGLsizei, format: TGLenum, 
+                         thetype: TGLenum, pixels: PGLvoid){.dynlib: dllname, 
+    importc: "glTexSubImage3DEXT".}
+  #***** GL_EXT_texture3D *****//
+const 
+  GL_PACK_SKIP_IMAGES_EXT* = 0x0000806B
+  GL_PACK_IMAGE_HEIGHT_EXT* = 0x0000806C
+  GL_UNPACK_SKIP_IMAGES_EXT* = 0x0000806D
+  GL_UNPACK_IMAGE_HEIGHT_EXT* = 0x0000806E # GL_TEXTURE_3D_EXT  { already defined }
+                                           # GL_PROXY_TEXTURE_3D_EXT  { already defined }
+  GL_TEXTURE_DEPTH_EXT* = 0x00008071
+  GL_TEXTURE_WRAP_R_EXT* = 0x00008072
+  GL_MAX_3D_TEXTURE_SIZE_EXT* = 0x00008073
+
+proc glTexImage3DEXT*(target: TGLenum, level: TGLint, internalformat: TGLenum, 
+                      width: TGLsizei, height: TGLsizei, depth: TGLsizei, 
+                      border: TGLint, format: TGLenum, thetype: TGLenum, 
+                      pixels: PGLvoid){.dynlib: dllname, 
+                                        importc: "glTexImage3DEXT".}
+  #***** GL_EXT_texture_compression_s3tc *****//
+const 
+  GL_COMPRESSED_RGB_S3TC_DXT1_EXT* = 0x000083F0
+  GL_COMPRESSED_RGBA_S3TC_DXT1_EXT* = 0x000083F1
+  GL_COMPRESSED_RGBA_S3TC_DXT3_EXT* = 0x000083F2
+  GL_COMPRESSED_RGBA_S3TC_DXT5_EXT* = 0x000083F3
+  #***** GL_EXT_texture_env_add *****//
+  #***** GL_EXT_texture_env_combine *****//
+
+const 
+  GL_COMBINE_EXT* = 0x00008570
+  GL_COMBINE_RGB_EXT* = 0x00008571
+  GL_COMBINE_ALPHA_EXT* = 0x00008572
+  GL_SOURCE0_RGB_EXT* = 0x00008580
+  GL_SOURCE1_RGB_EXT* = 0x00008581
+  GL_SOURCE2_RGB_EXT* = 0x00008582
+  GL_SOURCE0_ALPHA_EXT* = 0x00008588
+  GL_SOURCE1_ALPHA_EXT* = 0x00008589
+  GL_SOURCE2_ALPHA_EXT* = 0x0000858A
+  GL_OPERAND0_RGB_EXT* = 0x00008590
+  GL_OPERAND1_RGB_EXT* = 0x00008591
+  GL_OPERAND2_RGB_EXT* = 0x00008592
+  GL_OPERAND0_ALPHA_EXT* = 0x00008598
+  GL_OPERAND1_ALPHA_EXT* = 0x00008599
+  GL_OPERAND2_ALPHA_EXT* = 0x0000859A
+  GL_RGB_SCALE_EXT* = 0x00008573
+  GL_ADD_SIGNED_EXT* = 0x00008574
+  GL_INTERPOLATE_EXT* = 0x00008575
+  GL_CONSTANT_EXT* = 0x00008576
+  GL_PRIMARY_COLOR_EXT* = 0x00008577
+  GL_PREVIOUS_EXT* = 0x00008578
+  #***** GL_EXT_texture_env_dot3 *****//
+
+const 
+  GL_DOT3_RGB_EXT* = 0x00008740
+  GL_DOT3_RGBA_EXT* = 0x00008741
+  #***** GL_EXT_texture_filter_anisotropic *****//
+
+const 
+  GL_TEXTURE_MAX_ANISOTROPY_EXT* = 0x000084FE
+  GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT* = 0x000084FF
+  #***** GL_EXT_texture_lod_bias *****//
+
+const 
+  GL_TEXTURE_FILTER_CONTROL_EXT* = 0x00008500
+  GL_TEXTURE_LOD_BIAS_EXT* = 0x00008501
+  GL_MAX_TEXTURE_LOD_BIAS_EXT* = 0x000084FD
+  #***** GL_EXT_texture_object *****//
+
+const 
+  GL_TEXTURE_PRIORITY_EXT* = 0x00008066
+  GL_TEXTURE_RESIDENT_EXT* = 0x00008067
+  GL_TEXTURE_1D_BINDING_EXT* = 0x00008068
+  GL_TEXTURE_2D_BINDING_EXT* = 0x00008069
+  GL_TEXTURE_3D_BINDING_EXT* = 0x0000806A
+
+proc glGenTexturesEXT*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, 
+    importc: "glGenTexturesEXT".}
+proc glDeleteTexturesEXT*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteTexturesEXT".}
+proc glBindTextureEXT*(target: TGLenum, texture: TGLuint){.dynlib: dllname, 
+    importc: "glBindTextureEXT".}
+proc glPrioritizeTexturesEXT*(n: TGLsizei, textures: PGLuint, 
+                              priorities: PGLclampf){.dynlib: dllname, 
+    importc: "glPrioritizeTexturesEXT".}
+proc glAreTexturesResidentEXT*(n: TGLsizei, textures: PGLuint, 
+                               residences: PGLboolean): TGLboolean{.
+    dynlib: dllname, importc: "glAreTexturesResidentEXT".}
+proc glIsTextureEXT*(texture: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsTextureEXT".}
+  #***** GL_EXT_vertex_array *****//
+const 
+  GL_VERTEX_ARRAY_EXT* = 0x00008074
+  GL_NORMAL_ARRAY_EXT* = 0x00008075
+  GL_COLOR_ARRAY_EXT* = 0x00008076
+  GL_INDEX_ARRAY_EXT* = 0x00008077
+  GL_TEXTURE_COORD_ARRAY_EXT* = 0x00008078
+  GL_EDGE_FLAG_ARRAY_EXT* = 0x00008079
+  GL_DOUBLE_EXT* = 0x0000140A
+  GL_VERTEX_ARRAY_SIZE_EXT* = 0x0000807A
+  GL_VERTEX_ARRAY_TYPE_EXT* = 0x0000807B
+  GL_VERTEX_ARRAY_STRIDE_EXT* = 0x0000807C
+  GL_VERTEX_ARRAY_COUNT_EXT* = 0x0000807D
+  GL_NORMAL_ARRAY_TYPE_EXT* = 0x0000807E
+  GL_NORMAL_ARRAY_STRIDE_EXT* = 0x0000807F
+  GL_NORMAL_ARRAY_COUNT_EXT* = 0x00008080
+  GL_COLOR_ARRAY_SIZE_EXT* = 0x00008081
+  GL_COLOR_ARRAY_TYPE_EXT* = 0x00008082
+  GL_COLOR_ARRAY_STRIDE_EXT* = 0x00008083
+  GL_COLOR_ARRAY_COUNT_EXT* = 0x00008084
+  GL_INDEX_ARRAY_TYPE_EXT* = 0x00008085
+  GL_INDEX_ARRAY_STRIDE_EXT* = 0x00008086
+  GL_INDEX_ARRAY_COUNT_EXT* = 0x00008087
+  GL_TEXTURE_COORD_ARRAY_SIZE_EXT* = 0x00008088
+  GL_TEXTURE_COORD_ARRAY_TYPE_EXT* = 0x00008089
+  GL_TEXTURE_COORD_ARRAY_STRIDE_EXT* = 0x0000808A
+  GL_TEXTURE_COORD_ARRAY_COUNT_EXT* = 0x0000808B
+  GL_EDGE_FLAG_ARRAY_STRIDE_EXT* = 0x0000808C
+  GL_EDGE_FLAG_ARRAY_COUNT_EXT* = 0x0000808D
+  GL_VERTEX_ARRAY_POINTER_EXT* = 0x0000808E
+  GL_NORMAL_ARRAY_POINTER_EXT* = 0x0000808F
+  GL_COLOR_ARRAY_POINTER_EXT* = 0x00008090
+  GL_INDEX_ARRAY_POINTER_EXT* = 0x00008091
+  GL_TEXTURE_COORD_ARRAY_POINTER_EXT* = 0x00008092
+  GL_EDGE_FLAG_ARRAY_POINTER_EXT* = 0x00008093
+
+proc glArrayElementEXT*(i: TGLint){.dynlib: dllname, 
+                                    importc: "glArrayElementEXT".}
+proc glDrawArraysEXT*(mode: TGLenum, first: TGLint, count: TGLsizei){.
+    dynlib: dllname, importc: "glDrawArraysEXT".}
+proc glVertexPointerEXT*(size: TGLint, thetype: TGLenum, stride: TGLsizei, 
+                         count: TGLsizei, pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glVertexPointerEXT".}
+proc glNormalPointerEXT*(thetype: TGLenum, stride: TGLsizei, count: TGLsizei, 
+                         pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glNormalPointerEXT".}
+proc glColorPointerEXT*(size: TGLint, thetype: TGLenum, stride: TGLsizei, 
+                        count: TGLsizei, pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glColorPointerEXT".}
+proc glIndexPointerEXT*(thetype: TGLenum, stride: TGLsizei, count: TGLsizei, 
+                        pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glIndexPointerEXT".}
+proc glTexCoordPointerEXT*(size: TGLint, thetype: TGLenum, stride: TGLsizei, 
+                           count: TGLsizei, pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glTexCoordPointerEXT".}
+proc glEdgeFlagPointerEXT*(stride: TGLsizei, count: TGLsizei, 
+                           pointer: PGLboolean){.dynlib: dllname, 
+    importc: "glEdgeFlagPointerEXT".}
+proc glGetPointervEXT*(pname: TGLenum, params: PGLvoid){.dynlib: dllname, 
+    importc: "glGetPointervEXT".}
+  #***** GL_EXT_vertex_shader *****//
+const 
+  GL_VERTEX_SHADER_EXT* = 0x00008780
+  GL_VARIANT_VALUE_EXT* = 0x000087E4
+  GL_VARIANT_DATATYPE_EXT* = 0x000087E5
+  GL_VARIANT_ARRAY_STRIDE_EXT* = 0x000087E6
+  GL_VARIANT_ARRAY_TYPE_EXT* = 0x000087E7
+  GL_VARIANT_ARRAY_EXT* = 0x000087E8
+  GL_VARIANT_ARRAY_POINTER_EXT* = 0x000087E9
+  GL_INVARIANT_VALUE_EXT* = 0x000087EA
+  GL_INVARIANT_DATATYPE_EXT* = 0x000087EB
+  GL_LOCAL_CONSTANT_VALUE_EXT* = 0x000087EC
+  GL_LOCAL_CONSTANT_DATATYPE_EXT* = 0x000087ED
+  GL_OP_INDEX_EXT* = 0x00008782
+  GL_OP_NEGATE_EXT* = 0x00008783
+  GL_OP_DOT3_EXT* = 0x00008784
+  GL_OP_DOT4_EXT* = 0x00008785
+  GL_OP_MUL_EXT* = 0x00008786
+  GL_OP_ADD_EXT* = 0x00008787
+  GL_OP_MADD_EXT* = 0x00008788
+  GL_OP_FRAC_EXT* = 0x00008789
+  GL_OP_MAX_EXT* = 0x0000878A
+  GL_OP_MIN_EXT* = 0x0000878B
+  GL_OP_SET_GE_EXT* = 0x0000878C
+  GL_OP_SET_LT_EXT* = 0x0000878D
+  GL_OP_CLAMP_EXT* = 0x0000878E
+  GL_OP_FLOOR_EXT* = 0x0000878F
+  GL_OP_ROUND_EXT* = 0x00008790
+  GL_OP_EXP_BASE_2_EXT* = 0x00008791
+  GL_OP_LOG_BASE_2_EXT* = 0x00008792
+  GL_OP_POWER_EXT* = 0x00008793
+  GL_OP_RECIP_EXT* = 0x00008794
+  GL_OP_RECIP_SQRT_EXT* = 0x00008795
+  GL_OP_SUB_EXT* = 0x00008796
+  GL_OP_CROSS_PRODUCT_EXT* = 0x00008797
+  GL_OP_MULTIPLY_MATRIX_EXT* = 0x00008798
+  GL_OP_MOV_EXT* = 0x00008799
+  GL_OUTPUT_VERTEX_EXT* = 0x0000879A
+  GL_OUTPUT_COLOR0_EXT* = 0x0000879B
+  GL_OUTPUT_COLOR1_EXT* = 0x0000879C
+  GL_OUTPUT_TEXTURE_COORD0_EXT* = 0x0000879D
+  GL_OUTPUT_TEXTURE_COORD1_EXT* = 0x0000879E
+  GL_OUTPUT_TEXTURE_COORD2_EXT* = 0x0000879F
+  GL_OUTPUT_TEXTURE_COORD3_EXT* = 0x000087A0
+  GL_OUTPUT_TEXTURE_COORD4_EXT* = 0x000087A1
+  GL_OUTPUT_TEXTURE_COORD5_EXT* = 0x000087A2
+  GL_OUTPUT_TEXTURE_COORD6_EXT* = 0x000087A3
+  GL_OUTPUT_TEXTURE_COORD7_EXT* = 0x000087A4
+  GL_OUTPUT_TEXTURE_COORD8_EXT* = 0x000087A5
+  GL_OUTPUT_TEXTURE_COORD9_EXT* = 0x000087A6
+  GL_OUTPUT_TEXTURE_COORD10_EXT* = 0x000087A7
+  GL_OUTPUT_TEXTURE_COORD11_EXT* = 0x000087A8
+  GL_OUTPUT_TEXTURE_COORD12_EXT* = 0x000087A9
+  GL_OUTPUT_TEXTURE_COORD13_EXT* = 0x000087AA
+  GL_OUTPUT_TEXTURE_COORD14_EXT* = 0x000087AB
+  GL_OUTPUT_TEXTURE_COORD15_EXT* = 0x000087AC
+  GL_OUTPUT_TEXTURE_COORD16_EXT* = 0x000087AD
+  GL_OUTPUT_TEXTURE_COORD17_EXT* = 0x000087AE
+  GL_OUTPUT_TEXTURE_COORD18_EXT* = 0x000087AF
+  GL_OUTPUT_TEXTURE_COORD19_EXT* = 0x000087B0
+  GL_OUTPUT_TEXTURE_COORD20_EXT* = 0x000087B1
+  GL_OUTPUT_TEXTURE_COORD21_EXT* = 0x000087B2
+  GL_OUTPUT_TEXTURE_COORD22_EXT* = 0x000087B3
+  GL_OUTPUT_TEXTURE_COORD23_EXT* = 0x000087B4
+  GL_OUTPUT_TEXTURE_COORD24_EXT* = 0x000087B5
+  GL_OUTPUT_TEXTURE_COORD25_EXT* = 0x000087B6
+  GL_OUTPUT_TEXTURE_COORD26_EXT* = 0x000087B7
+  GL_OUTPUT_TEXTURE_COORD27_EXT* = 0x000087B8
+  GL_OUTPUT_TEXTURE_COORD28_EXT* = 0x000087B9
+  GL_OUTPUT_TEXTURE_COORD29_EXT* = 0x000087BA
+  GL_OUTPUT_TEXTURE_COORD30_EXT* = 0x000087BB
+  GL_OUTPUT_TEXTURE_COORD31_EXT* = 0x000087BC
+  GL_OUTPUT_FOG_EXT* = 0x000087BD
+  GL_SCALAR_EXT* = 0x000087BE
+  GL_VECTOR_EXT* = 0x000087BF
+  GL_MATRIX_EXT* = 0x000087C0
+  GL_VARIANT_EXT* = 0x000087C1
+  GL_INVARIANT_EXT* = 0x000087C2
+  GL_LOCAL_CONSTANT_EXT* = 0x000087C3
+  GL_LOCAL_EXT* = 0x000087C4
+  GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT* = 0x000087C5
+  GL_MAX_VERTEX_SHADER_VARIANTS_EXT* = 0x000087C6
+  GL_MAX_VERTEX_SHADER_INVARIANTS_EXT* = 0x000087C7
+  GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT* = 0x000087C8
+  GL_MAX_VERTEX_SHADER_LOCALS_EXT* = 0x000087C9
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT* = 0x000087CA
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT* = 0x000087CB
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT* = 0x000087CC
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT* = 0x000087CD
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT* = 0x000087CE
+  GL_VERTEX_SHADER_INSTRUCTIONS_EXT* = 0x000087CF
+  GL_VERTEX_SHADER_VARIANTS_EXT* = 0x000087D0
+  GL_VERTEX_SHADER_INVARIANTS_EXT* = 0x000087D1
+  GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT* = 0x000087D2
+  GL_VERTEX_SHADER_LOCALS_EXT* = 0x000087D3
+  GL_VERTEX_SHADER_BINDING_EXT* = 0x00008781
+  GL_VERTEX_SHADER_OPTIMIZED_EXT* = 0x000087D4
+  GL_X_EXT* = 0x000087D5
+  GL_Y_EXT* = 0x000087D6
+  GL_Z_EXT* = 0x000087D7
+  GL_W_EXT* = 0x000087D8
+  GL_NEGATIVE_X_EXT* = 0x000087D9
+  GL_NEGATIVE_Y_EXT* = 0x000087DA
+  GL_NEGATIVE_Z_EXT* = 0x000087DB
+  GL_NEGATIVE_W_EXT* = 0x000087DC
+  GL_ZERO_EXT* = 0x000087DD
+  GL_ONE_EXT* = 0x000087DE
+  GL_NEGATIVE_ONE_EXT* = 0x000087DF
+  GL_NORMALIZED_RANGE_EXT* = 0x000087E0
+  GL_FULL_RANGE_EXT* = 0x000087E1
+  GL_CURRENT_VERTEX_EXT* = 0x000087E2
+  GL_MVP_MATRIX_EXT* = 0x000087E3
+
+proc glBeginVertexShaderEXT*(){.dynlib: dllname, 
+                                importc: "glBeginVertexShaderEXT".}
+proc glEndVertexShaderEXT*(){.dynlib: dllname, importc: "glEndVertexShaderEXT".}
+proc glBindVertexShaderEXT*(id: TGLuint){.dynlib: dllname, 
+    importc: "glBindVertexShaderEXT".}
+proc glGenVertexShadersEXT*(range: TGLuint): TGLuint{.dynlib: dllname, 
+    importc: "glGenVertexShadersEXT".}
+proc glDeleteVertexShaderEXT*(id: TGLuint){.dynlib: dllname, 
+    importc: "glDeleteVertexShaderEXT".}
+proc glShaderOp1EXT*(op: TGLenum, res: TGLuint, arg1: TGLuint){.dynlib: dllname, 
+    importc: "glShaderOp1EXT".}
+proc glShaderOp2EXT*(op: TGLenum, res: TGLuint, arg1: TGLuint, arg2: TGLuint){.
+    dynlib: dllname, importc: "glShaderOp2EXT".}
+proc glShaderOp3EXT*(op: TGLenum, res: TGLuint, arg1: TGLuint, arg2: TGLuint, 
+                     arg3: TGLuint){.dynlib: dllname, importc: "glShaderOp3EXT".}
+proc glSwizzleEXT*(res: TGLuint, theIn: TGLuint, outX: TGLenum, outY: TGLenum, 
+                   outZ: TGLenum, outW: TGLenum){.dynlib: dllname, 
+    importc: "glSwizzleEXT".}
+proc glWriteMaskEXT*(res: TGLuint, theIn: TGLuint, outX: TGLenum, outY: TGLenum, 
+                     outZ: TGLenum, outW: TGLenum){.dynlib: dllname, 
+    importc: "glWriteMaskEXT".}
+proc glInsertComponentEXT*(res: TGLuint, src: TGLuint, num: TGLuint){.
+    dynlib: dllname, importc: "glInsertComponentEXT".}
+proc glExtractComponentEXT*(res: TGLuint, src: TGLuint, num: TGLuint){.
+    dynlib: dllname, importc: "glExtractComponentEXT".}
+proc glGenSymbolsEXT*(datatype: TGLenum, storagetype: TGLenum, range: TGLenum, 
+                      components: TGLuint): TGLuint{.dynlib: dllname, 
+    importc: "glGenSymbolsEXT".}
+proc glSetInvariantEXT*(id: TGLuint, thetype: TGLenum, address: PGLvoid){.
+    dynlib: dllname, importc: "glSetInvariantEXT".}
+proc glSetLocalConstantEXT*(id: TGLuint, thetype: TGLenum, address: PGLvoid){.
+    dynlib: dllname, importc: "glSetLocalConstantEXT".}
+proc glVariantbvEXT*(id: TGLuint, address: PGLbyte){.dynlib: dllname, 
+    importc: "glVariantbvEXT".}
+proc glVariantsvEXT*(id: TGLuint, address: PGLshort){.dynlib: dllname, 
+    importc: "glVariantsvEXT".}
+proc glVariantivEXT*(id: TGLuint, address: PGLint){.dynlib: dllname, 
+    importc: "glVariantivEXT".}
+proc glVariantfvEXT*(id: TGLuint, address: PGLfloat){.dynlib: dllname, 
+    importc: "glVariantfvEXT".}
+proc glVariantdvEXT*(id: TGLuint, address: PGLdouble){.dynlib: dllname, 
+    importc: "glVariantdvEXT".}
+proc glVariantubvEXT*(id: TGLuint, address: PGLubyte){.dynlib: dllname, 
+    importc: "glVariantubvEXT".}
+proc glVariantusvEXT*(id: TGLuint, address: PGLushort){.dynlib: dllname, 
+    importc: "glVariantusvEXT".}
+proc glVariantuivEXT*(id: TGLuint, address: PGLuint){.dynlib: dllname, 
+    importc: "glVariantuivEXT".}
+proc glVariantPointerEXT*(id: TGLuint, thetype: TGLenum, stride: TGLuint, 
+                          address: PGLvoid){.dynlib: dllname, 
+    importc: "glVariantPointerEXT".}
+proc glEnableVariantClientStateEXT*(id: TGLuint){.dynlib: dllname, 
+    importc: "glEnableVariantClientStateEXT".}
+proc glDisableVariantClientStateEXT*(id: TGLuint){.dynlib: dllname, 
+    importc: "glDisableVariantClientStateEXT".}
+proc glBindLightParameterEXT*(light: TGLenum, value: TGLenum): TGLuint{.
+    dynlib: dllname, importc: "glBindLightParameterEXT".}
+proc glBindMaterialParameterEXT*(face: TGLenum, value: TGLenum): TGLuint{.
+    dynlib: dllname, importc: "glBindMaterialParameterEXT".}
+proc glBindTexGenParameterEXT*(theunit: TGLenum, coord: TGLenum, value: TGLenum): TGLuint{.
+    dynlib: dllname, importc: "glBindTexGenParameterEXT".}
+proc glBindTextureUnitParameterEXT*(theunit: TGLenum, value: TGLenum): TGLuint{.
+    dynlib: dllname, importc: "glBindTextureUnitParameterEXT".}
+proc glBindParameterEXT*(value: TGLenum): TGLuint{.dynlib: dllname, 
+    importc: "glBindParameterEXT".}
+proc glIsVariantEnabledEXT*(id: TGLuint, cap: TGLenum): TGLboolean{.
+    dynlib: dllname, importc: "glIsVariantEnabledEXT".}
+proc glGetVariantBooleanvEXT*(id: TGLuint, value: TGLenum, data: PGLboolean){.
+    dynlib: dllname, importc: "glGetVariantBooleanvEXT".}
+proc glGetVariantIntegervEXT*(id: TGLuint, value: TGLenum, data: PGLint){.
+    dynlib: dllname, importc: "glGetVariantIntegervEXT".}
+proc glGetVariantFloatvEXT*(id: TGLuint, value: TGLenum, data: PGLfloat){.
+    dynlib: dllname, importc: "glGetVariantFloatvEXT".}
+proc glGetVariantPointervEXT*(id: TGLuint, value: TGLenum, data: PGLvoid){.
+    dynlib: dllname, importc: "glGetVariantPointervEXT".}
+proc glGetInvariantBooleanvEXT*(id: TGLuint, value: TGLenum, data: PGLboolean){.
+    dynlib: dllname, importc: "glGetInvariantBooleanvEXT".}
+proc glGetInvariantIntegervEXT*(id: TGLuint, value: TGLenum, data: PGLint){.
+    dynlib: dllname, importc: "glGetInvariantIntegervEXT".}
+proc glGetInvariantFloatvEXT*(id: TGLuint, value: TGLenum, data: PGLfloat){.
+    dynlib: dllname, importc: "glGetInvariantFloatvEXT".}
+proc glGetLocalConstantBooleanvEXT*(id: TGLuint, value: TGLenum, 
+                                    data: PGLboolean){.dynlib: dllname, 
+    importc: "glGetLocalConstantBooleanvEXT".}
+proc glGetLocalConstantIntegervEXT*(id: TGLuint, value: TGLenum, data: PGLint){.
+    dynlib: dllname, importc: "glGetLocalConstantIntegervEXT".}
+proc glGetLocalConstantFloatvEXT*(id: TGLuint, value: TGLenum, data: PGLfloat){.
+    dynlib: dllname, importc: "glGetLocalConstantFloatvEXT".}
+  #***** GL_EXT_vertex_weighting *****//
+const 
+  GL_VERTEX_WEIGHTING_EXT* = 0x00008509
+  GL_MODELVIEW0_EXT* = 0x00001700
+  GL_MODELVIEW1_EXT* = 0x0000850A
+  GL_MODELVIEW0_MATRIX_EXT* = 0x00000BA6
+  GL_MODELVIEW1_MATRIX_EXT* = 0x00008506
+  GL_CURRENT_VERTEX_WEIGHT_EXT* = 0x0000850B
+  GL_VERTEX_WEIGHT_ARRAY_EXT* = 0x0000850C
+  GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT* = 0x0000850D
+  GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT* = 0x0000850E
+  GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT* = 0x0000850F
+  GL_MODELVIEW0_STACK_DEPTH_EXT* = 0x00000BA3
+  GL_MODELVIEW1_STACK_DEPTH_EXT* = 0x00008502
+  GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT* = 0x00008510
+
+proc glVertexWeightfEXT*(weight: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexWeightfEXT".}
+proc glVertexWeightfvEXT*(weight: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexWeightfvEXT".}
+proc glVertexWeightPointerEXT*(size: TGLint, thetype: TGLenum, stride: TGLsizei, 
+                               pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glVertexWeightPointerEXT".}
+  #***** GL_HP_occlusion_test *****//
+const 
+  GL_OCCLUSION_TEST_HP* = 0x00008165
+  GL_OCCLUSION_TEST_RESULT_HP* = 0x00008166
+  #***** GL_NV_blend_square *****//
+  #***** GL_NV_copy_depth_to_color *****//
+
+const 
+  GL_DEPTH_STENCIL_TO_RGBA_NV* = 0x0000886E
+  GL_DEPTH_STENCIL_TO_BGRA_NV* = 0x0000886F
+  #***** GL_NV_depth_clamp *****//
+
+const 
+  GL_DEPTH_CLAMP_NV* = 0x0000864F
+  #***** GL_NV_evaluators *****//
+
+const 
+  GL_EVAL_2D_NV* = 0x000086C0
+  GL_EVAL_TRIANGULAR_2D_NV* = 0x000086C1
+  GL_MAP_TESSELLATION_NV* = 0x000086C2
+  GL_MAP_ATTRIB_U_ORDER_NV* = 0x000086C3
+  GL_MAP_ATTRIB_V_ORDER_NV* = 0x000086C4
+  GL_EVAL_FRACTIONAL_TESSELLATION_NV* = 0x000086C5
+  GL_EVAL_VERTEX_ATTRIB0_NV* = 0x000086C6
+  GL_EVAL_VERTEX_ATTRIB1_NV* = 0x000086C7
+  GL_EVAL_VERTEX_ATTRIB2_NV* = 0x000086C8
+  GL_EVAL_VERTEX_ATTRIB3_NV* = 0x000086C9
+  GL_EVAL_VERTEX_ATTRIB4_NV* = 0x000086CA
+  GL_EVAL_VERTEX_ATTRIB5_NV* = 0x000086CB
+  GL_EVAL_VERTEX_ATTRIB6_NV* = 0x000086CC
+  GL_EVAL_VERTEX_ATTRIB7_NV* = 0x000086CD
+  GL_EVAL_VERTEX_ATTRIB8_NV* = 0x000086CE
+  GL_EVAL_VERTEX_ATTRIB9_NV* = 0x000086CF
+  GL_EVAL_VERTEX_ATTRIB10_NV* = 0x000086D0
+  GL_EVAL_VERTEX_ATTRIB11_NV* = 0x000086D1
+  GL_EVAL_VERTEX_ATTRIB12_NV* = 0x000086D2
+  GL_EVAL_VERTEX_ATTRIB13_NV* = 0x000086D3
+  GL_EVAL_VERTEX_ATTRIB14_NV* = 0x000086D4
+  GL_EVAL_VERTEX_ATTRIB15_NV* = 0x000086D5
+  GL_MAX_MAP_TESSELLATION_NV* = 0x000086D6
+  GL_MAX_RATIONAL_EVAL_ORDER_NV* = 0x000086D7
+
+proc glMapControlPointsNV*(target: TGLenum, index: TGLuint, thetype: TGLenum, 
+                           ustride: TGLsizei, vstride: TGLsizei, uorder: TGLint, 
+                           vorder: TGLint, thepacked: TGLboolean, 
+                           points: PGLvoid){.dynlib: dllname, 
+    importc: "glMapControlPointsNV".}
+proc glMapParameterivNV*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glMapParameterivNV".}
+proc glMapParameterfvNV*(target: TGLenum, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glMapParameterfvNV".}
+proc glGetMapControlPointsNV*(target: TGLenum, index: TGLuint, thetype: TGLenum, 
+                              ustride: TGLsizei, vstride: TGLsizei, 
+                              thepacked: TGLboolean, points: PGLvoid){.
+    dynlib: dllname, importc: "glGetMapControlPointsNV".}
+proc glGetMapParameterivNV*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetMapParameterivNV".}
+proc glGetMapParameterfvNV*(target: TGLenum, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetMapParameterfvNV".}
+proc glGetMapAttribParameterivNV*(target: TGLenum, index: TGLuint, 
+                                  pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetMapAttribParameterivNV".}
+proc glGetMapAttribParameterfvNV*(target: TGLenum, index: TGLuint, 
+                                  pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetMapAttribParameterfvNV".}
+proc glEvalMapsNV*(target: TGLenum, mode: TGLenum){.dynlib: dllname, 
+    importc: "glEvalMapsNV".}
+  #***** GL_NV_fence *****//
+const 
+  GL_ALL_COMPLETED_NV* = 0x000084F2
+  GL_FENCE_STATUS_NV* = 0x000084F3
+  GL_FENCE_CONDITION_NV* = 0x000084F4
+
+proc glGenFencesNV*(n: TGLsizei, fences: PGLuint){.dynlib: dllname, 
+    importc: "glGenFencesNV".}
+proc glDeleteFencesNV*(n: TGLsizei, fences: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteFencesNV".}
+proc glSetFenceNV*(fence: TGLuint, condition: TGLenum){.dynlib: dllname, 
+    importc: "glSetFenceNV".}
+proc glTestFenceNV*(fence: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glTestFenceNV".}
+proc glFinishFenceNV*(fence: TGLuint){.dynlib: dllname, 
+                                       importc: "glFinishFenceNV".}
+proc glIsFenceNV*(fence: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsFenceNV".}
+proc glGetFenceivNV*(fence: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetFenceivNV".}
+  #***** GL_NV_fog_distance *****//
+const 
+  GL_FOG_DISTANCE_MODE_NV* = 0x0000855A
+  GL_EYE_RADIAL_NV* = 0x0000855B
+  GL_EYE_PLANE_ABSOLUTE_NV* = 0x0000855C
+  #***** GL_NV_light_max_exponent *****//
+
+const 
+  GL_MAX_SHININESS_NV* = 0x00008504
+  GL_MAX_SPOT_EXPONENT_NV* = 0x00008505
+  #***** GL_NV_multisample_filter_hint *****//
+
+const 
+  GL_MULTISAMPLE_FILTER_HINT_NV* = 0x00008534
+  #***** GL_NV_occlusion_query *****//
+  # GL_OCCLUSION_TEST_HP  { already defined }
+  # GL_OCCLUSION_TEST_RESULT_HP  { already defined }
+
+const 
+  GL_PIXEL_COUNTER_BITS_NV* = 0x00008864
+  GL_CURRENT_OCCLUSION_QUERY_ID_NV* = 0x00008865
+  GL_PIXEL_COUNT_NV* = 0x00008866
+  GL_PIXEL_COUNT_AVAILABLE_NV* = 0x00008867
+
+proc glGenOcclusionQueriesNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, 
+    importc: "glGenOcclusionQueriesNV".}
+proc glDeleteOcclusionQueriesNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteOcclusionQueriesNV".}
+proc glIsOcclusionQueryNV*(id: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsOcclusionQueryNV".}
+proc glBeginOcclusionQueryNV*(id: TGLuint){.dynlib: dllname, 
+    importc: "glBeginOcclusionQueryNV".}
+proc glEndOcclusionQueryNV*(){.dynlib: dllname, importc: "glEndOcclusionQueryNV".}
+proc glGetOcclusionQueryivNV*(id: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetOcclusionQueryivNV".}
+proc glGetOcclusionQueryuivNV*(id: TGLuint, pname: TGLenum, params: PGLuint){.
+    dynlib: dllname, importc: "glGetOcclusionQueryuivNV".}
+  #***** GL_NV_packed_depth_stencil *****//
+const 
+  GL_DEPTH_STENCIL_NV* = 0x000084F9
+  GL_UNSIGNED_INT_24_8_NV* = 0x000084FA
+  #***** GL_NV_point_sprite *****//
+
+const 
+  GL_POINT_SPRITE_NV* = 0x00008861
+  GL_COORD_REPLACE_NV* = 0x00008862
+  GL_POINT_SPRITE_R_MODE_NV* = 0x00008863
+
+proc glPointParameteriNV*(pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glPointParameteriNV".}
+proc glPointParameterivNV*(pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glPointParameterivNV".}
+  #***** GL_NV_register_combiners *****//
+const 
+  GL_REGISTER_COMBINERS_NV* = 0x00008522
+  GL_COMBINER0_NV* = 0x00008550
+  GL_COMBINER1_NV* = 0x00008551
+  GL_COMBINER2_NV* = 0x00008552
+  GL_COMBINER3_NV* = 0x00008553
+  GL_COMBINER4_NV* = 0x00008554
+  GL_COMBINER5_NV* = 0x00008555
+  GL_COMBINER6_NV* = 0x00008556
+  GL_COMBINER7_NV* = 0x00008557
+  GL_VARIABLE_A_NV* = 0x00008523
+  GL_VARIABLE_B_NV* = 0x00008524
+  GL_VARIABLE_C_NV* = 0x00008525
+  GL_VARIABLE_D_NV* = 0x00008526
+  GL_VARIABLE_E_NV* = 0x00008527
+  GL_VARIABLE_F_NV* = 0x00008528
+  GL_VARIABLE_G_NV* = 0x00008529
+  GL_CONSTANT_COLOR0_NV* = 0x0000852A
+  GL_CONSTANT_COLOR1_NV* = 0x0000852B
+  GL_PRIMARY_COLOR_NV* = 0x0000852C
+  GL_SECONDARY_COLOR_NV* = 0x0000852D
+  GL_SPARE0_NV* = 0x0000852E
+  GL_SPARE1_NV* = 0x0000852F
+  GL_UNSIGNED_IDENTITY_NV* = 0x00008536
+  GL_UNSIGNED_INVERT_NV* = 0x00008537
+  GL_EXPAND_NORMAL_NV* = 0x00008538
+  GL_EXPAND_NEGATE_NV* = 0x00008539
+  GL_HALF_BIAS_NORMAL_NV* = 0x0000853A
+  GL_HALF_BIAS_NEGATE_NV* = 0x0000853B
+  GL_SIGNED_IDENTITY_NV* = 0x0000853C
+  GL_SIGNED_NEGATE_NV* = 0x0000853D
+  GL_E_TIMES_F_NV* = 0x00008531
+  GL_SPARE0_PLUS_SECONDARY_COLOR_NV* = 0x00008532
+  GL_SCALE_BY_TWO_NV* = 0x0000853E
+  GL_SCALE_BY_FOUR_NV* = 0x0000853F
+  GL_SCALE_BY_ONE_HALF_NV* = 0x00008540
+  GL_BIAS_BY_NEGATIVE_ONE_HALF_NV* = 0x00008541
+  GL_DISCARD_NV* = 0x00008530
+  constGL_COMBINER_INPUT_NV* = 0x00008542
+  GL_COMBINER_MAPPING_NV* = 0x00008543
+  GL_COMBINER_COMPONENT_USAGE_NV* = 0x00008544
+  GL_COMBINER_AB_DOT_PRODUCT_NV* = 0x00008545
+  GL_COMBINER_CD_DOT_PRODUCT_NV* = 0x00008546
+  GL_COMBINER_MUX_SUM_NV* = 0x00008547
+  GL_COMBINER_SCALE_NV* = 0x00008548
+  GL_COMBINER_BIAS_NV* = 0x00008549
+  GL_COMBINER_AB_OUTPUT_NV* = 0x0000854A
+  GL_COMBINER_CD_OUTPUT_NV* = 0x0000854B
+  GL_COMBINER_SUM_OUTPUT_NV* = 0x0000854C
+  GL_NUM_GENERAL_COMBINERS_NV* = 0x0000854E
+  GL_COLOR_SUM_CLAMP_NV* = 0x0000854F
+  GL_MAX_GENERAL_COMBINERS_NV* = 0x0000854D
+
+proc glCombinerParameterfvNV*(pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glCombinerParameterfvNV".}
+proc glCombinerParameterivNV*(pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glCombinerParameterivNV".}
+proc glCombinerParameterfNV*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glCombinerParameterfNV".}
+proc glCombinerParameteriNV*(pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glCombinerParameteriNV".}
+proc glCombinerInputNV*(stage: TGLenum, portion: TGLenum, variable: TGLenum, 
+                        input: TGLenum, mapping: TGLenum, 
+                        componentUsage: TGLenum){.dynlib: dllname, 
+    importc: "glCombinerInputNV".}
+proc glCombinerOutputNV*(stage: TGLenum, portion: TGLenum, abOutput: TGLenum, 
+                         cdOutput: TGLenum, sumOutput: TGLenum, scale: TGLenum, 
+                         bias: TGLenum, abDotProduct: TGLboolean, 
+                         cdDotProduct: TGLboolean, muxSum: TGLboolean){.
+    dynlib: dllname, importc: "glCombinerOutputNV".}
+proc glFinalCombinerInputNV*(variable: TGLenum, input: TGLenum, 
+                             mapping: TGLenum, componentUsage: TGLenum){.
+    dynlib: dllname, importc: "glFinalCombinerInputNV".}
+proc glGetCombinerInputParameterfvNV*(stage: TGLenum, portion: TGLenum, 
+                                      variable: TGLenum, pname: TGLenum, 
+                                      params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetCombinerInputParameterfvNV".}
+proc glGetCombinerInputParameterivNV*(stage: TGLenum, portion: TGLenum, 
+                                      variable: TGLenum, pname: TGLenum, 
+                                      params: PGLint){.dynlib: dllname, 
+    importc: "glGetCombinerInputParameterivNV".}
+proc glGetCombinerOutputParameterfvNV*(stage: TGLenum, portion: TGLenum, 
+                                       pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetCombinerOutputParameterfvNV".}
+proc glGetCombinerOutputParameterivNV*(stage: TGLenum, portion: TGLenum, 
+                                       pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetCombinerOutputParameterivNV".}
+proc glGetFinalCombinerInputParameterfvNV*(variable: TGLenum, pname: TGLenum, 
+    params: PGLfloat){.dynlib: dllname, 
+                       importc: "glGetFinalCombinerInputParameterfvNV".}
+proc glGetFinalCombinerInputParameterivNV*(variable: TGLenum, pname: TGLenum, 
+    params: PGLint){.dynlib: dllname, 
+                     importc: "glGetFinalCombinerInputParameterivNV".}
+  #***** GL_NV_register_combiners2 *****//
+const 
+  GL_PER_STAGE_CONSTANTS_NV* = 0x00008535
+
+proc glCombinerStageParameterfvNV*(stage: TGLenum, pname: TGLenum, 
+                                   params: PGLfloat){.dynlib: dllname, 
+    importc: "glCombinerStageParameterfvNV".}
+proc glGetCombinerStageParameterfvNV*(stage: TGLenum, pname: TGLenum, 
+                                      params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetCombinerStageParameterfvNV".}
+  #***** GL_NV_texgen_emboss *****//
+const 
+  GL_EMBOSS_MAP_NV* = 0x0000855F
+  GL_EMBOSS_LIGHT_NV* = 0x0000855D
+  GL_EMBOSS_CONSTANT_NV* = 0x0000855E
+  #***** GL_NV_texgen_reflection *****//
+
+const 
+  GL_NORMAL_MAP_NV* = 0x00008511
+  GL_REFLECTION_MAP_NV* = 0x00008512
+  #***** GL_NV_texture_compression_vtc *****//
+  # GL_COMPRESSED_RGB_S3TC_DXT1_EXT  { already defined }
+  # GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  { already defined }
+  # GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  { already defined }
+  # GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  { already defined }
+  #***** GL_NV_texture_env_combine4 *****//
+
+const 
+  GL_COMBINE4_NV* = 0x00008503
+  GL_SOURCE3_RGB_NV* = 0x00008583
+  GL_SOURCE3_ALPHA_NV* = 0x0000858B
+  GL_OPERAND3_RGB_NV* = 0x00008593
+  GL_OPERAND3_ALPHA_NV* = 0x0000859B
+  #***** GL_NV_texture_rectangle *****//
+
+const 
+  GL_TEXTURE_RECTANGLE_NV* = 0x000084F5
+  GL_TEXTURE_BINDING_RECTANGLE_NV* = 0x000084F6
+  GL_PROXY_TEXTURE_RECTANGLE_NV* = 0x000084F7
+  GL_MAX_RECTANGLE_TEXTURE_SIZE_NV* = 0x000084F8
+  #***** GL_NV_texture_shader *****//
+
+const 
+  GL_TEXTURE_SHADER_NV* = 0x000086DE
+  GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV* = 0x000086D9
+  GL_SHADER_OPERATION_NV* = 0x000086DF
+  GL_CULL_MODES_NV* = 0x000086E0
+  GL_OFFSET_TEXTURE_MATRIX_NV* = 0x000086E1
+  GL_OFFSET_TEXTURE_SCALE_NV* = 0x000086E2
+  GL_OFFSET_TEXTURE_BIAS_NV* = 0x000086E3
+  GL_PREVIOUS_TEXTURE_INPUT_NV* = 0x000086E4
+  GL_CONST_EYE_NV* = 0x000086E5
+  GL_SHADER_CONSISTENT_NV* = 0x000086DD
+  GL_PASS_THROUGH_NV* = 0x000086E6
+  GL_CULL_FRAGMENT_NV* = 0x000086E7
+  GL_OFFSET_TEXTURE_2D_NV* = 0x000086E8
+  GL_OFFSET_TEXTURE_RECTANGLE_NV* = 0x0000864C
+  GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV* = 0x0000864D
+  GL_DEPENDENT_AR_TEXTURE_2D_NV* = 0x000086E9
+  GL_DEPENDENT_GB_TEXTURE_2D_NV* = 0x000086EA
+  GL_DOT_PRODUCT_NV* = 0x000086EC
+  GL_DOT_PRODUCT_DEPTH_REPLACE_NV* = 0x000086ED
+  GL_DOT_PRODUCT_TEXTURE_2D_NV* = 0x000086EE
+  GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV* = 0x0000864E
+  GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV* = 0x000086F0
+  GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV* = 0x000086F1
+  GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV* = 0x000086F2
+  GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV* = 0x000086F3
+  GL_HILO_NV* = 0x000086F4
+  GL_DSDT_NV* = 0x000086F5
+  GL_DSDT_MAG_NV* = 0x000086F6
+  GL_DSDT_MAG_VIB_NV* = 0x000086F7
+  GL_UNSIGNED_INT_S8_S8_8_8_NV* = 0x000086DA
+  GL_UNSIGNED_INT_8_8_S8_S8_REV_NV* = 0x000086DB
+  GL_SIGNED_RGBA_NV* = 0x000086FB
+  GL_SIGNED_RGBA8_NV* = 0x000086FC
+  GL_SIGNED_RGB_NV* = 0x000086FE
+  GL_SIGNED_RGB8_NV* = 0x000086FF
+  GL_SIGNED_LUMINANCE_NV* = 0x00008701
+  GL_SIGNED_LUMINANCE8_NV* = 0x00008702
+  GL_SIGNED_LUMINANCE_ALPHA_NV* = 0x00008703
+  GL_SIGNED_LUMINANCE8_ALPHA8_NV* = 0x00008704
+  GL_SIGNED_ALPHA_NV* = 0x00008705
+  GL_SIGNED_ALPHA8_NV* = 0x00008706
+  GL_SIGNED_INTENSITY_NV* = 0x00008707
+  GL_SIGNED_INTENSITY8_NV* = 0x00008708
+  GL_SIGNED_RGB_UNSIGNED_ALPHA_NV* = 0x0000870C
+  GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV* = 0x0000870D
+  GL_HILO16_NV* = 0x000086F8
+  GL_SIGNED_HILO_NV* = 0x000086F9
+  GL_SIGNED_HILO16_NV* = 0x000086FA
+  GL_DSDT8_NV* = 0x00008709
+  GL_DSDT8_MAG8_NV* = 0x0000870A
+  GL_DSDT_MAG_INTENSITY_NV* = 0x000086DC
+  GL_DSDT8_MAG8_INTENSITY8_NV* = 0x0000870B
+  GL_HI_SCALE_NV* = 0x0000870E
+  GL_LO_SCALE_NV* = 0x0000870F
+  GL_DS_SCALE_NV* = 0x00008710
+  GL_DT_SCALE_NV* = 0x00008711
+  GL_MAGNITUDE_SCALE_NV* = 0x00008712
+  GL_VIBRANCE_SCALE_NV* = 0x00008713
+  GL_HI_BIAS_NV* = 0x00008714
+  GL_LO_BIAS_NV* = 0x00008715
+  GL_DS_BIAS_NV* = 0x00008716
+  GL_DT_BIAS_NV* = 0x00008717
+  GL_MAGNITUDE_BIAS_NV* = 0x00008718
+  GL_VIBRANCE_BIAS_NV* = 0x00008719
+  GL_TEXTURE_BORDER_VALUES_NV* = 0x0000871A
+  GL_TEXTURE_HI_SIZE_NV* = 0x0000871B
+  GL_TEXTURE_LO_SIZE_NV* = 0x0000871C
+  GL_TEXTURE_DS_SIZE_NV* = 0x0000871D
+  GL_TEXTURE_DT_SIZE_NV* = 0x0000871E
+  GL_TEXTURE_MAG_SIZE_NV* = 0x0000871F
+  #***** GL_NV_texture_shader2 *****//
+
+const 
+  GL_DOT_PRODUCT_TEXTURE_3D_NV* = 0x000086EF # GL_HILO_NV  { already defined }
+                                             # GL_DSDT_NV  { already defined }
+                                             # GL_DSDT_MAG_NV  { already defined }
+                                             # GL_DSDT_MAG_VIB_NV  { already defined }
+                                             # GL_UNSIGNED_INT_S8_S8_8_8_NV  { already defined }
+                                             # GL_UNSIGNED_INT_8_8_S8_S8_REV_NV  { already defined }
+                                             # GL_SIGNED_RGBA_NV  { already defined }
+                                             # GL_SIGNED_RGBA8_NV  { already defined }
+                                             # GL_SIGNED_RGB_NV  { already defined }
+                                             # GL_SIGNED_RGB8_NV  { already defined }
+                                             # GL_SIGNED_LUMINANCE_NV  { already defined }
+                                             # GL_SIGNED_LUMINANCE8_NV  { already defined }
+                                             # GL_SIGNED_LUMINANCE_ALPHA_NV  { already defined }
+                                             # GL_SIGNED_LUMINANCE8_ALPHA8_NV  { already defined }
+                                             # GL_SIGNED_ALPHA_NV  { already defined }
+                                             # GL_SIGNED_ALPHA8_NV  { already defined }
+                                             # GL_SIGNED_INTENSITY_NV  { already defined }
+                                             # GL_SIGNED_INTENSITY8_NV  { already defined }
+                                             # GL_SIGNED_RGB_UNSIGNED_ALPHA_NV  { already defined }
+                                             # GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV  { already defined }
+                                             # GL_HILO16_NV  { already defined }
+                                             # GL_SIGNED_HILO_NV  { already defined }
+                                             # GL_SIGNED_HILO16_NV  { already defined }
+                                             # GL_DSDT8_NV  { already defined }
+                                             # GL_DSDT8_MAG8_NV  { already defined }
+                                             # GL_DSDT_MAG_INTENSITY_NV  { already defined }
+                                             # GL_DSDT8_MAG8_INTENSITY8_NV  { already defined }
+  #***** GL_NV_texture_shader3 *****//
+
+const 
+  GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV* = 0x00008850
+  GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV* = 0x00008851
+  GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV* = 0x00008852
+  GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV* = 0x00008853
+  GL_OFFSET_HILO_TEXTURE_2D_NV* = 0x00008854
+  GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV* = 0x00008855
+  GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV* = 0x00008856
+  GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV* = 0x00008857
+  GL_DEPENDENT_HILO_TEXTURE_2D_NV* = 0x00008858
+  GL_DEPENDENT_RGB_TEXTURE_3D_NV* = 0x00008859
+  GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV* = 0x0000885A
+  GL_DOT_PRODUCT_PASS_THROUGH_NV* = 0x0000885B
+  GL_DOT_PRODUCT_TEXTURE_1D_NV* = 0x0000885C
+  GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV* = 0x0000885D
+  GL_HILO8_NV* = 0x0000885E
+  GL_SIGNED_HILO8_NV* = 0x0000885F
+  GL_FORCE_BLUE_TO_ONE_NV* = 0x00008860
+  #***** GL_NV_vertex_array_range *****//
+
+const 
+  constGL_VERTEX_ARRAY_RANGE_NV* = 0x0000851D
+  GL_VERTEX_ARRAY_RANGE_LENGTH_NV* = 0x0000851E
+  GL_VERTEX_ARRAY_RANGE_VALID_NV* = 0x0000851F
+  GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV* = 0x00008520
+  GL_VERTEX_ARRAY_RANGE_POINTER_NV* = 0x00008521
+
+proc glVertexArrayRangeNV*(len: TGLsizei, pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glVertexArrayRangeNV".}
+proc glFlushVertexArrayRangeNV*(){.dynlib: dllname, 
+                                   importc: "glFlushVertexArrayRangeNV".}
+  #***** GL_NV_vertex_array_range2 *****//
+const 
+  GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV* = 0x00008533
+  #***** GL_NV_vertex_program *****//
+
+const 
+  GL_VERTEX_PROGRAM_NV* = 0x00008620
+  GL_VERTEX_PROGRAM_POINT_SIZE_NV* = 0x00008642
+  GL_VERTEX_PROGRAM_TWO_SIDE_NV* = 0x00008643
+  GL_VERTEX_STATE_PROGRAM_NV* = 0x00008621
+  GL_ATTRIB_ARRAY_SIZE_NV* = 0x00008623
+  GL_ATTRIB_ARRAY_STRIDE_NV* = 0x00008624
+  GL_ATTRIB_ARRAY_TYPE_NV* = 0x00008625
+  GL_CURRENT_ATTRIB_NV* = 0x00008626
+  GL_PROGRAM_PARAMETER_NV* = 0x00008644
+  GL_ATTRIB_ARRAY_POINTER_NV* = 0x00008645
+  GL_PROGRAM_TARGET_NV* = 0x00008646
+  GL_PROGRAM_LENGTH_NV* = 0x00008627
+  GL_PROGRAM_RESIDENT_NV* = 0x00008647
+  GL_PROGRAM_STRING_NV* = 0x00008628
+  constGL_TRACK_MATRIX_NV* = 0x00008648
+  GL_TRACK_MATRIX_TRANSFORM_NV* = 0x00008649
+  GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV* = 0x0000862E
+  GL_MAX_TRACK_MATRICES_NV* = 0x0000862F
+  GL_CURRENT_MATRIX_STACK_DEPTH_NV* = 0x00008640
+  GL_CURRENT_MATRIX_NV* = 0x00008641
+  GL_VERTEX_PROGRAM_BINDING_NV* = 0x0000864A
+  GL_PROGRAM_ERROR_POSITION_NV* = 0x0000864B
+  GL_MODELVIEW_PROJECTION_NV* = 0x00008629
+  GL_MATRIX0_NV* = 0x00008630
+  GL_MATRIX1_NV* = 0x00008631
+  GL_MATRIX2_NV* = 0x00008632
+  GL_MATRIX3_NV* = 0x00008633
+  GL_MATRIX4_NV* = 0x00008634
+  GL_MATRIX5_NV* = 0x00008635
+  GL_MATRIX6_NV* = 0x00008636
+  GL_MATRIX7_NV* = 0x00008637
+  GL_IDENTITY_NV* = 0x0000862A
+  GL_INVERSE_NV* = 0x0000862B
+  GL_TRANSPOSE_NV* = 0x0000862C
+  GL_INVERSE_TRANSPOSE_NV* = 0x0000862D
+  GL_VERTEX_ATTRIB_ARRAY0_NV* = 0x00008650
+  GL_VERTEX_ATTRIB_ARRAY1_NV* = 0x00008651
+  GL_VERTEX_ATTRIB_ARRAY2_NV* = 0x00008652
+  GL_VERTEX_ATTRIB_ARRAY3_NV* = 0x00008653
+  GL_VERTEX_ATTRIB_ARRAY4_NV* = 0x00008654
+  GL_VERTEX_ATTRIB_ARRAY5_NV* = 0x00008655
+  GL_VERTEX_ATTRIB_ARRAY6_NV* = 0x00008656
+  GL_VERTEX_ATTRIB_ARRAY7_NV* = 0x00008657
+  GL_VERTEX_ATTRIB_ARRAY8_NV* = 0x00008658
+  GL_VERTEX_ATTRIB_ARRAY9_NV* = 0x00008659
+  GL_VERTEX_ATTRIB_ARRAY10_NV* = 0x0000865A
+  GL_VERTEX_ATTRIB_ARRAY11_NV* = 0x0000865B
+  GL_VERTEX_ATTRIB_ARRAY12_NV* = 0x0000865C
+  GL_VERTEX_ATTRIB_ARRAY13_NV* = 0x0000865D
+  GL_VERTEX_ATTRIB_ARRAY14_NV* = 0x0000865E
+  GL_VERTEX_ATTRIB_ARRAY15_NV* = 0x0000865F
+  GL_MAP1_VERTEX_ATTRIB0_4_NV* = 0x00008660
+  GL_MAP1_VERTEX_ATTRIB1_4_NV* = 0x00008661
+  GL_MAP1_VERTEX_ATTRIB2_4_NV* = 0x00008662
+  GL_MAP1_VERTEX_ATTRIB3_4_NV* = 0x00008663
+  GL_MAP1_VERTEX_ATTRIB4_4_NV* = 0x00008664
+  GL_MAP1_VERTEX_ATTRIB5_4_NV* = 0x00008665
+  GL_MAP1_VERTEX_ATTRIB6_4_NV* = 0x00008666
+  GL_MAP1_VERTEX_ATTRIB7_4_NV* = 0x00008667
+  GL_MAP1_VERTEX_ATTRIB8_4_NV* = 0x00008668
+  GL_MAP1_VERTEX_ATTRIB9_4_NV* = 0x00008669
+  GL_MAP1_VERTEX_ATTRIB10_4_NV* = 0x0000866A
+  GL_MAP1_VERTEX_ATTRIB11_4_NV* = 0x0000866B
+  GL_MAP1_VERTEX_ATTRIB12_4_NV* = 0x0000866C
+  GL_MAP1_VERTEX_ATTRIB13_4_NV* = 0x0000866D
+  GL_MAP1_VERTEX_ATTRIB14_4_NV* = 0x0000866E
+  GL_MAP1_VERTEX_ATTRIB15_4_NV* = 0x0000866F
+  GL_MAP2_VERTEX_ATTRIB0_4_NV* = 0x00008670
+  GL_MAP2_VERTEX_ATTRIB1_4_NV* = 0x00008671
+  GL_MAP2_VERTEX_ATTRIB2_4_NV* = 0x00008672
+  GL_MAP2_VERTEX_ATTRIB3_4_NV* = 0x00008673
+  GL_MAP2_VERTEX_ATTRIB4_4_NV* = 0x00008674
+  GL_MAP2_VERTEX_ATTRIB5_4_NV* = 0x00008675
+  GL_MAP2_VERTEX_ATTRIB6_4_NV* = 0x00008676
+  GL_MAP2_VERTEX_ATTRIB7_4_NV* = 0x00008677
+  GL_MAP2_VERTEX_ATTRIB8_4_NV* = 0x00008678
+  GL_MAP2_VERTEX_ATTRIB9_4_NV* = 0x00008679
+  GL_MAP2_VERTEX_ATTRIB10_4_NV* = 0x0000867A
+  GL_MAP2_VERTEX_ATTRIB11_4_NV* = 0x0000867B
+  GL_MAP2_VERTEX_ATTRIB12_4_NV* = 0x0000867C
+  GL_MAP2_VERTEX_ATTRIB13_4_NV* = 0x0000867D
+  GL_MAP2_VERTEX_ATTRIB14_4_NV* = 0x0000867E
+  GL_MAP2_VERTEX_ATTRIB15_4_NV* = 0x0000867F
+
+proc glBindProgramNV*(target: TGLenum, id: TGLuint){.dynlib: dllname, 
+    importc: "glBindProgramNV".}
+proc glDeleteProgramsNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteProgramsNV".}
+proc glExecuteProgramNV*(target: TGLenum, id: TGLuint, params: PGLfloat){.
+    dynlib: dllname, importc: "glExecuteProgramNV".}
+proc glGenProgramsNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, 
+    importc: "glGenProgramsNV".}
+proc glAreProgramsResidentNV*(n: TGLsizei, ids: PGLuint, residences: PGLboolean): TGLboolean{.
+    dynlib: dllname, importc: "glAreProgramsResidentNV".}
+proc glRequestResidentProgramsNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, 
+    importc: "glRequestResidentProgramsNV".}
+proc glGetProgramParameterfvNV*(target: TGLenum, index: TGLuint, pname: TGLenum, 
+                                params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetProgramParameterfvNV".}
+proc glGetProgramParameterdvNV*(target: TGLenum, index: TGLuint, pname: TGLenum, 
+                                params: PGLdouble){.dynlib: dllname, 
+    importc: "glGetProgramParameterdvNV".}
+proc glGetProgramivNV*(id: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetProgramivNV".}
+proc glGetProgramStringNV*(id: TGLuint, pname: TGLenum, theProgram: PGLubyte){.
+    dynlib: dllname, importc: "glGetProgramStringNV".}
+proc glGetTrackMatrixivNV*(target: TGLenum, address: TGLuint, pname: TGLenum, 
+                           params: PGLint){.dynlib: dllname, 
+    importc: "glGetTrackMatrixivNV".}
+proc glGetVertexAttribdvNV*(index: TGLuint, pname: TGLenum, params: PGLdouble){.
+    dynlib: dllname, importc: "glGetVertexAttribdvNV".}
+proc glGetVertexAttribfvNV*(index: TGLuint, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetVertexAttribfvNV".}
+proc glGetVertexAttribivNV*(index: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetVertexAttribivNV".}
+proc glGetVertexAttribPointervNV*(index: TGLuint, pname: TGLenum, 
+                                  pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glGetVertexAttribPointervNV".}
+proc glIsProgramNV*(id: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsProgramNV".}
+proc glLoadProgramNV*(target: TGLenum, id: TGLuint, length: TGLsizei, 
+                      theProgram: PGLubyte){.dynlib: dllname, 
+    importc: "glLoadProgramNV".}
+proc glProgramParameter4fNV*(target: TGLenum, index: TGLuint, x: TGLfloat, 
+                             y: TGLfloat, z: TGLfloat, w: TGLfloat){.
+    dynlib: dllname, importc: "glProgramParameter4fNV".}
+proc glProgramParameter4fvNV*(target: TGLenum, index: TGLuint, params: PGLfloat){.
+    dynlib: dllname, importc: "glProgramParameter4fvNV".}
+proc glProgramParameters4dvNV*(target: TGLenum, index: TGLuint, num: TGLuint, 
+                               params: PGLdouble){.dynlib: dllname, 
+    importc: "glProgramParameters4dvNV".}
+proc glProgramParameters4fvNV*(target: TGLenum, index: TGLuint, num: TGLuint, 
+                               params: PGLfloat){.dynlib: dllname, 
+    importc: "glProgramParameters4fvNV".}
+proc glTrackMatrixNV*(target: TGLenum, address: TGLuint, matrix: TGLenum, 
+                      transform: TGLenum){.dynlib: dllname, 
+    importc: "glTrackMatrixNV".}
+proc glVertexAttribPointerNV*(index: TGLuint, size: TGLint, thetype: TGLenum, 
+                              stride: TGLsizei, pointer: PGLvoid){.
+    dynlib: dllname, importc: "glVertexAttribPointerNV".}
+proc glVertexAttrib1sNV*(index: TGLuint, x: TGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib1sNV".}
+proc glVertexAttrib1fNV*(index: TGLuint, x: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib1fNV".}
+proc glVertexAttrib1dNV*(index: TGLuint, x: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib1dNV".}
+proc glVertexAttrib2sNV*(index: TGLuint, x: TGLshort, y: TGLshort){.
+    dynlib: dllname, importc: "glVertexAttrib2sNV".}
+proc glVertexAttrib2fNV*(index: TGLuint, x: TGLfloat, y: TGLfloat){.
+    dynlib: dllname, importc: "glVertexAttrib2fNV".}
+proc glVertexAttrib2dNV*(index: TGLuint, x: TGLdouble, y: TGLdouble){.
+    dynlib: dllname, importc: "glVertexAttrib2dNV".}
+proc glVertexAttrib3sNV*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort){.
+    dynlib: dllname, importc: "glVertexAttrib3sNV".}
+proc glVertexAttrib3fNV*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glVertexAttrib3fNV".}
+proc glVertexAttrib3dNV*(index: TGLuint, x: TGLdouble, y: TGLdouble, 
+                         z: TGLdouble){.dynlib: dllname, 
+                                        importc: "glVertexAttrib3dNV".}
+proc glVertexAttrib4sNV*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort, 
+                         w: TGLshort){.dynlib: dllname, 
+                                       importc: "glVertexAttrib4sNV".}
+proc glVertexAttrib4fNV*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat, 
+                         w: TGLfloat){.dynlib: dllname, 
+                                       importc: "glVertexAttrib4fNV".}
+proc glVertexAttrib4dNV*(index: TGLuint, x: TGLdouble, y: TGLdouble, 
+                         z: TGLdouble, w: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib4dNV".}
+proc glVertexAttrib4ubNV*(index: TGLuint, x: TGLubyte, y: TGLubyte, z: TGLubyte, 
+                          w: TGLubyte){.dynlib: dllname, 
+                                        importc: "glVertexAttrib4ubNV".}
+proc glVertexAttrib1svNV*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib1svNV".}
+proc glVertexAttrib1fvNV*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib1fvNV".}
+proc glVertexAttrib1dvNV*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib1dvNV".}
+proc glVertexAttrib2svNV*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib2svNV".}
+proc glVertexAttrib2fvNV*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib2fvNV".}
+proc glVertexAttrib2dvNV*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib2dvNV".}
+proc glVertexAttrib3svNV*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib3svNV".}
+proc glVertexAttrib3fvNV*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib3fvNV".}
+proc glVertexAttrib3dvNV*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib3dvNV".}
+proc glVertexAttrib4svNV*(index: TGLuint, v: PGLshort){.dynlib: dllname, 
+    importc: "glVertexAttrib4svNV".}
+proc glVertexAttrib4fvNV*(index: TGLuint, v: PGLfloat){.dynlib: dllname, 
+    importc: "glVertexAttrib4fvNV".}
+proc glVertexAttrib4dvNV*(index: TGLuint, v: PGLdouble){.dynlib: dllname, 
+    importc: "glVertexAttrib4dvNV".}
+proc glVertexAttrib4ubvNV*(index: TGLuint, v: PGLubyte){.dynlib: dllname, 
+    importc: "glVertexAttrib4ubvNV".}
+proc glVertexAttribs1svNV*(index: TGLuint, n: TGLsizei, v: PGLshort){.
+    dynlib: dllname, importc: "glVertexAttribs1svNV".}
+proc glVertexAttribs1fvNV*(index: TGLuint, n: TGLsizei, v: PGLfloat){.
+    dynlib: dllname, importc: "glVertexAttribs1fvNV".}
+proc glVertexAttribs1dvNV*(index: TGLuint, n: TGLsizei, v: PGLdouble){.
+    dynlib: dllname, importc: "glVertexAttribs1dvNV".}
+proc glVertexAttribs2svNV*(index: TGLuint, n: TGLsizei, v: PGLshort){.
+    dynlib: dllname, importc: "glVertexAttribs2svNV".}
+proc glVertexAttribs2fvNV*(index: TGLuint, n: TGLsizei, v: PGLfloat){.
+    dynlib: dllname, importc: "glVertexAttribs2fvNV".}
+proc glVertexAttribs2dvNV*(index: TGLuint, n: TGLsizei, v: PGLdouble){.
+    dynlib: dllname, importc: "glVertexAttribs2dvNV".}
+proc glVertexAttribs3svNV*(index: TGLuint, n: TGLsizei, v: PGLshort){.
+    dynlib: dllname, importc: "glVertexAttribs3svNV".}
+proc glVertexAttribs3fvNV*(index: TGLuint, n: TGLsizei, v: PGLfloat){.
+    dynlib: dllname, importc: "glVertexAttribs3fvNV".}
+proc glVertexAttribs3dvNV*(index: TGLuint, n: TGLsizei, v: PGLdouble){.
+    dynlib: dllname, importc: "glVertexAttribs3dvNV".}
+proc glVertexAttribs4svNV*(index: TGLuint, n: TGLsizei, v: PGLshort){.
+    dynlib: dllname, importc: "glVertexAttribs4svNV".}
+proc glVertexAttribs4fvNV*(index: TGLuint, n: TGLsizei, v: PGLfloat){.
+    dynlib: dllname, importc: "glVertexAttribs4fvNV".}
+proc glVertexAttribs4dvNV*(index: TGLuint, n: TGLsizei, v: PGLdouble){.
+    dynlib: dllname, importc: "glVertexAttribs4dvNV".}
+proc glVertexAttribs4ubvNV*(index: TGLuint, n: TGLsizei, v: PGLubyte){.
+    dynlib: dllname, importc: "glVertexAttribs4ubvNV".}
+  #***** GL_NV_vertex_program1_1 *****//
+  #***** GL_ATI_element_array *****//
+const 
+  GL_ELEMENT_ARRAY_ATI* = 0x00008768
+  GL_ELEMENT_ARRAY_TYPE_ATI* = 0x00008769
+  GL_ELEMENT_ARRAY_POINTER_ATI* = 0x0000876A
+
+proc glElementPointerATI*(thetype: TGLenum, pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glElementPointerATI".}
+proc glDrawElementArrayATI*(mode: TGLenum, count: TGLsizei){.dynlib: dllname, 
+    importc: "glDrawElementArrayATI".}
+proc glDrawRangeElementArrayATI*(mode: TGLenum, start: TGLuint, theend: TGLuint, 
+                                 count: TGLsizei){.dynlib: dllname, 
+    importc: "glDrawRangeElementArrayATI".}
+  #***** GL_ATI_envmap_bumpmap *****//
+const 
+  GL_BUMP_ROT_MATRIX_ATI* = 0x00008775
+  GL_BUMP_ROT_MATRIX_SIZE_ATI* = 0x00008776
+  GL_BUMP_NUM_TEX_UNITS_ATI* = 0x00008777
+  GL_BUMP_TEX_UNITS_ATI* = 0x00008778
+  GL_DUDV_ATI* = 0x00008779
+  GL_DU8DV8_ATI* = 0x0000877A
+  GL_BUMP_ENVMAP_ATI* = 0x0000877B
+  GL_BUMP_TARGET_ATI* = 0x0000877C
+
+proc glTexBumpParameterivATI*(pname: TGLenum, param: PGLint){.dynlib: dllname, 
+    importc: "glTexBumpParameterivATI".}
+proc glTexBumpParameterfvATI*(pname: TGLenum, param: PGLfloat){.dynlib: dllname, 
+    importc: "glTexBumpParameterfvATI".}
+proc glGetTexBumpParameterivATI*(pname: TGLenum, param: PGLint){.
+    dynlib: dllname, importc: "glGetTexBumpParameterivATI".}
+proc glGetTexBumpParameterfvATI*(pname: TGLenum, param: PGLfloat){.
+    dynlib: dllname, importc: "glGetTexBumpParameterfvATI".}
+  #***** GL_ATI_fragment_shader *****//
+const 
+  GL_FRAGMENT_SHADER_ATI* = 0x00008920
+  GL_REG_0_ATI* = 0x00008921
+  GL_REG_1_ATI* = 0x00008922
+  GL_REG_2_ATI* = 0x00008923
+  GL_REG_3_ATI* = 0x00008924
+  GL_REG_4_ATI* = 0x00008925
+  GL_REG_5_ATI* = 0x00008926
+  GL_CON_0_ATI* = 0x00008941
+  GL_CON_1_ATI* = 0x00008942
+  GL_CON_2_ATI* = 0x00008943
+  GL_CON_3_ATI* = 0x00008944
+  GL_CON_4_ATI* = 0x00008945
+  GL_CON_5_ATI* = 0x00008946
+  GL_CON_6_ATI* = 0x00008947
+  GL_CON_7_ATI* = 0x00008948
+  GL_MOV_ATI* = 0x00008961
+  GL_ADD_ATI* = 0x00008963
+  GL_MUL_ATI* = 0x00008964
+  GL_SUB_ATI* = 0x00008965
+  GL_DOT3_ATI* = 0x00008966
+  GL_DOT4_ATI* = 0x00008967
+  GL_MAD_ATI* = 0x00008968
+  GL_LERP_ATI* = 0x00008969
+  GL_CND_ATI* = 0x0000896A
+  GL_CND0_ATI* = 0x0000896B
+  GL_DOT2_ADD_ATI* = 0x0000896C
+  GL_SECONDARY_INTERPOLATOR_ATI* = 0x0000896D
+  GL_SWIZZLE_STR_ATI* = 0x00008976
+  GL_SWIZZLE_STQ_ATI* = 0x00008977
+  GL_SWIZZLE_STR_DR_ATI* = 0x00008978
+  GL_SWIZZLE_STQ_DQ_ATI* = 0x00008979
+  GL_RED_BIT_ATI* = 0x00000001
+  GL_GREEN_BIT_ATI* = 0x00000002
+  GL_BLUE_BIT_ATI* = 0x00000004
+  GL_2X_BIT_ATI* = 0x00000001
+  GL_4X_BIT_ATI* = 0x00000002
+  GL_8X_BIT_ATI* = 0x00000004
+  GL_HALF_BIT_ATI* = 0x00000008
+  GL_QUARTER_BIT_ATI* = 0x00000010
+  GL_EIGHTH_BIT_ATI* = 0x00000020
+  GL_SATURATE_BIT_ATI* = 0x00000040 # GL_2X_BIT_ATI  { already defined }
+  GL_COMP_BIT_ATI* = 0x00000002
+  GL_NEGATE_BIT_ATI* = 0x00000004
+  GL_BIAS_BIT_ATI* = 0x00000008
+
+proc glGenFragmentShadersATI*(range: TGLuint): TGLuint{.dynlib: dllname, 
+    importc: "glGenFragmentShadersATI".}
+proc glBindFragmentShaderATI*(id: TGLuint){.dynlib: dllname, 
+    importc: "glBindFragmentShaderATI".}
+proc glDeleteFragmentShaderATI*(id: TGLuint){.dynlib: dllname, 
+    importc: "glDeleteFragmentShaderATI".}
+proc glBeginFragmentShaderATI*(){.dynlib: dllname, 
+                                  importc: "glBeginFragmentShaderATI".}
+proc glEndFragmentShaderATI*(){.dynlib: dllname, 
+                                importc: "glEndFragmentShaderATI".}
+proc glPassTexCoordATI*(dst: TGLuint, coord: TGLuint, swizzle: TGLenum){.
+    dynlib: dllname, importc: "glPassTexCoordATI".}
+proc glSampleMapATI*(dst: TGLuint, interp: TGLuint, swizzle: TGLenum){.
+    dynlib: dllname, importc: "glSampleMapATI".}
+proc glColorFragmentOp1ATI*(op: TGLenum, dst: TGLuint, dstMask: TGLuint, 
+                            dstMod: TGLuint, arg1: TGLuint, arg1Rep: TGLuint, 
+                            arg1Mod: TGLuint){.dynlib: dllname, 
+    importc: "glColorFragmentOp1ATI".}
+proc glColorFragmentOp2ATI*(op: TGLenum, dst: TGLuint, dstMask: TGLuint, 
+                            dstMod: TGLuint, arg1: TGLuint, arg1Rep: TGLuint, 
+                            arg1Mod: TGLuint, arg2: TGLuint, arg2Rep: TGLuint, 
+                            arg2Mod: TGLuint){.dynlib: dllname, 
+    importc: "glColorFragmentOp2ATI".}
+proc glColorFragmentOp3ATI*(op: TGLenum, dst: TGLuint, dstMask: TGLuint, 
+                            dstMod: TGLuint, arg1: TGLuint, arg1Rep: TGLuint, 
+                            arg1Mod: TGLuint, arg2: TGLuint, arg2Rep: TGLuint, 
+                            arg2Mod: TGLuint, arg3: TGLuint, arg3Rep: TGLuint, 
+                            arg3Mod: TGLuint){.dynlib: dllname, 
+    importc: "glColorFragmentOp3ATI".}
+proc glAlphaFragmentOp1ATI*(op: TGLenum, dst: TGLuint, dstMod: TGLuint, 
+                            arg1: TGLuint, arg1Rep: TGLuint, arg1Mod: TGLuint){.
+    dynlib: dllname, importc: "glAlphaFragmentOp1ATI".}
+proc glAlphaFragmentOp2ATI*(op: TGLenum, dst: TGLuint, dstMod: TGLuint, 
+                            arg1: TGLuint, arg1Rep: TGLuint, arg1Mod: TGLuint, 
+                            arg2: TGLuint, arg2Rep: TGLuint, arg2Mod: TGLuint){.
+    dynlib: dllname, importc: "glAlphaFragmentOp2ATI".}
+proc glAlphaFragmentOp3ATI*(op: TGLenum, dst: TGLuint, dstMod: TGLuint, 
+                            arg1: TGLuint, arg1Rep: TGLuint, arg1Mod: TGLuint, 
+                            arg2: TGLuint, arg2Rep: TGLuint, arg2Mod: TGLuint, 
+                            arg3: TGLuint, arg3Rep: TGLuint, arg3Mod: TGLuint){.
+    dynlib: dllname, importc: "glAlphaFragmentOp3ATI".}
+proc glSetFragmentShaderConstantATI*(dst: TGLuint, value: PGLfloat){.
+    dynlib: dllname, importc: "glSetFragmentShaderConstantATI".}
+  #***** GL_ATI_pn_triangles *****//
+const 
+  GL_PN_TRIANGLES_ATI* = 0x000087F0
+  GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI* = 0x000087F1
+  GL_PN_TRIANGLES_POINT_MODE_ATI* = 0x000087F2
+  GL_PN_TRIANGLES_NORMAL_MODE_ATI* = 0x000087F3
+  GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI* = 0x000087F4
+  GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI* = 0x000087F5
+  GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI* = 0x000087F6
+  GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI* = 0x000087F7
+  GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI* = 0x000087F8
+
+proc glPNTrianglesiATI*(pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glPNTrianglesiATI".}
+proc glPNTrianglesfATI*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glPNTrianglesfATI".}
+  #***** GL_ATI_texture_mirror_once *****//
+const 
+  GL_MIRROR_CLAMP_ATI* = 0x00008742
+  GL_MIRROR_CLAMP_TO_EDGE_ATI* = 0x00008743
+  #***** GL_ATI_vertex_array_object *****//
+
+const 
+  GL_STATIC_ATI* = 0x00008760
+  GL_DYNAMIC_ATI* = 0x00008761
+  GL_PRESERVE_ATI* = 0x00008762
+  GL_DISCARD_ATI* = 0x00008763
+  GL_OBJECT_BUFFER_SIZE_ATI* = 0x00008764
+  GL_OBJECT_BUFFER_USAGE_ATI* = 0x00008765
+  GL_ARRAY_OBJECT_BUFFER_ATI* = 0x00008766
+  GL_ARRAY_OBJECT_OFFSET_ATI* = 0x00008767
+
+proc glNewObjectBufferATI*(size: TGLsizei, pointer: PGLvoid, usage: TGLenum): TGLuint{.
+    dynlib: dllname, importc: "glNewObjectBufferATI".}
+proc glIsObjectBufferATI*(buffer: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsObjectBufferATI".}
+proc glUpdateObjectBufferATI*(buffer: TGLuint, offset: TGLuint, size: TGLsizei, 
+                              pointer: PGLvoid, preserve: TGLenum){.
+    dynlib: dllname, importc: "glUpdateObjectBufferATI".}
+proc glGetObjectBufferfvATI*(buffer: TGLuint, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetObjectBufferfvATI".}
+proc glGetObjectBufferivATI*(buffer: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetObjectBufferivATI".}
+proc glDeleteObjectBufferATI*(buffer: TGLuint){.dynlib: dllname, 
+    importc: "glDeleteObjectBufferATI".}
+proc glArrayObjectATI*(thearray: TGLenum, size: TGLint, thetype: TGLenum, 
+                       stride: TGLsizei, buffer: TGLuint, offset: TGLuint){.
+    dynlib: dllname, importc: "glArrayObjectATI".}
+proc glGetArrayObjectfvATI*(thearray: TGLenum, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetArrayObjectfvATI".}
+proc glGetArrayObjectivATI*(thearray: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetArrayObjectivATI".}
+proc glVariantArrayObjectATI*(id: TGLuint, thetype: TGLenum, stride: TGLsizei, 
+                              buffer: TGLuint, offset: TGLuint){.
+    dynlib: dllname, importc: "glVariantArrayObjectATI".}
+proc glGetVariantArrayObjectfvATI*(id: TGLuint, pname: TGLenum, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetVariantArrayObjectfvATI".}
+proc glGetVariantArrayObjectivATI*(id: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetVariantArrayObjectivATI".}
+  #***** GL_ATI_vertex_streams *****//
+const 
+  GL_MAX_VERTEX_STREAMS_ATI* = 0x0000876B
+  GL_VERTEX_STREAM0_ATI* = 0x0000876C
+  GL_VERTEX_STREAM1_ATI* = 0x0000876D
+  GL_VERTEX_STREAM2_ATI* = 0x0000876E
+  GL_VERTEX_STREAM3_ATI* = 0x0000876F
+  GL_VERTEX_STREAM4_ATI* = 0x00008770
+  GL_VERTEX_STREAM5_ATI* = 0x00008771
+  GL_VERTEX_STREAM6_ATI* = 0x00008772
+  GL_VERTEX_STREAM7_ATI* = 0x00008773
+  GL_VERTEX_SOURCE_ATI* = 0x00008774
+
+proc glVertexStream1s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glVertexStream1s".}
+proc glVertexStream1i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glVertexStream1i".}
+proc glVertexStream1f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexStream1f".}
+proc glVertexStream1d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexStream1d".}
+proc glVertexStream1sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glVertexStream1sv".}
+proc glVertexStream1iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glVertexStream1iv".}
+proc glVertexStream1fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexStream1fv".}
+proc glVertexStream1dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexStream1dv".}
+proc glVertexStream2s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glVertexStream2s".}
+proc glVertexStream2i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glVertexStream2i".}
+proc glVertexStream2f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexStream2f".}
+proc glVertexStream2d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexStream2d".}
+proc glVertexStream2sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glVertexStream2sv".}
+proc glVertexStream2iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glVertexStream2iv".}
+proc glVertexStream2fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexStream2fv".}
+proc glVertexStream2dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexStream2dv".}
+proc glVertexStream3s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glVertexStream3s".}
+proc glVertexStream3i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glVertexStream3i".}
+proc glVertexStream3f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexStream3f".}
+proc glVertexStream3d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexStream3d".}
+proc glVertexStream3sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glVertexStream3sv".}
+proc glVertexStream3iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glVertexStream3iv".}
+proc glVertexStream3fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexStream3fv".}
+proc glVertexStream3dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexStream3dv".}
+proc glVertexStream4s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glVertexStream4s".}
+proc glVertexStream4i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glVertexStream4i".}
+proc glVertexStream4f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexStream4f".}
+proc glVertexStream4d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexStream4d".}
+proc glVertexStream4sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glVertexStream4sv".}
+proc glVertexStream4iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glVertexStream4iv".}
+proc glVertexStream4fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexStream4fv".}
+proc glVertexStream4dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glVertexStream4dv".}
+proc glNormalStream3b*(stream: TGLenum, coords: TGLByte){.dynlib: dllname, 
+    importc: "glNormalStream3b".}
+proc glNormalStream3s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glNormalStream3s".}
+proc glNormalStream3i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glNormalStream3i".}
+proc glNormalStream3f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glNormalStream3f".}
+proc glNormalStream3d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glNormalStream3d".}
+proc glNormalStream3bv*(stream: TGLenum, coords: TGLByte){.dynlib: dllname, 
+    importc: "glNormalStream3bv".}
+proc glNormalStream3sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, 
+    importc: "glNormalStream3sv".}
+proc glNormalStream3iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, 
+    importc: "glNormalStream3iv".}
+proc glNormalStream3fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, 
+    importc: "glNormalStream3fv".}
+proc glNormalStream3dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, 
+    importc: "glNormalStream3dv".}
+proc glClientActiveVertexStream*(stream: TGLenum){.dynlib: dllname, 
+    importc: "glClientActiveVertexStream".}
+proc glVertexBlendEnvi*(pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glVertexBlendEnvi".}
+proc glVertexBlendEnvf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glVertexBlendEnvf".}
+  #***** GL_3DFX_texture_compression_FXT1 *****//
+const 
+  GL_COMPRESSED_RGB_FXT1_3DFX* = 0x000086B0
+  GL_COMPRESSED_RGBA_FXT1_3DFX* = 0x000086B1
+  #***** GL_IBM_cull_vertex *****//
+
+const 
+  GL_CULL_VERTEX_IBM* = 0x0001928A
+  #***** GL_IBM_multimode_draw_arrays *****//
+
+proc glMultiModeDrawArraysIBM*(mode: PGLenum, first: PGLint, count: PGLsizei, 
+                               primcount: TGLsizei, modestride: TGLint){.
+    dynlib: dllname, importc: "glMultiModeDrawArraysIBM".}
+proc glMultiModeDrawElementsIBM*(mode: PGLenum, count: PGLsizei, 
+                                 thetype: TGLenum, indices: PGLvoid, 
+                                 primcount: TGLsizei, modestride: TGLint){.
+    dynlib: dllname, importc: "glMultiModeDrawElementsIBM".}
+  #***** GL_IBM_raster_pos_clip *****//
+const 
+  GL_RASTER_POSITION_UNCLIPPED_IBM* = 0x00019262
+  #***** GL_IBM_texture_mirrored_repeat *****//
+
+const 
+  GL_MIRRORED_REPEAT_IBM* = 0x00008370
+  #***** GL_IBM_vertex_array_lists *****//
+
+const 
+  GL_VERTEX_ARRAY_LIST_IBM* = 0x0001929E
+  GL_NORMAL_ARRAY_LIST_IBM* = 0x0001929F
+  GL_COLOR_ARRAY_LIST_IBM* = 0x000192A0
+  GL_INDEX_ARRAY_LIST_IBM* = 0x000192A1
+  GL_TEXTURE_COORD_ARRAY_LIST_IBM* = 0x000192A2
+  GL_EDGE_FLAG_ARRAY_LIST_IBM* = 0x000192A3
+  GL_FOG_COORDINATE_ARRAY_LIST_IBM* = 0x000192A4
+  GL_SECONDARY_COLOR_ARRAY_LIST_IBM* = 0x000192A5
+  GL_VERTEX_ARRAY_LIST_STRIDE_IBM* = 0x000192A8
+  GL_NORMAL_ARRAY_LIST_STRIDE_IBM* = 0x000192A9
+  GL_COLOR_ARRAY_LIST_STRIDE_IBM* = 0x000192AA
+  GL_INDEX_ARRAY_LIST_STRIDE_IBM* = 0x000192AB
+  GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM* = 0x000192AC
+  GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM* = 0x000192AD
+  GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM* = 0x000192AE
+  GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM* = 0x000192AF
+
+proc glColorPointerListIBM*(size: TGLint, thetype: TGLenum, stride: TGLint, 
+                            pointer: PGLvoid, ptrstride: TGLint){.
+    dynlib: dllname, importc: "glColorPointerListIBM".}
+proc glSecondaryColorPointerListIBM*(size: TGLint, thetype: TGLenum, 
+                                     stride: TGLint, pointer: PGLvoid, 
+                                     ptrstride: TGLint){.dynlib: dllname, 
+    importc: "glSecondaryColorPointerListIBM".}
+proc glEdgeFlagPointerListIBM*(stride: TGLint, pointer: PGLboolean, 
+                               ptrstride: TGLint){.dynlib: dllname, 
+    importc: "glEdgeFlagPointerListIBM".}
+proc glFogCoordPointerListIBM*(thetype: TGLenum, stride: TGLint, 
+                               pointer: PGLvoid, ptrstride: TGLint){.
+    dynlib: dllname, importc: "glFogCoordPointerListIBM".}
+proc glNormalPointerListIBM*(thetype: TGLenum, stride: TGLint, pointer: PGLvoid, 
+                             ptrstride: TGLint){.dynlib: dllname, 
+    importc: "glNormalPointerListIBM".}
+proc glTexCoordPointerListIBM*(size: TGLint, thetype: TGLenum, stride: TGLint, 
+                               pointer: PGLvoid, ptrstride: TGLint){.
+    dynlib: dllname, importc: "glTexCoordPointerListIBM".}
+proc glVertexPointerListIBM*(size: TGLint, thetype: TGLenum, stride: TGLint, 
+                             pointer: PGLvoid, ptrstride: TGLint){.
+    dynlib: dllname, importc: "glVertexPointerListIBM".}
+  #***** GL_MESA_resize_buffers *****//
+proc glResizeBuffersMESA*(){.dynlib: dllname, importc: "glResizeBuffersMESA".}
+  #***** GL_MESA_window_pos *****//
+proc glWindowPos2dMESA*(x: TGLdouble, y: TGLdouble){.dynlib: dllname, 
+    importc: "glWindowPos2dMESA".}
+proc glWindowPos2fMESA*(x: TGLfloat, y: TGLfloat){.dynlib: dllname, 
+    importc: "glWindowPos2fMESA".}
+proc glWindowPos2iMESA*(x: TGLint, y: TGLint){.dynlib: dllname, 
+    importc: "glWindowPos2iMESA".}
+proc glWindowPos2sMESA*(x: TGLshort, y: TGLshort){.dynlib: dllname, 
+    importc: "glWindowPos2sMESA".}
+proc glWindowPos2ivMESA*(p: PGLint){.dynlib: dllname, 
+                                     importc: "glWindowPos2ivMESA".}
+proc glWindowPos2svMESA*(p: PGLshort){.dynlib: dllname, 
+                                       importc: "glWindowPos2svMESA".}
+proc glWindowPos2fvMESA*(p: PGLfloat){.dynlib: dllname, 
+                                       importc: "glWindowPos2fvMESA".}
+proc glWindowPos2dvMESA*(p: PGLdouble){.dynlib: dllname, 
+                                        importc: "glWindowPos2dvMESA".}
+proc glWindowPos3iMESA*(x: TGLint, y: TGLint, z: TGLint){.dynlib: dllname, 
+    importc: "glWindowPos3iMESA".}
+proc glWindowPos3sMESA*(x: TGLshort, y: TGLshort, z: TGLshort){.dynlib: dllname, 
+    importc: "glWindowPos3sMESA".}
+proc glWindowPos3fMESA*(x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, 
+    importc: "glWindowPos3fMESA".}
+proc glWindowPos3dMESA*(x: TGLdouble, y: TGLdouble, z: TGLdouble){.
+    dynlib: dllname, importc: "glWindowPos3dMESA".}
+proc glWindowPos3ivMESA*(p: PGLint){.dynlib: dllname, 
+                                     importc: "glWindowPos3ivMESA".}
+proc glWindowPos3svMESA*(p: PGLshort){.dynlib: dllname, 
+                                       importc: "glWindowPos3svMESA".}
+proc glWindowPos3fvMESA*(p: PGLfloat){.dynlib: dllname, 
+                                       importc: "glWindowPos3fvMESA".}
+proc glWindowPos3dvMESA*(p: PGLdouble){.dynlib: dllname, 
+                                        importc: "glWindowPos3dvMESA".}
+proc glWindowPos4iMESA*(x: TGLint, y: TGLint, z: TGLint, w: TGLint){.
+    dynlib: dllname, importc: "glWindowPos4iMESA".}
+proc glWindowPos4sMESA*(x: TGLshort, y: TGLshort, z: TGLshort, w: TGLshort){.
+    dynlib: dllname, importc: "glWindowPos4sMESA".}
+proc glWindowPos4fMESA*(x: TGLfloat, y: TGLfloat, z: TGLfloat, w: TGLfloat){.
+    dynlib: dllname, importc: "glWindowPos4fMESA".}
+proc glWindowPos4dMESA*(x: TGLdouble, y: TGLdouble, z: TGLdouble, w: TGLdouble){.
+    dynlib: dllname, importc: "glWindowPos4dMESA".}
+proc glWindowPos4ivMESA*(p: PGLint){.dynlib: dllname, 
+                                     importc: "glWindowPos4ivMESA".}
+proc glWindowPos4svMESA*(p: PGLshort){.dynlib: dllname, 
+                                       importc: "glWindowPos4svMESA".}
+proc glWindowPos4fvMESA*(p: PGLfloat){.dynlib: dllname, 
+                                       importc: "glWindowPos4fvMESA".}
+proc glWindowPos4dvMESA*(p: PGLdouble){.dynlib: dllname, 
+                                        importc: "glWindowPos4dvMESA".}
+  #***** GL_OML_interlace *****//
+const 
+  GL_INTERLACE_OML* = 0x00008980
+  GL_INTERLACE_READ_OML* = 0x00008981
+  #***** GL_OML_resample *****//
+
+const 
+  GL_PACK_RESAMPLE_OML* = 0x00008984
+  GL_UNPACK_RESAMPLE_OML* = 0x00008985
+  GL_RESAMPLE_REPLICATE_OML* = 0x00008986
+  GL_RESAMPLE_ZERO_FILL_OML* = 0x00008987
+  GL_RESAMPLE_AVERAGE_OML* = 0x00008988
+  GL_RESAMPLE_DECIMATE_OML* = 0x00008989 # GL_RESAMPLE_AVERAGE_OML  { already defined }
+  #***** GL_OML_subsample *****//
+
+const 
+  GL_FORMAT_SUBSAMPLE_24_24_OML* = 0x00008982
+  GL_FORMAT_SUBSAMPLE_244_244_OML* = 0x00008983
+  #***** GL_SGIS_generate_mipmap *****//
+
+const 
+  GL_GENERATE_MIPMAP_SGIS* = 0x00008191
+  GL_GENERATE_MIPMAP_HINT_SGIS* = 0x00008192
+  #***** GL_SGIS_multisample *****//
+
+const 
+  GLX_SAMPLE_BUFFERS_SGIS* = 0x000186A0
+  GLX_SAMPLES_SGIS* = 0x000186A1
+  GL_MULTISAMPLE_SGIS* = 0x0000809D
+  GL_SAMPLE_ALPHA_TO_MASK_SGIS* = 0x0000809E
+  GL_SAMPLE_ALPHA_TO_ONE_SGIS* = 0x0000809F
+  constGL_SAMPLE_MASK_SGIS* = 0x000080A0
+  GL_MULTISAMPLE_BIT_EXT* = 0x20000000
+  GL_1PASS_SGIS* = 0x000080A1
+  GL_2PASS_0_SGIS* = 0x000080A2
+  GL_2PASS_1_SGIS* = 0x000080A3
+  GL_4PASS_0_SGIS* = 0x000080A4
+  GL_4PASS_1_SGIS* = 0x000080A5
+  GL_4PASS_2_SGIS* = 0x000080A6
+  GL_4PASS_3_SGIS* = 0x000080A7
+  GL_SAMPLE_BUFFERS_SGIS* = 0x000080A8
+  GL_SAMPLES_SGIS* = 0x000080A9
+  GL_SAMPLE_MASK_VALUE_SGIS* = 0x000080AA
+  GL_SAMPLE_MASK_INVERT_SGIS* = 0x000080AB
+  constGL_SAMPLE_PATTERN_SGIS* = 0x000080AC
+
+proc glSampleMaskSGIS*(value: TGLclampf, invert: TGLboolean){.dynlib: dllname, 
+    importc: "glSampleMaskSGIS".}
+proc glSamplePatternSGIS*(pattern: TGLenum){.dynlib: dllname, 
+    importc: "glSamplePatternSGIS".}
+  #***** GL_SGIS_pixel_texture *****//
+const 
+  GL_PIXEL_TEXTURE_SGIS* = 0x00008353
+  GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS* = 0x00008354
+  GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS* = 0x00008355
+  GL_PIXEL_GROUP_COLOR_SGIS* = 0x00008356
+
+proc glPixelTexGenParameteriSGIS*(pname: TGLenum, param: TGLint){.
+    dynlib: dllname, importc: "glPixelTexGenParameteriSGIS".}
+proc glPixelTexGenParameterfSGIS*(pname: TGLenum, param: TGLfloat){.
+    dynlib: dllname, importc: "glPixelTexGenParameterfSGIS".}
+proc glGetPixelTexGenParameterivSGIS*(pname: TGLenum, params: TGLint){.
+    dynlib: dllname, importc: "glGetPixelTexGenParameterivSGIS".}
+proc glGetPixelTexGenParameterfvSGIS*(pname: TGLenum, params: TGLfloat){.
+    dynlib: dllname, importc: "glGetPixelTexGenParameterfvSGIS".}
+  #***** GL_SGIS_texture_border_clamp *****//
+  # GL_CLAMP_TO_BORDER_SGIS  { already defined }
+  #***** GL_SGIS_texture_color_mask *****//
+const 
+  GL_TEXTURE_COLOR_WRITEMASK_SGIS* = 0x000081EF
+
+proc glTextureColorMaskSGIS*(r: TGLboolean, g: TGLboolean, b: TGLboolean, 
+                             a: TGLboolean){.dynlib: dllname, 
+    importc: "glTextureColorMaskSGIS".}
+  #***** GL_SGIS_texture_edge_clamp *****//
+const 
+  GL_CLAMP_TO_EDGE_SGIS* = 0x0000812F
+  #***** GL_SGIS_texture_lod *****//
+
+const 
+  GL_TEXTURE_MIN_LOD_SGIS* = 0x0000813A
+  GL_TEXTURE_MAX_LOD_SGIS* = 0x0000813B
+  GL_TEXTURE_BASE_LEVEL_SGIS* = 0x0000813C
+  GL_TEXTURE_MAX_LEVEL_SGIS* = 0x0000813D
+  #***** GL_SGIS_depth_texture *****//
+
+const 
+  GL_DEPTH_COMPONENT16_SGIX* = 0x000081A5
+  GL_DEPTH_COMPONENT24_SGIX* = 0x000081A6
+  GL_DEPTH_COMPONENT32_SGIX* = 0x000081A7
+  #***** GL_SGIX_fog_offset *****//
+
+const 
+  GL_FOG_OFFSET_SGIX* = 0x00008198
+  GL_FOG_OFFSET_VALUE_SGIX* = 0x00008199
+  #***** GL_SGIX_interlace *****//
+
+const 
+  GL_INTERLACE_SGIX* = 0x00008094
+  #***** GL_SGIX_shadow_ambient *****//
+
+const 
+  GL_SHADOW_AMBIENT_SGIX* = 0x000080BF
+  #***** GL_SGI_color_matrix *****//
+
+const 
+  GL_COLOR_MATRIX_SGI* = 0x000080B1
+  GL_COLOR_MATRIX_STACK_DEPTH_SGI* = 0x000080B2
+  GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI* = 0x000080B3
+  GL_POST_COLOR_MATRIX_RED_SCALE_SGI* = 0x000080B4
+  GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI* = 0x000080B5
+  GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI* = 0x000080B6
+  GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI* = 0x000080B7
+  GL_POST_COLOR_MATRIX_RED_BIAS_SGI* = 0x000080B8
+  GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI* = 0x000080B9
+  GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI* = 0x000080BA
+  GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI* = 0x000080BB
+  #***** GL_SGI_color_table *****//
+
+const 
+  constGL_COLOR_TABLE_SGI* = 0x000080D0
+  GL_POST_CONVOLUTION_COLOR_TABLE_SGI* = 0x000080D1
+  GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI* = 0x000080D2
+  GL_PROXY_COLOR_TABLE_SGI* = 0x000080D3
+  GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI* = 0x000080D4
+  GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI* = 0x000080D5
+  GL_COLOR_TABLE_SCALE_SGI* = 0x000080D6
+  GL_COLOR_TABLE_BIAS_SGI* = 0x000080D7
+  GL_COLOR_TABLE_FORMAT_SGI* = 0x000080D8
+  GL_COLOR_TABLE_WIDTH_SGI* = 0x000080D9
+  GL_COLOR_TABLE_RED_SIZE_SGI* = 0x000080DA
+  GL_COLOR_TABLE_GREEN_SIZE_SGI* = 0x000080DB
+  GL_COLOR_TABLE_BLUE_SIZE_SGI* = 0x000080DC
+  GL_COLOR_TABLE_ALPHA_SIZE_SGI* = 0x000080DD
+  GL_COLOR_TABLE_LUMINANCE_SIZE_SGI* = 0x000080DE
+  GL_COLOR_TABLE_INTENSITY_SIZE_SGI* = 0x000080DF
+
+proc glColorTableSGI*(target: TGLenum, internalformat: TGLenum, width: TGLsizei, 
+                      format: TGLenum, thetype: TGLenum, table: PGLvoid){.
+    dynlib: dllname, importc: "glColorTableSGI".}
+proc glCopyColorTableSGI*(target: TGLenum, internalformat: TGLenum, x: TGLint, 
+                          y: TGLint, width: TGLsizei){.dynlib: dllname, 
+    importc: "glCopyColorTableSGI".}
+proc glColorTableParameterivSGI*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glColorTableParameterivSGI".}
+proc glColorTableParameterfvSGI*(target: TGLenum, pname: TGLenum, 
+                                 params: PGLfloat){.dynlib: dllname, 
+    importc: "glColorTableParameterfvSGI".}
+proc glGetColorTableSGI*(target: TGLenum, format: TGLenum, thetype: TGLenum, 
+                         table: PGLvoid){.dynlib: dllname, 
+    importc: "glGetColorTableSGI".}
+proc glGetColorTableParameterivSGI*(target: TGLenum, pname: TGLenum, 
+                                    params: PGLint){.dynlib: dllname, 
+    importc: "glGetColorTableParameterivSGI".}
+proc glGetColorTableParameterfvSGI*(target: TGLenum, pname: TGLenum, 
+                                    params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetColorTableParameterfvSGI".}
+  #***** GL_SGI_texture_color_table *****//
+const 
+  GL_TEXTURE_COLOR_TABLE_SGI* = 0x000080BC
+  GL_PROXY_TEXTURE_COLOR_TABLE_SGI* = 0x000080BD
+  #***** GL_SUN_vertex *****//
+
+proc glColor4ubVertex2fSUN*(r: TGLubyte, g: TGLubyte, b: TGLubyte, a: TGLubyte, 
+                            x: TGLfloat, y: TGLfloat){.dynlib: dllname, 
+    importc: "glColor4ubVertex2fSUN".}
+proc glColor4ubVertex2fvSUN*(c: PGLubyte, v: PGLfloat){.dynlib: dllname, 
+    importc: "glColor4ubVertex2fvSUN".}
+proc glColor4ubVertex3fSUN*(r: TGLubyte, g: TGLubyte, b: TGLubyte, a: TGLubyte, 
+                            x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glColor4ubVertex3fSUN".}
+proc glColor4ubVertex3fvSUN*(c: PGLubyte, v: PGLfloat){.dynlib: dllname, 
+    importc: "glColor4ubVertex3fvSUN".}
+proc glColor3fVertex3fSUN*(r: TGLfloat, g: TGLfloat, b: TGLfloat, x: TGLfloat, 
+                           y: TGLfloat, z: TGLfloat){.dynlib: dllname, 
+    importc: "glColor3fVertex3fSUN".}
+proc glColor3fVertex3fvSUN*(c: PGLfloat, v: PGLfloat){.dynlib: dllname, 
+    importc: "glColor3fVertex3fvSUN".}
+proc glNormal3fVertex3fSUN*(nx: TGLfloat, ny: TGLfloat, nz: TGLfloat, 
+                            x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glNormal3fVertex3fSUN".}
+proc glNormal3fVertex3fvSUN*(n: PGLfloat, v: PGLfloat){.dynlib: dllname, 
+    importc: "glNormal3fVertex3fvSUN".}
+proc glColor4fNormal3fVertex3fSUN*(r: TGLfloat, g: TGLfloat, b: TGLfloat, 
+                                   a: TGLfloat, nx: TGLfloat, ny: TGLfloat, 
+                                   nz: TGLfloat, x: TGLfloat, y: TGLfloat, 
+                                   z: TGLfloat){.dynlib: dllname, 
+    importc: "glColor4fNormal3fVertex3fSUN".}
+proc glColor4fNormal3fVertex3fvSUN*(c: PGLfloat, n: PGLfloat, v: PGLfloat){.
+    dynlib: dllname, importc: "glColor4fNormal3fVertex3fvSUN".}
+proc glTexCoord2fVertex3fSUN*(s: TGLfloat, t: TGLfloat, x: TGLfloat, 
+                              y: TGLfloat, z: TGLfloat){.dynlib: dllname, 
+    importc: "glTexCoord2fVertex3fSUN".}
+proc glTexCoord2fVertex3fvSUN*(tc: PGLfloat, v: PGLfloat){.dynlib: dllname, 
+    importc: "glTexCoord2fVertex3fvSUN".}
+proc glTexCoord4fVertex4fSUN*(s: TGLfloat, t: TGLfloat, p: TGLfloat, 
+                              q: TGLfloat, x: TGLfloat, y: TGLfloat, 
+                              z: TGLfloat, w: TGLfloat){.dynlib: dllname, 
+    importc: "glTexCoord4fVertex4fSUN".}
+proc glTexCoord4fVertex4fvSUN*(tc: PGLfloat, v: PGLfloat){.dynlib: dllname, 
+    importc: "glTexCoord4fVertex4fvSUN".}
+proc glTexCoord2fColor4ubVertex3fSUN*(s: TGLfloat, t: TGLfloat, r: TGLubyte, 
+                                      g: TGLubyte, b: TGLubyte, a: TGLubyte, 
+                                      x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glTexCoord2fColor4ubVertex3fSUN".}
+proc glTexCoord2fColor4ubVertex3fvSUN*(tc: PGLfloat, c: PGLubyte, v: PGLfloat){.
+    dynlib: dllname, importc: "glTexCoord2fColor4ubVertex3fvSUN".}
+proc glTexCoord2fColor3fVertex3fSUN*(s: TGLfloat, t: TGLfloat, r: TGLfloat, 
+                                     g: TGLfloat, b: TGLfloat, x: TGLfloat, 
+                                     y: TGLfloat, z: TGLfloat){.dynlib: dllname, 
+    importc: "glTexCoord2fColor3fVertex3fSUN".}
+proc glTexCoord2fColor3fVertex3fvSUN*(tc: PGLfloat, c: PGLfloat, v: PGLfloat){.
+    dynlib: dllname, importc: "glTexCoord2fColor3fVertex3fvSUN".}
+proc glTexCoord2fNormal3fVertex3fSUN*(s: TGLfloat, t: TGLfloat, nx: TGLfloat, 
+                                      ny: TGLfloat, nz: TGLfloat, x: TGLfloat, 
+                                      y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glTexCoord2fNormal3fVertex3fSUN".}
+proc glTexCoord2fNormal3fVertex3fvSUN*(tc: PGLfloat, n: PGLfloat, v: PGLfloat){.
+    dynlib: dllname, importc: "glTexCoord2fNormal3fVertex3fvSUN".}
+proc glTexCoord2fColor4fNormal3fVertex3fSUN*(s: TGLfloat, t: TGLfloat, 
+    r: TGLfloat, g: TGLfloat, b: TGLfloat, a: TGLfloat, nx: TGLfloat, 
+    ny: TGLfloat, nz: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glTexCoord2fColor4fNormal3fVertex3fSUN".}
+proc glTexCoord2fColor4fNormal3fVertex3fvSUN*(tc: PGLfloat, c: PGLfloat, 
+    n: PGLfloat, v: PGLfloat){.dynlib: dllname, importc: "glTexCoord2fColor4fNormal3fVertex3fvSUN".}
+proc glTexCoord4fColor4fNormal3fVertex4fSUN*(s: TGLfloat, t: TGLfloat, 
+    p: TGLfloat, q: TGLfloat, r: TGLfloat, g: TGLfloat, b: TGLfloat, 
+    a: TGLfloat, nx: TGLfloat, ny: TGLfloat, nz: TGLfloat, x: TGLfloat, 
+    y: TGLfloat, z: TGLfloat, w: TGLfloat){.dynlib: dllname, 
+    importc: "glTexCoord4fColor4fNormal3fVertex4fSUN".}
+proc glTexCoord4fColor4fNormal3fVertex4fvSUN*(tc: PGLfloat, c: PGLfloat, 
+    n: PGLfloat, v: PGLfloat){.dynlib: dllname, importc: "glTexCoord4fColor4fNormal3fVertex4fvSUN".}
+proc glReplacementCodeuiVertex3fSUN*(rc: TGLuint, x: TGLfloat, y: TGLfloat, 
+                                     z: TGLfloat){.dynlib: dllname, 
+    importc: "glReplacementCodeuiVertex3fSUN".}
+proc glReplacementCodeuiVertex3fvSUN*(rc: PGLuint, v: PGLfloat){.
+    dynlib: dllname, importc: "glReplacementCodeuiVertex3fvSUN".}
+proc glReplacementCodeuiColor4ubVertex3fSUN*(rc: TGLuint, r: TGLubyte, 
+    g: TGLubyte, b: TGLubyte, a: TGLubyte, x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glReplacementCodeuiColor4ubVertex3fSUN".}
+proc glReplacementCodeuiColor4ubVertex3fvSUN*(rc: PGLuint, c: PGLubyte, 
+    v: PGLfloat){.dynlib: dllname, 
+                  importc: "glReplacementCodeuiColor4ubVertex3fvSUN".}
+proc glReplacementCodeuiColor3fVertex3fSUN*(rc: TGLuint, r: TGLfloat, 
+    g: TGLfloat, b: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glReplacementCodeuiColor3fVertex3fSUN".}
+proc glReplacementCodeuiColor3fVertex3fvSUN*(rc: PGLuint, c: PGLfloat, 
+    v: PGLfloat){.dynlib: dllname, 
+                  importc: "glReplacementCodeuiColor3fVertex3fvSUN".}
+proc glReplacementCodeuiNormal3fVertex3fSUN*(rc: TGLuint, nx: TGLfloat, 
+    ny: TGLfloat, nz: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){.
+    dynlib: dllname, importc: "glReplacementCodeuiNormal3fVertex3fSUN".}
+proc glReplacementCodeuiNormal3fVertex3fvSUN*(rc: PGLuint, n: PGLfloat, 
+    v: PGLfloat){.dynlib: dllname, 
+                  importc: "glReplacementCodeuiNormal3fVertex3fvSUN".}
+proc glReplacementCodeuiColor4fNormal3fVertex3fSUN*(rc: TGLuint, r: TGLfloat, 
+    g: TGLfloat, b: TGLfloat, a: TGLfloat, nx: TGLfloat, ny: TGLfloat, 
+    nz: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, 
+    importc: "glReplacementCodeuiColor4fNormal3fVertex3fSUN".}
+proc glReplacementCodeuiColor4fNormal3fVertex3fvSUN*(rc: PGLuint, c: PGLfloat, 
+    n: PGLfloat, v: PGLfloat){.dynlib: dllname, importc: "glReplacementCodeuiColor4fNormal3fVertex3fvSUN".}
+proc glReplacementCodeuiTexCoord2fVertex3fSUN*(rc: TGLuint, s: TGLfloat, 
+    t: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, 
+    importc: "glReplacementCodeuiTexCoord2fVertex3fSUN".}
+proc glReplacementCodeuiTexCoord2fVertex3fvSUN*(rc: PGLuint, tc: PGLfloat, 
+    v: PGLfloat){.dynlib: dllname, 
+                  importc: "glReplacementCodeuiTexCoord2fVertex3fvSUN".}
+proc glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN*(rc: TGLuint, s: TGLfloat, 
+    t: TGLfloat, nx: TGLfloat, ny: TGLfloat, nz: TGLfloat, x: TGLfloat, 
+    y: TGLfloat, z: TGLfloat){.dynlib: dllname, importc: "glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN".}
+proc glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN*(rc: PGLuint, 
+    tc: PGLfloat, n: PGLfloat, v: PGLfloat){.dynlib: dllname, 
+    importc: "glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN".}
+proc glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN*(rc: TGLuint, 
+    s: TGLfloat, t: TGLfloat, r: TGLfloat, g: TGLfloat, b: TGLfloat, 
+    a: TGLfloat, nx: TGLfloat, ny: TGLfloat, nz: TGLfloat, x: TGLfloat, 
+    y: TGLfloat, z: TGLfloat){.dynlib: dllname, importc: "glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN".}
+proc glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN*(rc: PGLuint, 
+    tc: PGLfloat, c: PGLfloat, n: PGLfloat, v: PGLfloat){.dynlib: dllname, 
+    importc: "glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN".}
+  #***** GL_ARB_fragment_program *****//
+const 
+  GL_FRAGMENT_PROGRAM_ARB* = 0x00008804 # GL_PROGRAM_FORMAT_ASCII_ARB  { already defined }
+                                        # GL_PROGRAM_LENGTH_ARB  { already defined }
+                                        # GL_PROGRAM_FORMAT_ARB  { already defined }
+                                        # GL_PROGRAM_BINDING_ARB  { already defined }
+                                        # GL_PROGRAM_INSTRUCTIONS_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_INSTRUCTIONS_ARB  { already defined }
+                                        # GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB  { already defined }
+                                        # GL_PROGRAM_TEMPORARIES_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_TEMPORARIES_ARB  { already defined }
+                                        # GL_PROGRAM_NATIVE_TEMPORARIES_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB  { already defined }
+                                        # GL_PROGRAM_PARAMETERS_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_PARAMETERS_ARB  { already defined }
+                                        # GL_PROGRAM_NATIVE_PARAMETERS_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB  { already defined }
+                                        # GL_PROGRAM_ATTRIBS_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_ATTRIBS_ARB  { already defined }
+                                        # GL_PROGRAM_NATIVE_ATTRIBS_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB  { already defined }
+                                        # GL_MAX_PROGRAM_ENV_PARAMETERS_ARB  { already defined }
+                                        # GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB  { already defined }
+  GL_PROGRAM_ALU_INSTRUCTIONS_ARB* = 0x00008805
+  GL_PROGRAM_TEX_INSTRUCTIONS_ARB* = 0x00008806
+  GL_PROGRAM_TEX_INDIRECTIONS_ARB* = 0x00008807
+  GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB* = 0x00008808
+  GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB* = 0x00008809
+  GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB* = 0x0000880A
+  GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB* = 0x0000880B
+  GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB* = 0x0000880C
+  GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB* = 0x0000880D
+  GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB* = 0x0000880E
+  GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB* = 0x0000880F
+  GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB* = 0x00008810 # GL_PROGRAM_STRING_ARB  { already defined }
+                                                           # 
+                                                           # 
+                                                           # GL_PROGRAM_ERROR_POSITION_ARB  { already defined }
+                                                           # GL_CURRENT_MATRIX_ARB  { already defined }
+                                                           # 
+                                                           # 
+                                                           # GL_TRANSPOSE_CURRENT_MATRIX_ARB  { already defined }
+                                                           # 
+                                                           # 
+                                                           # GL_CURRENT_MATRIX_STACK_DEPTH_ARB  { already defined }
+                                                           # 
+                                                           # 
+                                                           # GL_MAX_PROGRAM_MATRICES_ARB  { already defined }
+                                                           # 
+                                                           # 
+                                                           # GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB  { already defined }
+  GL_MAX_TEXTURE_COORDS_ARB* = 0x00008871
+  GL_MAX_TEXTURE_IMAGE_UNITS_ARB* = 0x00008872 # GL_PROGRAM_ERROR_STRING_ARB  { already defined }
+                                               # GL_MATRIX0_ARB  { already defined }
+                                               # GL_MATRIX1_ARB  { already defined }
+                                               # GL_MATRIX2_ARB  { already defined }
+                                               # GL_MATRIX3_ARB  { already defined }
+                                               # GL_MATRIX4_ARB  { already defined }
+                                               # GL_MATRIX5_ARB  { already defined }
+                                               # GL_MATRIX6_ARB  { already defined }
+                                               # GL_MATRIX7_ARB  { already defined }
+                                               # GL_MATRIX8_ARB  { already defined }
+                                               # GL_MATRIX9_ARB  { already defined }
+                                               # GL_MATRIX10_ARB  { already defined }
+                                               # GL_MATRIX11_ARB  { already defined }
+                                               # GL_MATRIX12_ARB  { already defined }
+                                               # GL_MATRIX13_ARB  { already defined }
+                                               # GL_MATRIX14_ARB  { already defined }
+                                               # GL_MATRIX15_ARB  { already defined }
+                                               # GL_MATRIX16_ARB  { already defined }
+                                               # GL_MATRIX17_ARB  { already defined }
+                                               # GL_MATRIX18_ARB  { already defined }
+                                               # GL_MATRIX19_ARB  { already defined }
+                                               # GL_MATRIX20_ARB  { already defined }
+                                               # GL_MATRIX21_ARB  { already defined }
+                                               # GL_MATRIX22_ARB  { already defined }
+                                               # GL_MATRIX23_ARB  { already defined }
+                                               # GL_MATRIX24_ARB  { already defined }
+                                               # GL_MATRIX25_ARB  { already defined }
+                                               # GL_MATRIX26_ARB  { already defined }
+                                               # GL_MATRIX27_ARB  { already defined }
+                                               # GL_MATRIX28_ARB  { already defined }
+                                               # GL_MATRIX29_ARB  { already defined }
+                                               # GL_MATRIX30_ARB  { already defined }
+                                               # GL_MATRIX31_ARB  { already defined }
+                                               # glProgramStringARB  { already defined }
+                                               # glBindProgramARB  { already defined }
+                                               # glDeleteProgramsARB  { already defined }
+                                               # glGenProgramsARB  { already defined }
+                                               # glProgramEnvParameter4dARB  { already defined }
+                                               # glProgramEnvParameter4dvARB  { already defined }
+                                               # glProgramEnvParameter4fARB  { already defined }
+                                               # glProgramEnvParameter4fvARB  { already defined }
+                                               # glProgramLocalParameter4dARB  { already defined }
+                                               # glProgramLocalParameter4dvARB  { already defined }
+                                               # glProgramLocalParameter4fARB  { already defined }
+                                               # glProgramLocalParameter4fvARB  { already defined }
+                                               # glGetProgramEnvParameterdvARB  { already defined }
+                                               # glGetProgramEnvParameterfvARB  { already defined }
+                                               # glGetProgramLocalParameterdvARB  { already defined }
+                                               # glGetProgramLocalParameterfvARB  { already defined }
+                                               # glGetProgramivARB  { already defined }
+                                               # glGetProgramStringARB  { already defined }
+                                               # glIsProgramARB  { already defined }
+  #***** GL_ATI_text_fragment_shader *****
+
+const 
+  GL_TEXT_FRAGMENT_SHADER_ATI* = 0x00008200 #***** GL_ARB_vertex_buffer_object *****
+
+const 
+  GL_BUFFER_SIZE_ARB* = 0x00008764
+  GL_BUFFER_USAGE_ARB* = 0x00008765
+  GL_ARRAY_BUFFER_ARB* = 0x00008892
+  GL_ELEMENT_ARRAY_BUFFER_ARB* = 0x00008893
+  GL_ARRAY_BUFFER_BINDING_ARB* = 0x00008894
+  GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB* = 0x00008895
+  GL_VERTEX_ARRAY_BUFFER_BINDING_ARB* = 0x00008896
+  GL_NORMAL_ARRAY_BUFFER_BINDING_ARB* = 0x00008897
+  GL_COLOR_ARRAY_BUFFER_BINDING_ARB* = 0x00008898
+  GL_INDEX_ARRAY_BUFFER_BINDING_ARB* = 0x00008899
+  GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB* = 0x0000889A
+  GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB* = 0x0000889B
+  GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB* = 0x0000889C
+  GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB* = 0x0000889D
+  GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB* = 0x0000889E
+  GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB* = 0x0000889F
+  GL_READ_ONLY_ARB* = 0x000088B8
+  GL_WRITE_ONLY_ARB* = 0x000088B9
+  GL_READ_WRITE_ARB* = 0x000088BA
+  GL_BUFFER_ACCESS_ARB* = 0x000088BB
+  GL_BUFFER_MAPPED_ARB* = 0x000088BC
+  GL_BUFFER_MAP_POINTER_ARB* = 0x000088BD
+  GL_STREAM_DRAW_ARB* = 0x000088E0
+  GL_STREAM_READ_ARB* = 0x000088E1
+  GL_STREAM_COPY_ARB* = 0x000088E2
+  GL_STATIC_DRAW_ARB* = 0x000088E4
+  GL_STATIC_READ_ARB* = 0x000088E5
+  GL_STATIC_COPY_ARB* = 0x000088E6
+  GL_DYNAMIC_DRAW_ARB* = 0x000088E8
+  GL_DYNAMIC_READ_ARB* = 0x000088E9
+  GL_DYNAMIC_COPY_ARB* = 0x000088EA
+
+proc glBindBufferARB*(target: TGLenum, buffer: TGLuint){.dynlib: dllname, 
+    importc: "glBindBufferARB".}
+proc glDeleteBuffersARB*(n: TGLsizei, buffers: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteBuffersARB".}
+proc glGenBuffersARB*(n: TGLsizei, buffers: PGLuint){.dynlib: dllname, 
+    importc: "glGenBuffersARB".}
+proc glIsBufferARB*(buffer: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsBufferARB".}
+proc glBufferDataARB*(target: TGLenum, size: TGLsizei, data: PGLvoid, 
+                      usage: TGLenum){.dynlib: dllname, 
+                                       importc: "glBufferDataARB".}
+proc glBufferSubDataARB*(target: TGLenum, offset: TGLint, size: TGLsizei, 
+                         data: PGLvoid){.dynlib: dllname, 
+    importc: "glBufferSubDataARB".}
+proc glGetBufferSubDataARB*(target: TGLenum, offset: TGLint, size: TGLsizei, 
+                            data: PGLvoid){.dynlib: dllname, 
+    importc: "glGetBufferSubDataARB".}
+proc glMapBufferARB*(target: TGLenum, access: TGLenum): PGLvoid{.
+    dynlib: dllname, importc: "glMapBufferARB".}
+proc glUnmapBufferARB*(target: TGLenum): TGLboolean{.dynlib: dllname, 
+    importc: "glUnmapBufferARB".}
+proc glGetBufferParameterivARB*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetBufferParameterivARB".}
+proc glGetBufferPointervARB*(target: TGLenum, pname: TGLenum, params: PPGLvoid){.
+    dynlib: dllname, importc: "glGetBufferPointervARB".}
+  #***** GL_APPLE_client_storage *****//
+const 
+  GL_UNPACK_CLIENT_STORAGE_APPLE* = 0x000085B2
+  #***** GL_APPLE_element_array *****//
+
+const 
+  GL_ELEMENT_ARRAY_APPLE* = 0x00008768
+  GL_ELEMENT_ARRAY_TYPE_APPLE* = 0x00008769
+  GL_ELEMENT_ARRAY_POINTER_APPLE* = 0x0000876A
+
+proc glElementPointerAPPLE*(thetype: TGLenum, pointer: PGLvoid){.
+    dynlib: dllname, importc: "glElementPointerAPPLE".}
+proc glDrawElementArrayAPPLE*(mode: TGLenum, first: TGLint, count: TGLsizei){.
+    dynlib: dllname, importc: "glDrawElementArrayAPPLE".}
+proc glDrawRangeElementArrayAPPLE*(mode: TGLenum, start: TGLuint, 
+                                   theend: TGLuint, first: TGLint, 
+                                   count: TGLsizei){.dynlib: dllname, 
+    importc: "glDrawRangeElementArrayAPPLE".}
+proc glMultiDrawElementArrayAPPLE*(mode: TGLenum, first: PGLint, 
+                                   count: PGLsizei, primcount: TGLsizei){.
+    dynlib: dllname, importc: "glMultiDrawElementArrayAPPLE".}
+proc glMultiDrawRangeElementArrayAPPLE*(mode: TGLenum, start: TGLuint, 
+                                        theend: TGLuint, first: PGLint, 
+                                        count: PGLsizei, primcount: TGLsizei){.
+    dynlib: dllname, importc: "glMultiDrawRangeElementArrayAPPLE".}
+  #***** GL_APPLE_fence *****//
+const 
+  GL_DRAW_PIXELS_APPLE* = 0x00008A0A
+  GL_FENCE_APPLE* = 0x00008A0B
+
+proc glGenFencesAPPLE*(n: TGLsizei, fences: PGLuint){.dynlib: dllname, 
+    importc: "glGenFencesAPPLE".}
+proc glDeleteFencesAPPLE*(n: TGLsizei, fences: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteFencesAPPLE".}
+proc glSetFenceAPPLE*(fence: TGLuint){.dynlib: dllname, 
+                                       importc: "glSetFenceAPPLE".}
+proc glIsFenceAPPLE*(fence: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsFenceAPPLE".}
+proc glTestFenceAPPLE*(fence: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glTestFenceAPPLE".}
+proc glFinishFenceAPPLE*(fence: TGLuint){.dynlib: dllname, 
+    importc: "glFinishFenceAPPLE".}
+proc glTestObjectAPPLE*(theobject: TGLenum, name: TGLuint): TGLboolean{.
+    dynlib: dllname, importc: "glTestObjectAPPLE".}
+proc glFinishObjectAPPLE*(theobject: TGLenum, name: TGLint){.dynlib: dllname, 
+    importc: "glFinishObjectAPPLE".}
+  #***** GL_APPLE_vertex_array_object *****//
+const 
+  GL_VERTEX_ARRAY_BINDING_APPLE* = 0x000085B5
+
+proc glBindVertexArrayAPPLE*(thearray: TGLuint){.dynlib: dllname, 
+    importc: "glBindVertexArrayAPPLE".}
+proc glDeleteVertexArraysAPPLE*(n: TGLsizei, arrays: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteVertexArraysAPPLE".}
+proc glGenVertexArraysAPPLE*(n: TGLsizei, arrays: PGLuint){.dynlib: dllname, 
+    importc: "glGenVertexArraysAPPLE".}
+proc glIsVertexArrayAPPLE*(thearray: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsVertexArrayAPPLE".}
+  #***** GL_APPLE_vertex_array_range *****//
+const 
+  constGL_VERTEX_ARRAY_RANGE_APPLE* = 0x0000851D
+  GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE* = 0x0000851E
+  GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE* = 0x00008520
+  GL_VERTEX_ARRAY_RANGE_POINTER_APPLE* = 0x00008521
+  GL_VERTEX_ARRAY_STORAGE_HINT_APPLE* = 0x0000851F
+  GL_STORAGE_CACHED_APPLE* = 0x000085BE
+  GL_STORAGE_SHARED_APPLE* = 0x000085BF
+
+proc glVertexArrayRangeAPPLE*(len: TGLsizei, pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glVertexArrayRangeAPPLE".}
+proc glFlushVertexArrayRangeAPPLE*(len: TGLsizei, pointer: PGLvoid){.
+    dynlib: dllname, importc: "glFlushVertexArrayRangeAPPLE".}
+proc glVertexArrayParameteriAPPLE*(pname: TGLenum, param: TGLint){.
+    dynlib: dllname, importc: "glVertexArrayParameteriAPPLE".}
+  #***** GL_ARB_matrix_palette *****//
+const 
+  GL_MATRIX_PALETTE_ARB* = 0x00008840
+  GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB* = 0x00008841
+  GL_MAX_PALETTE_MATRICES_ARB* = 0x00008842
+  constGL_CURRENT_PALETTE_MATRIX_ARB* = 0x00008843
+  GL_MATRIX_INDEX_ARRAY_ARB* = 0x00008844
+  GL_CURRENT_MATRIX_INDEX_ARB* = 0x00008845
+  GL_MATRIX_INDEX_ARRAY_SIZE_ARB* = 0x00008846
+  GL_MATRIX_INDEX_ARRAY_TYPE_ARB* = 0x00008847
+  GL_MATRIX_INDEX_ARRAY_STRIDE_ARB* = 0x00008848
+  GL_MATRIX_INDEX_ARRAY_POINTER_ARB* = 0x00008849
+
+proc glCurrentPaletteMatrixARB*(index: TGLint){.dynlib: dllname, 
+    importc: "glCurrentPaletteMatrixARB".}
+proc glMatrixIndexubvARB*(size: TGLint, indices: PGLubyte){.dynlib: dllname, 
+    importc: "glMatrixIndexubvARB".}
+proc glMatrixIndexusvARB*(size: TGLint, indices: PGLushort){.dynlib: dllname, 
+    importc: "glMatrixIndexusvARB".}
+proc glMatrixIndexuivARB*(size: TGLint, indices: PGLuint){.dynlib: dllname, 
+    importc: "glMatrixIndexuivARB".}
+proc glMatrixIndexPointerARB*(size: TGLint, thetype: TGLenum, stride: TGLsizei, 
+                              pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glMatrixIndexPointerARB".}
+  #***** GL_NV_element_array *****//
+const 
+  GL_ELEMENT_ARRAY_TYPE_NV* = 0x00008769
+  GL_ELEMENT_ARRAY_POINTER_NV* = 0x0000876A
+
+proc glElementPointerNV*(thetype: TGLenum, pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glElementPointerNV".}
+proc glDrawElementArrayNV*(mode: TGLenum, first: TGLint, count: TGLsizei){.
+    dynlib: dllname, importc: "glDrawElementArrayNV".}
+proc glDrawRangeElementArrayNV*(mode: TGLenum, start: TGLuint, theend: TGLuint, 
+                                first: TGLint, count: TGLsizei){.
+    dynlib: dllname, importc: "glDrawRangeElementArrayNV".}
+proc glMultiDrawElementArrayNV*(mode: TGLenum, first: PGLint, count: PGLsizei, 
+                                primcount: TGLsizei){.dynlib: dllname, 
+    importc: "glMultiDrawElementArrayNV".}
+proc glMultiDrawRangeElementArrayNV*(mode: TGLenum, start: TGLuint, 
+                                     theend: TGLuint, first: PGLint, 
+                                     count: PGLsizei, primcount: TGLsizei){.
+    dynlib: dllname, importc: "glMultiDrawRangeElementArrayNV".}
+  #***** GL_NV_float_buffer *****//
+const 
+  GL_FLOAT_R_NV* = 0x00008880
+  GL_FLOAT_RG_NV* = 0x00008881
+  GL_FLOAT_RGB_NV* = 0x00008882
+  GL_FLOAT_RGBA_NV* = 0x00008883
+  GL_FLOAT_R16_NV* = 0x00008884
+  GL_FLOAT_R32_NV* = 0x00008885
+  GL_FLOAT_RG16_NV* = 0x00008886
+  GL_FLOAT_RG32_NV* = 0x00008887
+  GL_FLOAT_RGB16_NV* = 0x00008888
+  GL_FLOAT_RGB32_NV* = 0x00008889
+  GL_FLOAT_RGBA16_NV* = 0x0000888A
+  GL_FLOAT_RGBA32_NV* = 0x0000888B
+  GL_TEXTURE_FLOAT_COMPONENTS_NV* = 0x0000888C
+  GL_FLOAT_CLEAR_COLOR_VALUE_NV* = 0x0000888D
+  GL_FLOAT_RGBA_MODE_NV* = 0x0000888E
+  #***** GL_NV_fragment_program *****//
+
+const 
+  GL_FRAGMENT_PROGRAM_NV* = 0x00008870
+  GL_MAX_TEXTURE_COORDS_NV* = 0x00008871
+  GL_MAX_TEXTURE_IMAGE_UNITS_NV* = 0x00008872
+  GL_FRAGMENT_PROGRAM_BINDING_NV* = 0x00008873
+  GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV* = 0x00008868
+  GL_PROGRAM_ERROR_STRING_NV* = 0x00008874
+
+proc glProgramNamedParameter4fNV*(id: TGLuint, length: TGLsizei, name: PGLubyte, 
+                                  x: TGLfloat, y: TGLfloat, z: TGLfloat, 
+                                  w: TGLfloat){.dynlib: dllname, 
+    importc: "glProgramNamedParameter4fNV".}
+proc glProgramNamedParameter4dNV*(id: TGLuint, length: TGLsizei, name: PGLubyte, 
+                                  x: TGLdouble, y: TGLdouble, z: TGLdouble, 
+                                  w: TGLdouble){.dynlib: dllname, 
+    importc: "glProgramNamedParameter4dNV".}
+proc glGetProgramNamedParameterfvNV*(id: TGLuint, length: TGLsizei, 
+                                     name: PGLubyte, params: PGLfloat){.
+    dynlib: dllname, importc: "glGetProgramNamedParameterfvNV".}
+proc glGetProgramNamedParameterdvNV*(id: TGLuint, length: TGLsizei, 
+                                     name: PGLubyte, params: PGLdouble){.
+    dynlib: dllname, importc: "glGetProgramNamedParameterdvNV".}
+  # glProgramLocalParameter4dARB  { already defined }
+  # glProgramLocalParameter4dvARB  { already defined }
+  # glProgramLocalParameter4fARB  { already defined }
+  # glProgramLocalParameter4fvARB  { already defined }
+  # glGetProgramLocalParameterdvARB  { already defined }
+  # glGetProgramLocalParameterfvARB  { already defined }
+  #***** GL_NV_primitive_restart *****//
+const 
+  constGL_PRIMITIVE_RESTART_NV* = 0x00008558
+  constGL_PRIMITIVE_RESTART_INDEX_NV* = 0x00008559
+
+proc glPrimitiveRestartNV*(){.dynlib: dllname, importc: "glPrimitiveRestartNV".}
+proc glPrimitiveRestartIndexNV*(index: TGLuint){.dynlib: dllname, 
+    importc: "glPrimitiveRestartIndexNV".}
+  #***** GL_NV_vertex_program2 *****//
+  #***** GL_NV_pixel_data_range *****//
+const 
+  GL_WRITE_PIXEL_DATA_RANGE_NV* = 0x00008878
+  GL_READ_PIXEL_DATA_RANGE_NV* = 0x00008879
+  GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV* = 0x0000887A
+  GL_READ_PIXEL_DATA_RANGE_LENGTH_NV* = 0x0000887B
+  GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV* = 0x0000887C
+  GL_READ_PIXEL_DATA_RANGE_POINTER_NV* = 0x0000887D
+
+proc glPixelDataRangeNV*(target: TGLenum, len: TGLsizei, pointer: PGLvoid){.
+    dynlib: dllname, importc: "glPixelDataRangeNV".}
+proc glFlushPixelDataRangeNV*(target: TGLenum){.dynlib: dllname, 
+    importc: "glFlushPixelDataRangeNV".}
+  # wglAllocateMemoryNV  { already defined }
+  # wglFreeMemoryNV  { already defined }
+  #***** GL_EXT_texture_rectangle *****//
+const 
+  GL_TEXTURE_RECTANGLE_EXT* = 0x000084F5
+  GL_TEXTURE_BINDING_RECTANGLE_EXT* = 0x000084F6
+  GL_PROXY_TEXTURE_RECTANGLE_EXT* = 0x000084F7
+  GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT* = 0x000084F8
+  #***** GL_S3_s3tc *****//
+
+const 
+  GL_RGB_S3TC* = 0x000083A0
+  GL_RGB4_S3TC* = 0x000083A1
+  GL_RGBA_S3TC* = 0x000083A2
+  GL_RGBA4_S3TC* = 0x000083A3
+  #***** GL_ATI_draw_buffers *****//
+
+const 
+  GL_MAX_DRAW_BUFFERS_ATI* = 0x00008824
+  GL_DRAW_BUFFER0_ATI* = 0x00008825
+  GL_DRAW_BUFFER1_ATI* = 0x00008826
+  GL_DRAW_BUFFER2_ATI* = 0x00008827
+  GL_DRAW_BUFFER3_ATI* = 0x00008828
+  GL_DRAW_BUFFER4_ATI* = 0x00008829
+  GL_DRAW_BUFFER5_ATI* = 0x0000882A
+  GL_DRAW_BUFFER6_ATI* = 0x0000882B
+  GL_DRAW_BUFFER7_ATI* = 0x0000882C
+  GL_DRAW_BUFFER8_ATI* = 0x0000882D
+  GL_DRAW_BUFFER9_ATI* = 0x0000882E
+  GL_DRAW_BUFFER10_ATI* = 0x0000882F
+  GL_DRAW_BUFFER11_ATI* = 0x00008830
+  GL_DRAW_BUFFER12_ATI* = 0x00008831
+  GL_DRAW_BUFFER13_ATI* = 0x00008832
+  GL_DRAW_BUFFER14_ATI* = 0x00008833
+  GL_DRAW_BUFFER15_ATI* = 0x00008834
+
+proc glDrawBuffersATI*(n: TGLsizei, bufs: PGLenum){.dynlib: dllname, 
+    importc: "glDrawBuffersATI".}
+  #***** GL_ATI_texture_env_combine3 *****//
+const 
+  GL_MODULATE_ADD_ATI* = 0x00008744
+  GL_MODULATE_SIGNED_ADD_ATI* = 0x00008745
+  GL_MODULATE_SUBTRACT_ATI* = 0x00008746
+  #***** GL_ATI_texture_float *****//
+
+const 
+  GL_RGBA_FLOAT32_ATI* = 0x00008814
+  GL_RGB_FLOAT32_ATI* = 0x00008815
+  GL_ALPHA_FLOAT32_ATI* = 0x00008816
+  GL_INTENSITY_FLOAT32_ATI* = 0x00008817
+  GL_LUMINANCE_FLOAT32_ATI* = 0x00008818
+  GL_LUMINANCE_ALPHA_FLOAT32_ATI* = 0x00008819
+  GL_RGBA_FLOAT16_ATI* = 0x0000881A
+  GL_RGB_FLOAT16_ATI* = 0x0000881B
+  GL_ALPHA_FLOAT16_ATI* = 0x0000881C
+  GL_INTENSITY_FLOAT16_ATI* = 0x0000881D
+  GL_LUMINANCE_FLOAT16_ATI* = 0x0000881E
+  GL_LUMINANCE_ALPHA_FLOAT16_ATI* = 0x0000881F
+  #***** GL_NV_texture_expand_normal *****//
+
+const 
+  GL_TEXTURE_UNSIGNED_REMAP_MODE_NV* = 0x0000888F
+  #***** GL_NV_half_float *****//
+
+const 
+  GL_HALF_FLOAT_NV* = 0x0000140B
+
+proc glVertex2hNV*(x: TGLushort, y: TGLushort){.dynlib: dllname, 
+    importc: "glVertex2hNV".}
+proc glVertex2hvNV*(v: PGLushort){.dynlib: dllname, importc: "glVertex2hvNV".}
+proc glVertex3hNV*(x: TGLushort, y: TGLushort, z: TGLushort){.dynlib: dllname, 
+    importc: "glVertex3hNV".}
+proc glVertex3hvNV*(v: PGLushort){.dynlib: dllname, importc: "glVertex3hvNV".}
+proc glVertex4hNV*(x: TGLushort, y: TGLushort, z: TGLushort, w: TGLushort){.
+    dynlib: dllname, importc: "glVertex4hNV".}
+proc glVertex4hvNV*(v: PGLushort){.dynlib: dllname, importc: "glVertex4hvNV".}
+proc glNormal3hNV*(nx: TGLushort, ny: TGLushort, nz: TGLushort){.
+    dynlib: dllname, importc: "glNormal3hNV".}
+proc glNormal3hvNV*(v: PGLushort){.dynlib: dllname, importc: "glNormal3hvNV".}
+proc glColor3hNV*(red: TGLushort, green: TGLushort, blue: TGLushort){.
+    dynlib: dllname, importc: "glColor3hNV".}
+proc glColor3hvNV*(v: PGLushort){.dynlib: dllname, importc: "glColor3hvNV".}
+proc glColor4hNV*(red: TGLushort, green: TGLushort, blue: TGLushort, 
+                  alpha: TGLushort){.dynlib: dllname, importc: "glColor4hNV".}
+proc glColor4hvNV*(v: PGLushort){.dynlib: dllname, importc: "glColor4hvNV".}
+proc glTexCoord1hNV*(s: TGLushort){.dynlib: dllname, importc: "glTexCoord1hNV".}
+proc glTexCoord1hvNV*(v: PGLushort){.dynlib: dllname, importc: "glTexCoord1hvNV".}
+proc glTexCoord2hNV*(s: TGLushort, t: TGLushort){.dynlib: dllname, 
+    importc: "glTexCoord2hNV".}
+proc glTexCoord2hvNV*(v: PGLushort){.dynlib: dllname, importc: "glTexCoord2hvNV".}
+proc glTexCoord3hNV*(s: TGLushort, t: TGLushort, r: TGLushort){.dynlib: dllname, 
+    importc: "glTexCoord3hNV".}
+proc glTexCoord3hvNV*(v: PGLushort){.dynlib: dllname, importc: "glTexCoord3hvNV".}
+proc glTexCoord4hNV*(s: TGLushort, t: TGLushort, r: TGLushort, q: TGLushort){.
+    dynlib: dllname, importc: "glTexCoord4hNV".}
+proc glTexCoord4hvNV*(v: PGLushort){.dynlib: dllname, importc: "glTexCoord4hvNV".}
+proc glMultiTexCoord1hNV*(target: TGLenum, s: TGLushort){.dynlib: dllname, 
+    importc: "glMultiTexCoord1hNV".}
+proc glMultiTexCoord1hvNV*(target: TGLenum, v: PGLushort){.dynlib: dllname, 
+    importc: "glMultiTexCoord1hvNV".}
+proc glMultiTexCoord2hNV*(target: TGLenum, s: TGLushort, t: TGLushort){.
+    dynlib: dllname, importc: "glMultiTexCoord2hNV".}
+proc glMultiTexCoord2hvNV*(target: TGLenum, v: PGLushort){.dynlib: dllname, 
+    importc: "glMultiTexCoord2hvNV".}
+proc glMultiTexCoord3hNV*(target: TGLenum, s: TGLushort, t: TGLushort, 
+                          r: TGLushort){.dynlib: dllname, 
+    importc: "glMultiTexCoord3hNV".}
+proc glMultiTexCoord3hvNV*(target: TGLenum, v: PGLushort){.dynlib: dllname, 
+    importc: "glMultiTexCoord3hvNV".}
+proc glMultiTexCoord4hNV*(target: TGLenum, s: TGLushort, t: TGLushort, 
+                          r: TGLushort, q: TGLushort){.dynlib: dllname, 
+    importc: "glMultiTexCoord4hNV".}
+proc glMultiTexCoord4hvNV*(target: TGLenum, v: PGLushort){.dynlib: dllname, 
+    importc: "glMultiTexCoord4hvNV".}
+proc glFogCoordhNV*(fog: TGLushort){.dynlib: dllname, importc: "glFogCoordhNV".}
+proc glFogCoordhvNV*(fog: PGLushort){.dynlib: dllname, importc: "glFogCoordhvNV".}
+proc glSecondaryColor3hNV*(red: TGLushort, green: TGLushort, blue: TGLushort){.
+    dynlib: dllname, importc: "glSecondaryColor3hNV".}
+proc glSecondaryColor3hvNV*(v: PGLushort){.dynlib: dllname, 
+    importc: "glSecondaryColor3hvNV".}
+proc glVertexWeighthNV*(weight: TGLushort){.dynlib: dllname, 
+    importc: "glVertexWeighthNV".}
+proc glVertexWeighthvNV*(weight: PGLushort){.dynlib: dllname, 
+    importc: "glVertexWeighthvNV".}
+proc glVertexAttrib1hNV*(index: TGLuint, x: TGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib1hNV".}
+proc glVertexAttrib1hvNV*(index: TGLuint, v: PGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib1hvNV".}
+proc glVertexAttrib2hNV*(index: TGLuint, x: TGLushort, y: TGLushort){.
+    dynlib: dllname, importc: "glVertexAttrib2hNV".}
+proc glVertexAttrib2hvNV*(index: TGLuint, v: PGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib2hvNV".}
+proc glVertexAttrib3hNV*(index: TGLuint, x: TGLushort, y: TGLushort, 
+                         z: TGLushort){.dynlib: dllname, 
+                                        importc: "glVertexAttrib3hNV".}
+proc glVertexAttrib3hvNV*(index: TGLuint, v: PGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib3hvNV".}
+proc glVertexAttrib4hNV*(index: TGLuint, x: TGLushort, y: TGLushort, 
+                         z: TGLushort, w: TGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib4hNV".}
+proc glVertexAttrib4hvNV*(index: TGLuint, v: PGLushort){.dynlib: dllname, 
+    importc: "glVertexAttrib4hvNV".}
+proc glVertexAttribs1hvNV*(index: TGLuint, n: TGLsizei, v: PGLushort){.
+    dynlib: dllname, importc: "glVertexAttribs1hvNV".}
+proc glVertexAttribs2hvNV*(index: TGLuint, n: TGLsizei, v: PGLushort){.
+    dynlib: dllname, importc: "glVertexAttribs2hvNV".}
+proc glVertexAttribs3hvNV*(index: TGLuint, n: TGLsizei, v: PGLushort){.
+    dynlib: dllname, importc: "glVertexAttribs3hvNV".}
+proc glVertexAttribs4hvNV*(index: TGLuint, n: TGLsizei, v: PGLushort){.
+    dynlib: dllname, importc: "glVertexAttribs4hvNV".}
+  #***** GL_ATI_map_object_buffer *****//
+proc glMapObjectBufferATI*(buffer: TGLuint): PGLvoid{.dynlib: dllname, 
+    importc: "glMapObjectBufferATI".}
+proc glUnmapObjectBufferATI*(buffer: TGLuint){.dynlib: dllname, 
+    importc: "glUnmapObjectBufferATI".}
+  #***** GL_ATI_separate_stencil *****//
+const 
+  GL_KEEP* = 0x00001E00
+  GL_ZERO* = 0x00000000
+  GL_REPLACE* = 0x00001E01
+  GL_INCR* = 0x00001E02
+  GL_DECR* = 0x00001E03
+  GL_INVERT* = 0x0000150A
+  GL_NEVER* = 0x00000200
+  GL_LESS* = 0x00000201
+  GL_LEQUAL* = 0x00000203
+  GL_GREATER* = 0x00000204
+  GL_GEQUAL* = 0x00000206
+  GL_EQUAL* = 0x00000202
+  GL_NOTEQUAL* = 0x00000205
+  GL_ALWAYS* = 0x00000207
+  GL_FRONT* = 0x00000404
+  GL_BACK* = 0x00000405
+  GL_FRONT_AND_BACK* = 0x00000408
+  GL_STENCIL_BACK_FUNC_ATI* = 0x00008800
+  GL_STENCIL_BACK_FAIL_ATI* = 0x00008801
+  GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI* = 0x00008802
+  GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI* = 0x00008803
+
+proc glStencilOpSeparateATI*(face: TGLenum, sfail: TGLenum, dpfail: TGLenum, 
+                             dppass: TGLenum){.dynlib: dllname, 
+    importc: "glStencilOpSeparateATI".}
+proc glStencilFuncSeparateATI*(frontfunc: TGLenum, backfunc: TGLenum, 
+                               theRef: TGLint, mask: TGLuint){.dynlib: dllname, 
+    importc: "glStencilFuncSeparateATI".}
+  #***** GL_ATI_vertex_attrib_array_object *****//
+proc glVertexAttribArrayObjectATI*(index: TGLuint, size: TGLint, 
+                                   thetype: TGLenum, normalized: TGLboolean, 
+                                   stride: TGLsizei, buffer: TGLuint, 
+                                   offset: TGLuint){.dynlib: dllname, 
+    importc: "glVertexAttribArrayObjectATI".}
+proc glGetVertexAttribArrayObjectfvATI*(index: TGLuint, pname: TGLenum, 
+                                        params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetVertexAttribArrayObjectfvATI".}
+proc glGetVertexAttribArrayObjectivATI*(index: TGLuint, pname: TGLenum, 
+                                        params: PGLint){.dynlib: dllname, 
+    importc: "glGetVertexAttribArrayObjectivATI".}
+  #***** GL_ARB_occlusion_query *****//
+const 
+  GL_SAMPLES_PASSED_ARB* = 0x00008914
+  GL_QUERY_COUNTER_BITS_ARB* = 0x00008864
+  GL_CURRENT_QUERY_ARB* = 0x00008865
+  GL_QUERY_RESULT_ARB* = 0x00008866
+  GL_QUERY_RESULT_AVAILABLE_ARB* = 0x00008867
+
+proc glGenQueriesARB*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, 
+    importc: "glGenQueriesARB".}
+proc glDeleteQueriesARB*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteQueriesARB".}
+proc glIsQueryARB*(id: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsQueryARB".}
+proc glBeginQueryARB*(target: TGLenum, id: TGLuint){.dynlib: dllname, 
+    importc: "glBeginQueryARB".}
+proc glEndQueryARB*(target: TGLenum){.dynlib: dllname, importc: "glEndQueryARB".}
+proc glGetQueryivARB*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetQueryivARB".}
+proc glGetQueryObjectivARB*(id: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetQueryObjectivARB".}
+proc glGetQueryObjectuivARB*(id: TGLuint, pname: TGLenum, params: PGLuint){.
+    dynlib: dllname, importc: "glGetQueryObjectuivARB".}
+  #***** GL_ARB_shader_objects *****//
+const 
+  GL_PROGRAM_OBJECT_ARB* = 0x00008B40
+  GL_OBJECT_TYPE_ARB* = 0x00008B4E
+  GL_OBJECT_SUBTYPE_ARB* = 0x00008B4F
+  GL_OBJECT_DELETE_STATUS_ARB* = 0x00008B80
+  GL_OBJECT_COMPILE_STATUS_ARB* = 0x00008B81
+  GL_OBJECT_LINK_STATUS_ARB* = 0x00008B82
+  GL_OBJECT_VALIDATE_STATUS_ARB* = 0x00008B83
+  GL_OBJECT_INFO_LOG_LENGTH_ARB* = 0x00008B84
+  GL_OBJECT_ATTACHED_OBJECTS_ARB* = 0x00008B85
+  GL_OBJECT_ACTIVE_UNIFORMS_ARB* = 0x00008B86
+  GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB* = 0x00008B87
+  GL_OBJECT_SHADER_SOURCE_LENGTH_ARB* = 0x00008B88
+  GL_SHADER_OBJECT_ARB* = 0x00008B48
+  GL_FLOAT* = 0x00001406
+  GL_FLOAT_VEC2_ARB* = 0x00008B50
+  GL_FLOAT_VEC3_ARB* = 0x00008B51
+  GL_FLOAT_VEC4_ARB* = 0x00008B52
+  GL_INT* = 0x00001404
+  GL_INT_VEC2_ARB* = 0x00008B53
+  GL_INT_VEC3_ARB* = 0x00008B54
+  GL_INT_VEC4_ARB* = 0x00008B55
+  GL_BOOL_ARB* = 0x00008B56
+  GL_BOOL_VEC2_ARB* = 0x00008B57
+  GL_BOOL_VEC3_ARB* = 0x00008B58
+  GL_BOOL_VEC4_ARB* = 0x00008B59
+  GL_FLOAT_MAT2_ARB* = 0x00008B5A
+  GL_FLOAT_MAT3_ARB* = 0x00008B5B
+  GL_FLOAT_MAT4_ARB* = 0x00008B5C
+
+proc glDeleteObjectARB*(obj: GLhandleARB){.dynlib: dllname, 
+    importc: "glDeleteObjectARB".}
+proc glGetHandleARB*(pname: TGLenum): GLhandleARB{.dynlib: dllname, 
+    importc: "glGetHandleARB".}
+proc glDetachObjectARB*(containerObj: GLhandleARB, attachedObj: GLhandleARB){.
+    dynlib: dllname, importc: "glDetachObjectARB".}
+proc glCreateShaderObjectARB*(shaderType: TGLenum): GLhandleARB{.
+    dynlib: dllname, importc: "glCreateShaderObjectARB".}
+proc glShaderSourceARB*(shaderObj: GLhandleARB, count: TGLsizei, str: PGLvoid, 
+                        len: PGLint){.dynlib: dllname, 
+                                      importc: "glShaderSourceARB".}
+proc glCompileShaderARB*(shaderObj: GLhandleARB){.dynlib: dllname, 
+    importc: "glCompileShaderARB".}
+proc glCreateProgramObjectARB*(): GLhandleARB{.dynlib: dllname, 
+    importc: "glCreateProgramObjectARB".}
+proc glAttachObjectARB*(containerObj: GLhandleARB, obj: GLhandleARB){.
+    dynlib: dllname, importc: "glAttachObjectARB".}
+proc glLinkProgramARB*(programObj: GLhandleARB){.dynlib: dllname, 
+    importc: "glLinkProgramARB".}
+proc glUseProgramObjectARB*(programObj: GLhandleARB){.dynlib: dllname, 
+    importc: "glUseProgramObjectARB".}
+proc glValidateProgramARB*(programObj: GLhandleARB){.dynlib: dllname, 
+    importc: "glValidateProgramARB".}
+proc glUniform1fARB*(location: TGLint, v0: TGLfloat){.dynlib: dllname, 
+    importc: "glUniform1fARB".}
+proc glUniform2fARB*(location: TGLint, v0: TGLfloat, v1: TGLfloat){.
+    dynlib: dllname, importc: "glUniform2fARB".}
+proc glUniform3fARB*(location: TGLint, v0: TGLfloat, v1: TGLfloat, v2: TGLfloat){.
+    dynlib: dllname, importc: "glUniform3fARB".}
+proc glUniform4fARB*(location: TGLint, v0: TGLfloat, v1: TGLfloat, v2: TGLfloat, 
+                     v3: TGLfloat){.dynlib: dllname, importc: "glUniform4fARB".}
+proc glUniform1iARB*(location: TGLint, v0: TGLint){.dynlib: dllname, 
+    importc: "glUniform1iARB".}
+proc glUniform2iARB*(location: TGLint, v0: TGLint, v1: TGLint){.dynlib: dllname, 
+    importc: "glUniform2iARB".}
+proc glUniform3iARB*(location: TGLint, v0: TGLint, v1: TGLint, v2: TGLint){.
+    dynlib: dllname, importc: "glUniform3iARB".}
+proc glUniform4iARB*(location: TGLint, v0: TGLint, v1: TGLint, v2: TGLint, 
+                     v3: TGLint){.dynlib: dllname, importc: "glUniform4iARB".}
+proc glUniform1fvARB*(location: TGLint, count: TGLsizei, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniform1fvARB".}
+proc glUniform2fvARB*(location: TGLint, count: TGLsizei, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniform2fvARB".}
+proc glUniform3fvARB*(location: TGLint, count: TGLsizei, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniform3fvARB".}
+proc glUniform4fvARB*(location: TGLint, count: TGLsizei, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniform4fvARB".}
+proc glUniform1ivARB*(location: TGLint, count: TGLsizei, value: PGLint){.
+    dynlib: dllname, importc: "glUniform1ivARB".}
+proc glUniform2ivARB*(location: TGLint, count: TGLsizei, value: PGLint){.
+    dynlib: dllname, importc: "glUniform2ivARB".}
+proc glUniform3ivARB*(location: TGLint, count: TGLsizei, value: PGLint){.
+    dynlib: dllname, importc: "glUniform3ivARB".}
+proc glUniform4ivARB*(location: TGLint, count: TGLsizei, value: PGLint){.
+    dynlib: dllname, importc: "glUniform4ivARB".}
+proc glUniformMatrix2fvARB*(location: TGLint, count: TGLsizei, 
+                            transpose: TGLboolean, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniformMatrix2fvARB".}
+proc glUniformMatrix3fvARB*(location: TGLint, count: TGLsizei, 
+                            transpose: TGLboolean, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniformMatrix3fvARB".}
+proc glUniformMatrix4fvARB*(location: TGLint, count: TGLsizei, 
+                            transpose: TGLboolean, value: PGLfloat){.
+    dynlib: dllname, importc: "glUniformMatrix4fvARB".}
+proc glGetObjectParameterfvARB*(obj: GLhandleARB, pname: TGLenum, 
+                                params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetObjectParameterfvARB".}
+proc glGetObjectParameterivARB*(obj: GLhandleARB, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetObjectParameterivARB".}
+proc glGetInfoLogARB*(obj: GLhandleARB, maxLength: TGLsizei, len: PGLsizei, 
+                      infoLog: PGLcharARB){.dynlib: dllname, 
+    importc: "glGetInfoLogARB".}
+proc glGetAttachedObjectsARB*(containerObj: GLhandleARB, maxCount: TGLsizei, 
+                              count: PGLsizei, obj: PGLhandleARB){.
+    dynlib: dllname, importc: "glGetAttachedObjectsARB".}
+proc glGetUniformLocationARB*(programObj: GLhandleARB, name: PGLcharARB): TGLint{.
+    dynlib: dllname, importc: "glGetUniformLocationARB".}
+proc glGetActiveUniformARB*(programObj: GLhandleARB, index: TGLuint, 
+                            maxLength: TGLsizei, len: PGLsizei, size: PGLint, 
+                            thetype: PGLenum, name: PGLcharARB){.
+    dynlib: dllname, importc: "glGetActiveUniformARB".}
+proc glGetUniformfvARB*(programObj: GLhandleARB, location: TGLint, 
+                        params: PGLfloat){.dynlib: dllname, 
+    importc: "glGetUniformfvARB".}
+proc glGetUniformivARB*(programObj: GLhandleARB, location: TGLint, 
+                        params: PGLint){.dynlib: dllname, 
+    importc: "glGetUniformivARB".}
+proc glGetShaderSourceARB*(obj: GLhandleARB, maxLength: TGLsizei, len: PGLsizei, 
+                           source: PGLcharARB){.dynlib: dllname, 
+    importc: "glGetShaderSourceARB".}
+const 
+  GL_VERTEX_SHADER_ARB* = 0x00008B31
+  GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB* = 0x00008B4A
+  GL_MAX_VARYING_FLOATS_ARB* = 0x00008B4B # GL_MAX_VERTEX_ATTRIBS_ARB  { already defined }
+                                          # GL_MAX_TEXTURE_IMAGE_UNITS_ARB  { already defined }
+  GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB* = 0x00008B4C
+  GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB* = 0x00008B4D # 
+                                                        # 
+                                                        # GL_MAX_TEXTURE_COORDS_ARB  { already defined }
+                                                        # 
+                                                        # 
+                                                        # GL_VERTEX_PROGRAM_POINT_SIZE_ARB  { already defined }
+                                                        # 
+                                                        # 
+                                                        # GL_VERTEX_PROGRAM_TWO_SIDE_ARB  { already defined }
+                                                        # GL_OBJECT_TYPE_ARB  { already defined }
+                                                        # GL_OBJECT_SUBTYPE_ARB  { already defined }
+  GL_OBJECT_ACTIVE_ATTRIBUTES_ARB* = 0x00008B89
+  GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB* = 0x00008B8A # GL_SHADER_OBJECT_ARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # GL_CURRENT_VERTEX_ATTRIB_ARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB  { already defined }
+                                                          # GL_FLOAT  { already defined }
+                                                          # GL_FLOAT_VEC2_ARB  { already defined }
+                                                          # GL_FLOAT_VEC3_ARB  { already defined }
+                                                          # GL_FLOAT_VEC4_ARB  { already defined }
+                                                          # GL_FLOAT_MAT2_ARB  { already defined }
+                                                          # GL_FLOAT_MAT3_ARB  { already defined }
+                                                          # GL_FLOAT_MAT4_ARB  { already defined }
+                                                          # glVertexAttrib1fARB  { already defined }
+                                                          # glVertexAttrib1sARB  { already defined }
+                                                          # glVertexAttrib1dARB  { already defined }
+                                                          # glVertexAttrib2fARB  { already defined }
+                                                          # glVertexAttrib2sARB  { already defined }
+                                                          # glVertexAttrib2dARB  { already defined }
+                                                          # glVertexAttrib3fARB  { already defined }
+                                                          # glVertexAttrib3sARB  { already defined }
+                                                          # glVertexAttrib3dARB  { already defined }
+                                                          # glVertexAttrib4fARB  { already defined }
+                                                          # glVertexAttrib4sARB  { already defined }
+                                                          # glVertexAttrib4dARB  { already defined }
+                                                          # glVertexAttrib4NubARB  { already defined }
+                                                          # glVertexAttrib1fvARB  { already defined }
+                                                          # glVertexAttrib1svARB  { already defined }
+                                                          # glVertexAttrib1dvARB  { already defined }
+                                                          # glVertexAttrib2fvARB  { already defined }
+                                                          # glVertexAttrib2svARB  { already defined }
+                                                          # glVertexAttrib2dvARB  { already defined }
+                                                          # glVertexAttrib3fvARB  { already defined }
+                                                          # glVertexAttrib3svARB  { already defined }
+                                                          # glVertexAttrib3dvARB  { already defined }
+                                                          # glVertexAttrib4fvARB  { already defined }
+                                                          # glVertexAttrib4svARB  { already defined }
+                                                          # glVertexAttrib4dvARB  { already defined }
+                                                          # glVertexAttrib4ivARB  { already defined }
+                                                          # glVertexAttrib4bvARB  { already defined }
+                                                          # glVertexAttrib4ubvARB  { already defined }
+                                                          # glVertexAttrib4usvARB  { already defined }
+                                                          # glVertexAttrib4uivARB  { already defined }
+                                                          # glVertexAttrib4NbvARB  { already defined }
+                                                          # glVertexAttrib4NsvARB  { already defined }
+                                                          # glVertexAttrib4NivARB  { already defined }
+                                                          # glVertexAttrib4NubvARB  { already defined }
+                                                          # glVertexAttrib4NusvARB  { already defined }
+                                                          # glVertexAttrib4NuivARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # glVertexAttribPointerARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # glEnableVertexAttribArrayARB  { already defined }
+                                                          # 
+                                                          # 
+                                                          # glDisableVertexAttribArrayARB  { already defined }
+
+proc glBindAttribLocationARB*(programObj: GLhandleARB, index: TGLuint, 
+                              name: PGLcharARB){.dynlib: dllname, 
+    importc: "glBindAttribLocationARB".}
+proc glGetActiveAttribARB*(programObj: GLhandleARB, index: TGLuint, 
+                           maxLength: TGLsizei, len: PGLsizei, size: PGLint, 
+                           thetype: PGLenum, name: PGLcharARB){.dynlib: dllname, 
+    importc: "glGetActiveAttribARB".}
+proc glGetAttribLocationARB*(programObj: GLhandleARB, name: PGLcharARB): TGLint{.
+    dynlib: dllname, importc: "glGetAttribLocationARB".}
+  # glGetVertexAttribdvARB  { already defined }
+  # glGetVertexAttribfvARB  { already defined }
+  # glGetVertexAttribivARB  { already defined }
+  # glGetVertexAttribPointervARB  { already defined }
+  #***** GL_ARB_fragment_shader *****//
+const 
+  GL_FRAGMENT_SHADER_ARB* = 0x00008B30
+  GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB* = 0x00008B49 # GL_MAX_TEXTURE_COORDS_ARB  { already defined }
+                                                       # 
+                                                       # 
+                                                       # GL_MAX_TEXTURE_IMAGE_UNITS_ARB  { already defined }
+                                                       # GL_OBJECT_TYPE_ARB  { already defined }
+                                                       # GL_OBJECT_SUBTYPE_ARB  { already defined }
+                                                       # GL_SHADER_OBJECT_ARB  { already defined }
+  #***** GL_ARB_shading_language_100 *****//
+  #***** GL_ARB_texture_non_power_of_two *****//
+  #***** GL_ARB_point_sprite *****//
+
+const 
+  GL_POINT_SPRITE_ARB* = 0x00008861
+  GL_COORD_REPLACE_ARB* = 0x00008862
+  #***** GL_EXT_depth_bounds_test *****//
+
+const 
+  constGL_DEPTH_BOUNDS_TEST_EXT* = 0x00008890
+  constGL_DEPTH_BOUNDS_EXT* = 0x00008891
+
+proc glDepthBoundsEXT*(zmin: TGLclampd, zmax: TGLclampd){.dynlib: dllname, 
+    importc: "glDepthBoundsEXT".}
+  #***** GL_EXT_texture_mirror_clamp *****//
+const 
+  GL_MIRROR_CLAMP_EXT* = 0x00008742
+  GL_MIRROR_CLAMP_TO_EDGE_EXT* = 0x00008743
+  GL_MIRROR_CLAMP_TO_BORDER_EXT* = 0x00008912
+  #***** GL_EXT_blend_equation_separate *****//
+
+const 
+  GL_BLEND_EQUATION_RGB_EXT* = 0x00008009
+  GL_BLEND_EQUATION_ALPHA_EXT* = 0x0000883D
+
+proc glBlendEquationSeparateEXT*(modeRGB: TGLenum, modeAlpha: TGLenum){.
+    dynlib: dllname, importc: "glBlendEquationSeparateEXT".}
+  #***** GL_MESA_pack_invert *****//
+const 
+  GL_PACK_INVERT_MESA* = 0x00008758
+  #***** GL_MESA_ycbcr_texture *****//
+
+const 
+  GL_YCBCR_MESA* = 0x00008757
+  GL_UNSIGNED_SHORT_8_8_MESA* = 0x000085BA
+  GL_UNSIGNED_SHORT_8_8_REV_MESA* = 0x000085BB
+  #***** GL_ARB_fragment_program_shadow *****//
+  #***** GL_NV_fragment_program_option *****//
+  #***** GL_EXT_pixel_buffer_object *****//
+
+const 
+  GL_PIXEL_PACK_BUFFER_EXT* = 0x000088EB
+  GL_PIXEL_UNPACK_BUFFER_EXT* = 0x000088EC
+  GL_PIXEL_PACK_BUFFER_BINDING_EXT* = 0x000088ED
+  GL_PIXEL_UNPACK_BUFFER_BINDING_EXT* = 0x000088EF
+  #***** GL_NV_fragment_program2 *****//
+
+const 
+  GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV* = 0x000088F4
+  GL_MAX_PROGRAM_CALL_DEPTH_NV* = 0x000088F5
+  GL_MAX_PROGRAM_IF_DEPTH_NV* = 0x000088F6
+  GL_MAX_PROGRAM_LOOP_DEPTH_NV* = 0x000088F7
+  GL_MAX_PROGRAM_LOOP_COUNT_NV* = 0x000088F8
+  #***** GL_NV_vertex_program2_option *****//
+  # GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV  { already defined }
+  # GL_MAX_PROGRAM_CALL_DEPTH_NV  { already defined }
+  #***** GL_NV_vertex_program3 *****//
+  # GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB  { already defined }
+  #***** GL_ARB_draw_buffers *****//
+
+const 
+  GL_MAX_DRAW_BUFFERS_ARB* = 0x00008824
+  GL_DRAW_BUFFER0_ARB* = 0x00008825
+  GL_DRAW_BUFFER1_ARB* = 0x00008826
+  GL_DRAW_BUFFER2_ARB* = 0x00008827
+  GL_DRAW_BUFFER3_ARB* = 0x00008828
+  GL_DRAW_BUFFER4_ARB* = 0x00008829
+  GL_DRAW_BUFFER5_ARB* = 0x0000882A
+  GL_DRAW_BUFFER6_ARB* = 0x0000882B
+  GL_DRAW_BUFFER7_ARB* = 0x0000882C
+  GL_DRAW_BUFFER8_ARB* = 0x0000882D
+  GL_DRAW_BUFFER9_ARB* = 0x0000882E
+  GL_DRAW_BUFFER10_ARB* = 0x0000882F
+  GL_DRAW_BUFFER11_ARB* = 0x00008830
+  GL_DRAW_BUFFER12_ARB* = 0x00008831
+  GL_DRAW_BUFFER13_ARB* = 0x00008832
+  GL_DRAW_BUFFER14_ARB* = 0x00008833
+  GL_DRAW_BUFFER15_ARB* = 0x00008834
+
+proc glDrawBuffersARB*(n: TGLsizei, bufs: PGLenum){.dynlib: dllname, 
+    importc: "glDrawBuffersARB".}
+  #***** GL_ARB_texture_rectangle *****//
+const 
+  GL_TEXTURE_RECTANGLE_ARB* = 0x000084F5
+  GL_TEXTURE_BINDING_RECTANGLE_ARB* = 0x000084F6
+  GL_PROXY_TEXTURE_RECTANGLE_ARB* = 0x000084F7
+  GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB* = 0x000084F8
+  #***** GL_ARB_color_buffer_float *****//
+
+const 
+  GL_RGBA_FLOAT_MODE_ARB* = 0x00008820
+  GL_CLAMP_VERTEX_COLOR_ARB* = 0x0000891A
+  GL_CLAMP_FRAGMENT_COLOR_ARB* = 0x0000891B
+  GL_CLAMP_READ_COLOR_ARB* = 0x0000891C
+  GL_FIXED_ONLY_ARB* = 0x0000891D
+  WGL_TYPE_RGBA_FLOAT_ARB* = 0x000021A0
+
+proc glClampColorARB*(target: TGLenum, clamp: TGLenum){.dynlib: dllname, 
+    importc: "glClampColorARB".}
+  #***** GL_ARB_half_float_pixel *****//
+const 
+  GL_HALF_FLOAT_ARB* = 0x0000140B
+  #***** GL_ARB_texture_float *****//
+
+const 
+  GL_TEXTURE_RED_TYPE_ARB* = 0x00008C10
+  GL_TEXTURE_GREEN_TYPE_ARB* = 0x00008C11
+  GL_TEXTURE_BLUE_TYPE_ARB* = 0x00008C12
+  GL_TEXTURE_ALPHA_TYPE_ARB* = 0x00008C13
+  GL_TEXTURE_LUMINANCE_TYPE_ARB* = 0x00008C14
+  GL_TEXTURE_INTENSITY_TYPE_ARB* = 0x00008C15
+  GL_TEXTURE_DEPTH_TYPE_ARB* = 0x00008C16
+  GL_UNSIGNED_NORMALIZED_ARB* = 0x00008C17
+  GL_RGBA32F_ARB* = 0x00008814
+  GL_RGB32F_ARB* = 0x00008815
+  GL_ALPHA32F_ARB* = 0x00008816
+  GL_INTENSITY32F_ARB* = 0x00008817
+  GL_LUMINANCE32F_ARB* = 0x00008818
+  GL_LUMINANCE_ALPHA32F_ARB* = 0x00008819
+  GL_RGBA16F_ARB* = 0x0000881A
+  GL_RGB16F_ARB* = 0x0000881B
+  GL_ALPHA16F_ARB* = 0x0000881C
+  GL_INTENSITY16F_ARB* = 0x0000881D
+  GL_LUMINANCE16F_ARB* = 0x0000881E
+  GL_LUMINANCE_ALPHA16F_ARB* = 0x0000881F
+  #***** GL_EXT_texture_compression_dxt1 *****//
+  # GL_COMPRESSED_RGB_S3TC_DXT1_EXT  { already defined }
+  # GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  { already defined }
+  #***** GL_ARB_pixel_buffer_object *****//
+
+const 
+  GL_PIXEL_PACK_BUFFER_ARB* = 0x000088EB
+  GL_PIXEL_UNPACK_BUFFER_ARB* = 0x000088EC
+  GL_PIXEL_PACK_BUFFER_BINDING_ARB* = 0x000088ED
+  GL_PIXEL_UNPACK_BUFFER_BINDING_ARB* = 0x000088EF
+  #***** GL_EXT_framebuffer_object *****//
+
+const 
+  GL_FRAMEBUFFER_EXT* = 0x00008D40
+  GL_RENDERBUFFER_EXT* = 0x00008D41
+  GL_STENCIL_INDEX_EXT* = 0x00008D45
+  GL_STENCIL_INDEX1_EXT* = 0x00008D46
+  GL_STENCIL_INDEX4_EXT* = 0x00008D47
+  GL_STENCIL_INDEX8_EXT* = 0x00008D48
+  GL_STENCIL_INDEX16_EXT* = 0x00008D49
+  GL_RENDERBUFFER_WIDTH_EXT* = 0x00008D42
+  GL_RENDERBUFFER_HEIGHT_EXT* = 0x00008D43
+  GL_RENDERBUFFER_INTERNAL_FORMAT_EXT* = 0x00008D44
+  GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT* = 0x00008CD0
+  GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT* = 0x00008CD1
+  GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT* = 0x00008CD2
+  GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT* = 0x00008CD3
+  GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT* = 0x00008CD4
+  GL_COLOR_ATTACHMENT0_EXT* = 0x00008CE0
+  GL_COLOR_ATTACHMENT1_EXT* = 0x00008CE1
+  GL_COLOR_ATTACHMENT2_EXT* = 0x00008CE2
+  GL_COLOR_ATTACHMENT3_EXT* = 0x00008CE3
+  GL_COLOR_ATTACHMENT4_EXT* = 0x00008CE4
+  GL_COLOR_ATTACHMENT5_EXT* = 0x00008CE5
+  GL_COLOR_ATTACHMENT6_EXT* = 0x00008CE6
+  GL_COLOR_ATTACHMENT7_EXT* = 0x00008CE7
+  GL_COLOR_ATTACHMENT8_EXT* = 0x00008CE8
+  GL_COLOR_ATTACHMENT9_EXT* = 0x00008CE9
+  GL_COLOR_ATTACHMENT10_EXT* = 0x00008CEA
+  GL_COLOR_ATTACHMENT11_EXT* = 0x00008CEB
+  GL_COLOR_ATTACHMENT12_EXT* = 0x00008CEC
+  GL_COLOR_ATTACHMENT13_EXT* = 0x00008CED
+  GL_COLOR_ATTACHMENT14_EXT* = 0x00008CEE
+  GL_COLOR_ATTACHMENT15_EXT* = 0x00008CEF
+  GL_DEPTH_ATTACHMENT_EXT* = 0x00008D00
+  GL_STENCIL_ATTACHMENT_EXT* = 0x00008D20
+  GL_FRAMEBUFFER_COMPLETE_EXT* = 0x00008CD5
+  GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT* = 0x00008CD6
+  GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT* = 0x00008CD7
+  GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT* = 0x00008CD8
+  GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT* = 0x00008CD9
+  GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT* = 0x00008CDA
+  GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT* = 0x00008CDB
+  GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT* = 0x00008CDC
+  GL_FRAMEBUFFER_UNSUPPORTED_EXT* = 0x00008CDD
+  GL_FRAMEBUFFER_STATUS_ERROR_EXT* = 0x00008CDE
+  GL_FRAMEBUFFER_BINDING_EXT* = 0x00008CA6
+  GL_RENDERBUFFER_BINDING_EXT* = 0x00008CA7
+  GL_MAX_COLOR_ATTACHMENTS_EXT* = 0x00008CDF
+  GL_MAX_RENDERBUFFER_SIZE_EXT* = 0x000084E8
+  GL_INVALID_FRAMEBUFFER_OPERATION_EXT* = 0x00000506
+
+proc glIsRenderbufferEXT*(renderbuffer: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsRenderbufferEXT".}
+proc glBindRenderbufferEXT*(target: TGLenum, renderbuffer: TGLuint){.
+    dynlib: dllname, importc: "glBindRenderbufferEXT".}
+proc glDeleteRenderbuffersEXT*(n: TGLsizei, renderbuffers: PGLuint){.
+    dynlib: dllname, importc: "glDeleteRenderbuffersEXT".}
+proc glGenRenderbuffersEXT*(n: TGLsizei, renderbuffers: PGLuint){.
+    dynlib: dllname, importc: "glGenRenderbuffersEXT".}
+proc glRenderbufferStorageEXT*(target: TGLenum, internalformat: TGLenum, 
+                               width: TGLsizei, height: TGLsizei){.
+    dynlib: dllname, importc: "glRenderbufferStorageEXT".}
+proc glGetRenderbufferParameterivEXT*(target: TGLenum, pname: TGLenum, 
+                                      params: PGLint){.dynlib: dllname, 
+    importc: "glGetRenderbufferParameterivEXT".}
+proc glIsFramebufferEXT*(framebuffer: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsFramebufferEXT".}
+proc glBindFramebufferEXT*(target: TGLenum, framebuffer: TGLuint){.
+    dynlib: dllname, importc: "glBindFramebufferEXT".}
+proc glDeleteFramebuffersEXT*(n: TGLsizei, framebuffers: PGLuint){.
+    dynlib: dllname, importc: "glDeleteFramebuffersEXT".}
+proc glGenFramebuffersEXT*(n: TGLsizei, framebuffers: PGLuint){.dynlib: dllname, 
+    importc: "glGenFramebuffersEXT".}
+proc glCheckFramebufferStatusEXT*(target: TGLenum): TGLenum{.dynlib: dllname, 
+    importc: "glCheckFramebufferStatusEXT".}
+proc glFramebufferTexture1DEXT*(target: TGLenum, attachment: TGLenum, 
+                                textarget: TGLenum, texture: TGLuint, 
+                                level: TGLint){.dynlib: dllname, 
+    importc: "glFramebufferTexture1DEXT".}
+proc glFramebufferTexture2DEXT*(target: TGLenum, attachment: TGLenum, 
+                                textarget: TGLenum, texture: TGLuint, 
+                                level: TGLint){.dynlib: dllname, 
+    importc: "glFramebufferTexture2DEXT".}
+proc glFramebufferTexture3DEXT*(target: TGLenum, attachment: TGLenum, 
+                                textarget: TGLenum, texture: TGLuint, 
+                                level: TGLint, zoffset: TGLint){.
+    dynlib: dllname, importc: "glFramebufferTexture3DEXT".}
+proc glFramebufferRenderbufferEXT*(target: TGLenum, attachment: TGLenum, 
+                                   renderbuffertarget: TGLenum, 
+                                   renderbuffer: TGLuint){.dynlib: dllname, 
+    importc: "glFramebufferRenderbufferEXT".}
+proc glGetFramebufferAttachmentParameterivEXT*(target: TGLenum, 
+    attachment: TGLenum, pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glGetFramebufferAttachmentParameterivEXT".}
+proc glGenerateMipmapEXT*(target: TGLenum){.dynlib: dllname, 
+    importc: "glGenerateMipmapEXT".}
+  #***** GL_version_1_4 *****//
+const 
+  GL_BLEND_DST_RGB* = 0x000080C8
+  GL_BLEND_SRC_RGB* = 0x000080C9
+  GL_BLEND_DST_ALPHA* = 0x000080CA
+  GL_BLEND_SRC_ALPHA* = 0x000080CB
+  GL_POINT_SIZE_MIN* = 0x00008126
+  GL_POINT_SIZE_MAX* = 0x00008127
+  GL_POINT_FADE_THRESHOLD_SIZE* = 0x00008128
+  GL_POINT_DISTANCE_ATTENUATION* = 0x00008129
+  GL_GENERATE_MIPMAP* = 0x00008191
+  GL_GENERATE_MIPMAP_HINT* = 0x00008192
+  GL_DEPTH_COMPONENT16* = 0x000081A5
+  GL_DEPTH_COMPONENT24* = 0x000081A6
+  GL_DEPTH_COMPONENT32* = 0x000081A7
+  GL_MIRRORED_REPEAT* = 0x00008370
+  GL_FOG_COORDINATE_SOURCE* = 0x00008450
+  GL_FOG_COORDINATE* = 0x00008451
+  GL_FRAGMENT_DEPTH* = 0x00008452
+  GL_CURRENT_FOG_COORDINATE* = 0x00008453
+  GL_FOG_COORDINATE_ARRAY_TYPE* = 0x00008454
+  GL_FOG_COORDINATE_ARRAY_STRIDE* = 0x00008455
+  GL_FOG_COORDINATE_ARRAY_POINTER* = 0x00008456
+  GL_FOG_COORDINATE_ARRAY* = 0x00008457
+  GL_COLOR_SUM* = 0x00008458
+  GL_CURRENT_SECONDARY_COLOR* = 0x00008459
+  GL_SECONDARY_COLOR_ARRAY_SIZE* = 0x0000845A
+  GL_SECONDARY_COLOR_ARRAY_TYPE* = 0x0000845B
+  GL_SECONDARY_COLOR_ARRAY_STRIDE* = 0x0000845C
+  GL_SECONDARY_COLOR_ARRAY_POINTER* = 0x0000845D
+  GL_SECONDARY_COLOR_ARRAY* = 0x0000845E
+  GL_MAX_TEXTURE_LOD_BIAS* = 0x000084FD
+  GL_TEXTURE_FILTER_CONTROL* = 0x00008500
+  GL_TEXTURE_LOD_BIAS* = 0x00008501
+  GL_INCR_WRAP* = 0x00008507
+  GL_DECR_WRAP* = 0x00008508
+  GL_TEXTURE_DEPTH_SIZE* = 0x0000884A
+  GL_DEPTH_TEXTURE_MODE* = 0x0000884B
+  GL_TEXTURE_COMPARE_MODE* = 0x0000884C
+  GL_TEXTURE_COMPARE_FUNC* = 0x0000884D
+  GL_COMPARE_R_TO_TEXTURE* = 0x0000884E
+
+proc glBlendFuncSeparate*(sfactorRGB: TGLenum, dfactorRGB: TGLenum, 
+                          sfactorAlpha: TGLenum, dfactorAlpha: TGLenum){.
+    dynlib: dllname, importc: "glBlendFuncSeparate".}
+proc glFogCoordf*(coord: TGLfloat){.dynlib: dllname, importc: "glFogCoordf".}
+proc glFogCoordfv*(coord: PGLfloat){.dynlib: dllname, importc: "glFogCoordfv".}
+proc glFogCoordd*(coord: TGLdouble){.dynlib: dllname, importc: "glFogCoordd".}
+proc glFogCoorddv*(coord: PGLdouble){.dynlib: dllname, importc: "glFogCoorddv".}
+proc glFogCoordPointer*(thetype: TGLenum, stride: TGLsizei, pointer: PGLvoid){.
+    dynlib: dllname, importc: "glFogCoordPointer".}
+proc glMultiDrawArrays*(mode: TGLenum, first: PGLint, count: PGLsizei, 
+                        primcount: TGLsizei){.dynlib: dllname, 
+    importc: "glMultiDrawArrays".}
+proc glMultiDrawElements*(mode: TGLenum, count: PGLsizei, thetype: TGLenum, 
+                          indices: PGLvoid, primcount: TGLsizei){.
+    dynlib: dllname, importc: "glMultiDrawElements".}
+proc glPointParameterf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, 
+    importc: "glPointParameterf".}
+proc glPointParameterfv*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, 
+    importc: "glPointParameterfv".}
+proc glPointParameteri*(pname: TGLenum, param: TGLint){.dynlib: dllname, 
+    importc: "glPointParameteri".}
+proc glPointParameteriv*(pname: TGLenum, params: PGLint){.dynlib: dllname, 
+    importc: "glPointParameteriv".}
+proc glSecondaryColor3b*(red: TGLByte, green: TGLByte, blue: TGLByte){.
+    dynlib: dllname, importc: "glSecondaryColor3b".}
+proc glSecondaryColor3bv*(v: PGLbyte){.dynlib: dllname, 
+                                       importc: "glSecondaryColor3bv".}
+proc glSecondaryColor3d*(red: TGLdouble, green: TGLdouble, blue: TGLdouble){.
+    dynlib: dllname, importc: "glSecondaryColor3d".}
+proc glSecondaryColor3dv*(v: PGLdouble){.dynlib: dllname, 
+    importc: "glSecondaryColor3dv".}
+proc glSecondaryColor3f*(red: TGLfloat, green: TGLfloat, blue: TGLfloat){.
+    dynlib: dllname, importc: "glSecondaryColor3f".}
+proc glSecondaryColor3fv*(v: PGLfloat){.dynlib: dllname, 
+                                        importc: "glSecondaryColor3fv".}
+proc glSecondaryColor3i*(red: TGLint, green: TGLint, blue: TGLint){.
+    dynlib: dllname, importc: "glSecondaryColor3i".}
+proc glSecondaryColor3iv*(v: PGLint){.dynlib: dllname, 
+                                      importc: "glSecondaryColor3iv".}
+proc glSecondaryColor3s*(red: TGLshort, green: TGLshort, blue: TGLshort){.
+    dynlib: dllname, importc: "glSecondaryColor3s".}
+proc glSecondaryColor3sv*(v: PGLshort){.dynlib: dllname, 
+                                        importc: "glSecondaryColor3sv".}
+proc glSecondaryColor3ub*(red: TGLubyte, green: TGLubyte, blue: TGLubyte){.
+    dynlib: dllname, importc: "glSecondaryColor3ub".}
+proc glSecondaryColor3ubv*(v: PGLubyte){.dynlib: dllname, 
+    importc: "glSecondaryColor3ubv".}
+proc glSecondaryColor3ui*(red: TGLuint, green: TGLuint, blue: TGLuint){.
+    dynlib: dllname, importc: "glSecondaryColor3ui".}
+proc glSecondaryColor3uiv*(v: PGLuint){.dynlib: dllname, 
+                                        importc: "glSecondaryColor3uiv".}
+proc glSecondaryColor3us*(red: TGLushort, green: TGLushort, blue: TGLushort){.
+    dynlib: dllname, importc: "glSecondaryColor3us".}
+proc glSecondaryColor3usv*(v: PGLushort){.dynlib: dllname, 
+    importc: "glSecondaryColor3usv".}
+proc glSecondaryColorPointer*(size: TGLint, thetype: TGLenum, stride: TGLsizei, 
+                              pointer: PGLvoid){.dynlib: dllname, 
+    importc: "glSecondaryColorPointer".}
+proc glWindowPos2d*(x: TGLdouble, y: TGLdouble){.dynlib: dllname, 
+    importc: "glWindowPos2d".}
+proc glWindowPos2dv*(v: PGLdouble){.dynlib: dllname, importc: "glWindowPos2dv".}
+proc glWindowPos2f*(x: TGLfloat, y: TGLfloat){.dynlib: dllname, 
+    importc: "glWindowPos2f".}
+proc glWindowPos2fv*(v: PGLfloat){.dynlib: dllname, importc: "glWindowPos2fv".}
+proc glWindowPos2i*(x: TGLint, y: TGLint){.dynlib: dllname, 
+    importc: "glWindowPos2i".}
+proc glWindowPos2iv*(v: PGLint){.dynlib: dllname, importc: "glWindowPos2iv".}
+proc glWindowPos2s*(x: TGLshort, y: TGLshort){.dynlib: dllname, 
+    importc: "glWindowPos2s".}
+proc glWindowPos2sv*(v: PGLshort){.dynlib: dllname, importc: "glWindowPos2sv".}
+proc glWindowPos3d*(x: TGLdouble, y: TGLdouble, z: TGLdouble){.dynlib: dllname, 
+    importc: "glWindowPos3d".}
+proc glWindowPos3dv*(v: PGLdouble){.dynlib: dllname, importc: "glWindowPos3dv".}
+proc glWindowPos3f*(x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, 
+    importc: "glWindowPos3f".}
+proc glWindowPos3fv*(v: PGLfloat){.dynlib: dllname, importc: "glWindowPos3fv".}
+proc glWindowPos3i*(x: TGLint, y: TGLint, z: TGLint){.dynlib: dllname, 
+    importc: "glWindowPos3i".}
+proc glWindowPos3iv*(v: PGLint){.dynlib: dllname, importc: "glWindowPos3iv".}
+proc glWindowPos3s*(x: TGLshort, y: TGLshort, z: TGLshort){.dynlib: dllname, 
+    importc: "glWindowPos3s".}
+proc glWindowPos3sv*(v: PGLshort){.dynlib: dllname, importc: "glWindowPos3sv".}
+  #***** GL_version_1_5 *****//
+const 
+  GL_BUFFER_SIZE* = 0x00008764
+  GL_BUFFER_USAGE* = 0x00008765
+  GL_QUERY_COUNTER_BITS* = 0x00008864
+  GL_CURRENT_QUERY* = 0x00008865
+  GL_QUERY_RESULT* = 0x00008866
+  GL_QUERY_RESULT_AVAILABLE* = 0x00008867
+  GL_ARRAY_BUFFER* = 0x00008892
+  GL_ELEMENT_ARRAY_BUFFER* = 0x00008893
+  GL_ARRAY_BUFFER_BINDING* = 0x00008894
+  GL_ELEMENT_ARRAY_BUFFER_BINDING* = 0x00008895
+  GL_VERTEX_ARRAY_BUFFER_BINDING* = 0x00008896
+  GL_NORMAL_ARRAY_BUFFER_BINDING* = 0x00008897
+  GL_COLOR_ARRAY_BUFFER_BINDING* = 0x00008898
+  GL_INDEX_ARRAY_BUFFER_BINDING* = 0x00008899
+  GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING* = 0x0000889A
+  GL_EDGE_FLAG_ARRAY_BUFFER_BINDING* = 0x0000889B
+  GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING* = 0x0000889C
+  GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING* = 0x0000889D
+  GL_WEIGHT_ARRAY_BUFFER_BINDING* = 0x0000889E
+  GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING* = 0x0000889F
+  GL_READ_ONLY* = 0x000088B8
+  GL_WRITE_ONLY* = 0x000088B9
+  GL_READ_WRITE* = 0x000088BA
+  GL_BUFFER_ACCESS* = 0x000088BB
+  GL_BUFFER_MAPPED* = 0x000088BC
+  GL_BUFFER_MAP_POINTER* = 0x000088BD
+  GL_STREAM_DRAW* = 0x000088E0
+  GL_STREAM_READ* = 0x000088E1
+  GL_STREAM_COPY* = 0x000088E2
+  GL_STATIC_DRAW* = 0x000088E4
+  GL_STATIC_READ* = 0x000088E5
+  GL_STATIC_COPY* = 0x000088E6
+  GL_DYNAMIC_DRAW* = 0x000088E8
+  GL_DYNAMIC_READ* = 0x000088E9
+  GL_DYNAMIC_COPY* = 0x000088EA
+  GL_SAMPLES_PASSED* = 0x00008914
+  GL_FOG_COORD_SRC* = 0x00008450
+  GL_FOG_COORD* = 0x00008451
+  GL_CURRENT_FOG_COORD* = 0x00008453
+  GL_FOG_COORD_ARRAY_TYPE* = 0x00008454
+  GL_FOG_COORD_ARRAY_STRIDE* = 0x00008455
+  GL_FOG_COORD_ARRAY_POINTER* = 0x00008456
+  GL_FOG_COORD_ARRAY* = 0x00008457
+  GL_FOG_COORD_ARRAY_BUFFER_BINDING* = 0x0000889D
+  GL_SRC0_RGB* = 0x00008580
+  GL_SRC1_RGB* = 0x00008581
+  GL_SRC2_RGB* = 0x00008582
+  GL_SRC0_ALPHA* = 0x00008588
+  GL_SRC1_ALPHA* = 0x00008589
+  GL_SRC2_ALPHA* = 0x0000858A
+
+proc glGenQueries*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, 
+    importc: "glGenQueries".}
+proc glDeleteQueries*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteQueries".}
+proc glIsQuery*(id: TGLuint): TGLboolean{.dynlib: dllname, importc: "glIsQuery".}
+proc glBeginQuery*(target: TGLenum, id: TGLuint){.dynlib: dllname, 
+    importc: "glBeginQuery".}
+proc glEndQuery*(target: TGLenum){.dynlib: dllname, importc: "glEndQuery".}
+proc glGetQueryiv*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetQueryiv".}
+proc glGetQueryObjectiv*(id: TGLuint, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetQueryObjectiv".}
+proc glGetQueryObjectuiv*(id: TGLuint, pname: TGLenum, params: PGLuint){.
+    dynlib: dllname, importc: "glGetQueryObjectuiv".}
+proc glBindBuffer*(target: TGLenum, buffer: TGLuint){.dynlib: dllname, 
+    importc: "glBindBuffer".}
+proc glDeleteBuffers*(n: TGLsizei, buffers: PGLuint){.dynlib: dllname, 
+    importc: "glDeleteBuffers".}
+proc glGenBuffers*(n: TGLsizei, buffers: PGLuint){.dynlib: dllname, 
+    importc: "glGenBuffers".}
+proc glIsBuffer*(buffer: TGLuint): TGLboolean{.dynlib: dllname, 
+    importc: "glIsBuffer".}
+proc glBufferData*(target: TGLenum, size: GLsizeiptr, data: PGLvoid, 
+                   usage: TGLenum){.dynlib: dllname, importc: "glBufferData".}
+proc glBufferSubData*(target: TGLenum, offset: GLintptr, size: GLsizeiptr, 
+                      data: PGLvoid){.dynlib: dllname, 
+                                      importc: "glBufferSubData".}
+proc glGetBufferSubData*(target: TGLenum, offset: GLintptr, size: GLsizeiptr, 
+                         data: PGLvoid){.dynlib: dllname, 
+    importc: "glGetBufferSubData".}
+proc glMapBuffer*(target: TGLenum, access: TGLenum): PGLvoid{.dynlib: dllname, 
+    importc: "glMapBuffer".}
+proc glUnmapBuffer*(target: TGLenum): TGLboolean{.dynlib: dllname, 
+    importc: "glUnmapBuffer".}
+proc glGetBufferParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){.
+    dynlib: dllname, importc: "glGetBufferParameteriv".}
+proc glGetBufferPointerv*(target: TGLenum, pname: TGLenum, params: PGLvoid){.
+    dynlib: dllname, importc: "glGetBufferPointerv".}
+  #***** GL_version_2_0 *****//
+const 
+  GL_BLEND_EQUATION_RGB* = 0x00008009
+  GL_VERTEX_ATTRIB_ARRAY_ENABLED* = 0x00008622
+  GL_VERTEX_ATTRIB_ARRAY_SIZE* = 0x00008623
+  GL_VERTEX_ATTRIB_ARRAY_STRIDE* = 0x00008624
+  GL_VERTEX_ATTRIB_ARRAY_TYPE* = 0x00008625
+  GL_CURRENT_VERTEX_ATTRIB* = 0x00008626
+  GL_VERTEX_PROGRAM_POINT_SIZE* = 0x00008642
+  GL_VERTEX_PROGRAM_TWO_SIDE* = 0x00008643
+  GL_VERTEX_ATTRIB_ARRAY_POINTER* = 0x00008645
+  GL_STENCIL_BACK_FUNC* = 0x00008800
+  GL_STENCIL_BACK_FAIL* = 0x00008801
+  GL_STENCIL_BACK_PASS_DEPTH_FAIL* = 0x00008802
+  GL_STENCIL_BACK_PASS_DEPTH_PASS* = 0x00008803
+  GL_MAX_DRAW_BUFFERS* = 0x00008824
+  GL_DRAW_BUFFER0* = 0x00008825
+  GL_DRAW_BUFFER1* = 0x00008826
+  GL_DRAW_BUFFER2* = 0x00008827
+  GL_DRAW_BUFFER3* = 0x00008828
+  GL_DRAW_BUFFER4* = 0x00008829
+  GL_DRAW_BUFFER5* = 0x0000882A
+  GL_DRAW_BUFFER6* = 0x0000882B
+  GL_DRAW_BUFFER7* = 0x0000882C
+  GL_DRAW_BUFFER8* = 0x0000882D
+  GL_DRAW_BUFFER9* = 0x0000882E
+  GL_DRAW_BUFFER10* = 0x0000882F
+  GL_DRAW_BUFFER11* = 0x00008830
+  GL_DRAW_BUFFER12* = 0x00008831
+  GL_DRAW_BUFFER13* = 0x00008832
+  GL_DRAW_BUFFER14* = 0x00008833
+  GL_DRAW_BUFFER15* = 0x00008834
+  GL_BLEND_EQUATION_ALPHA* = 0x0000883D
+  GL_POINT_SPRITE* = 0x00008861
+  GL_COORD_REPLACE* = 0x00008862
+  GL_MAX_VERTEX_ATTRIBS* = 0x00008869
+  GL_VERTEX_ATTRIB_ARRAY_NORMALIZED* = 0x0000886A
+  GL_MAX_TEXTURE_COORDS* = 0x00008871
+  GL_MAX_TEXTURE_IMAGE_UNITS* = 0x00008872
+  GL_FRAGMENT_SHADER* = 0x00008B30
+  GL_VERTEX_SHADER* = 0x00008B31
+  GL_MAX_FRAGMENT_UNIFORM_COMPONENTS* = 0x00008B49
+  GL_MAX_VERTEX_UNIFORM_COMPONENTS* = 0x00008B4A
+  GL_MAX_VARYING_FLOATS* = 0x00008B4B
+  GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS* = 0x00008B4C
+  GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS* = 0x00008B4D
+  GL_SHADER_TYPE* = 0x00008B4F
+  GL_FLOAT_VEC2* = 0x00008B50
+  GL_FLOAT_VEC3* = 0x00008B51
+  GL_FLOAT_VEC4* = 0x00008B52
+  GL_INT_VEC2* = 0x00008B53
+  GL_INT_VEC3* = 0x00008B54
+  GL_INT_VEC4* = 0x00008B55
+  GL_BOOL* = 0x00008B56
+  GL_BOOL_VEC2* = 0x00008B57
+  GL_BOOL_VEC3* = 0x00008B58
+  GL_BOOL_VEC4* = 0x00008B59
+  GL_FLOAT_MAT2* = 0x00008B5A
+  GL_FLOAT_MAT3* = 0x00008B5B
+  GL_FLOAT_MAT4* = 0x00008B5C
+  GL_SAMPLER_1D* = 0x00008B5D
+  GL_SAMPLER_2D* = 0x00008B5E
+  GL_SAMPLER_3D* = 0x00008B5F
+  GL_SAMPLER_CUBE* = 0x00008B60
+  GL_SAMPLER_1D_SHADOW* = 0x00008B61
+  GL_SAMPLER_2D_SHADOW* = 0x00008B62
+  GL_DELETE_STATUS* = 0x00008B80
+  GL_COMPILE_STATUS* = 0x00008B81
+  GL_LINK_STATUS* = 0x00008B82
+  GL_VALIDATE_STATUS* = 0x00008B83
+  GL_INFO_LOG_LENGTH* = 0x00008B84
+  GL_ATTACHED_SHADERS* = 0x00008B85
+  GL_ACTIVE_UNIFORMS* = 0x00008B86
+  GL_ACTIVE_UNIFORM_MAX_LENGTH* = 0x00008B87
+  GL_SHADER_SOURCE_LENGTH* = 0x00008B88
+  GL_ACTIVE_ATTRIBUTES* = 0x00008B89
+  GL_ACTIVE_ATTRIBUTE_MAX_LENGTH* = 0x00008B8A
+  GL_FRAGMENT_SHADER_DERIVATIVE_HINT* = 0x00008B8B
+  GL_SHADING_LANGUAGE_VERSION* = 0x00008B8C
+  GL_CURRENT_PROGRAM* = 0x00008B8D
+  GL_POINT_SPRITE_COORD_ORIGIN* = 0x00008CA0
+  GL_LOWER_LEFT* = 0x00008CA1
+  GL_UPPER_LEFT* = 0x00008CA2
+  GL_STENCIL_BACK_REF* = 0x00008CA3
+  GL_STENCIL_BACK_VALUE_MASK* = 0x00008CA4
+  GL_STENCIL_BACK_WRITEMASK* = 0x00008CA5
+
+{.pop.}
\ No newline at end of file
diff --git a/tests/manyloc/keineschweine/lib/glu.nim b/tests/manyloc/keineschweine/lib/glu.nim
new file mode 100644
index 0000000000..e00120d83b
--- /dev/null
+++ b/tests/manyloc/keineschweine/lib/glu.nim
@@ -0,0 +1,335 @@
+#
+#
+#  Adaption of the delphi3d.net OpenGL units to FreePascal
+#  Sebastian Guenther (sg@freepascal.org) in 2002
+#  These units are free to use
+#******************************************************************************
+# Converted to Delphi by Tom Nuydens (tom@delphi3d.net)                        
+# For the latest updates, visit Delphi3D: http://www.delphi3d.net              
+#******************************************************************************
+
+import 
+  GL
+
+when defined(windows): 
+  {.push, callconv: stdcall.}
+else: 
+  {.push, callconv: cdecl.}
+
+when defined(windows): 
+  const 
+    dllname = "glu32.dll"
+elif defined(macosx): 
+  const 
+    dllname = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"
+else: 
+  const 
+    dllname = "libGLU.so.1"
+type 
+  TViewPortArray* = array[0..3, TGLint]
+  T16dArray* = array[0..15, TGLdouble]
+  TCallBack* = proc ()
+  T3dArray* = array[0..2, TGLdouble]
+  T4pArray* = array[0..3, Pointer]
+  T4fArray* = array[0..3, TGLfloat]
+  PPointer* = ptr Pointer
+
+type 
+  GLUnurbs*{.final.} = object 
+  PGLUnurbs* = ptr GLUnurbs
+  GLUquadric*{.final.} = object 
+  PGLUquadric* = ptr GLUquadric
+  GLUtesselator*{.final.} = object 
+  PGLUtesselator* = ptr GLUtesselator # backwards compatibility:
+  GLUnurbsObj* = GLUnurbs
+  PGLUnurbsObj* = PGLUnurbs
+  GLUquadricObj* = GLUquadric
+  PGLUquadricObj* = PGLUquadric
+  GLUtesselatorObj* = GLUtesselator
+  PGLUtesselatorObj* = PGLUtesselator
+  GLUtriangulatorObj* = GLUtesselator
+  PGLUtriangulatorObj* = PGLUtesselator
+  TGLUnurbs* = GLUnurbs
+  TGLUquadric* = GLUquadric
+  TGLUtesselator* = GLUtesselator
+  TGLUnurbsObj* = GLUnurbsObj
+  TGLUquadricObj* = GLUquadricObj
+  TGLUtesselatorObj* = GLUtesselatorObj
+  TGLUtriangulatorObj* = GLUtriangulatorObj
+
+proc gluErrorString*(errCode: TGLenum): cstring{.dynlib: dllname, 
+    importc: "gluErrorString".}
+proc gluErrorUnicodeStringEXT*(errCode: TGLenum): ptr int16{.dynlib: dllname, 
+    importc: "gluErrorUnicodeStringEXT".}
+proc gluGetString*(name: TGLenum): cstring{.dynlib: dllname, 
+    importc: "gluGetString".}
+proc gluOrtho2D*(left, right, bottom, top: TGLdouble){.dynlib: dllname, 
+    importc: "gluOrtho2D".}
+proc gluPerspective*(fovy, aspect, zNear, zFar: TGLdouble){.dynlib: dllname, 
+    importc: "gluPerspective".}
+proc gluPickMatrix*(x, y, width, height: TGLdouble, viewport: var TViewPortArray){.
+    dynlib: dllname, importc: "gluPickMatrix".}
+proc gluLookAt*(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz: TGLdouble){.
+    dynlib: dllname, importc: "gluLookAt".}
+proc gluProject*(objx, objy, objz: TGLdouble, 
+                 modelMatrix, projMatrix: var T16dArray, 
+                 viewport: var TViewPortArray, winx, winy, winz: PGLdouble): int{.
+    dynlib: dllname, importc: "gluProject".}
+proc gluUnProject*(winx, winy, winz: TGLdouble, 
+                   modelMatrix, projMatrix: var T16dArray, 
+                   viewport: var TViewPortArray, objx, objy, objz: PGLdouble): int{.
+    dynlib: dllname, importc: "gluUnProject".}
+proc gluScaleImage*(format: TGLenum, widthin, heightin: TGLint, typein: TGLenum, 
+                    datain: Pointer, widthout, heightout: TGLint, 
+                    typeout: TGLenum, dataout: Pointer): int{.dynlib: dllname, 
+    importc: "gluScaleImage".}
+proc gluBuild1DMipmaps*(target: TGLenum, components, width: TGLint, 
+                        format, atype: TGLenum, data: Pointer): int{.
+    dynlib: dllname, importc: "gluBuild1DMipmaps".}
+proc gluBuild2DMipmaps*(target: TGLenum, components, width, height: TGLint, 
+                        format, atype: TGLenum, data: Pointer): int{.
+    dynlib: dllname, importc: "gluBuild2DMipmaps".}
+proc gluNewQuadric*(): PGLUquadric{.dynlib: dllname, importc: "gluNewQuadric".}
+proc gluDeleteQuadric*(state: PGLUquadric){.dynlib: dllname, 
+    importc: "gluDeleteQuadric".}
+proc gluQuadricNormals*(quadObject: PGLUquadric, normals: TGLenum){.
+    dynlib: dllname, importc: "gluQuadricNormals".}
+proc gluQuadricTexture*(quadObject: PGLUquadric, textureCoords: TGLboolean){.
+    dynlib: dllname, importc: "gluQuadricTexture".}
+proc gluQuadricOrientation*(quadObject: PGLUquadric, orientation: TGLenum){.
+    dynlib: dllname, importc: "gluQuadricOrientation".}
+proc gluQuadricDrawStyle*(quadObject: PGLUquadric, drawStyle: TGLenum){.
+    dynlib: dllname, importc: "gluQuadricDrawStyle".}
+proc gluCylinder*(qobj: PGLUquadric, baseRadius, topRadius, height: TGLdouble, 
+                  slices, stacks: TGLint){.dynlib: dllname, 
+    importc: "gluCylinder".}
+proc gluDisk*(qobj: PGLUquadric, innerRadius, outerRadius: TGLdouble, 
+              slices, loops: TGLint){.dynlib: dllname, importc: "gluDisk".}
+proc gluPartialDisk*(qobj: PGLUquadric, innerRadius, outerRadius: TGLdouble, 
+                     slices, loops: TGLint, startAngle, sweepAngle: TGLdouble){.
+    dynlib: dllname, importc: "gluPartialDisk".}
+proc gluSphere*(qobj: PGLuquadric, radius: TGLdouble, slices, stacks: TGLint){.
+    dynlib: dllname, importc: "gluSphere".}
+proc gluQuadricCallback*(qobj: PGLUquadric, which: TGLenum, fn: TCallBack){.
+    dynlib: dllname, importc: "gluQuadricCallback".}
+proc gluNewTess*(): PGLUtesselator{.dynlib: dllname, importc: "gluNewTess".}
+proc gluDeleteTess*(tess: PGLUtesselator){.dynlib: dllname, 
+    importc: "gluDeleteTess".}
+proc gluTessBeginPolygon*(tess: PGLUtesselator, polygon_data: Pointer){.
+    dynlib: dllname, importc: "gluTessBeginPolygon".}
+proc gluTessBeginContour*(tess: PGLUtesselator){.dynlib: dllname, 
+    importc: "gluTessBeginContour".}
+proc gluTessVertex*(tess: PGLUtesselator, coords: var T3dArray, data: Pointer){.
+    dynlib: dllname, importc: "gluTessVertex".}
+proc gluTessEndContour*(tess: PGLUtesselator){.dynlib: dllname, 
+    importc: "gluTessEndContour".}
+proc gluTessEndPolygon*(tess: PGLUtesselator){.dynlib: dllname, 
+    importc: "gluTessEndPolygon".}
+proc gluTessProperty*(tess: PGLUtesselator, which: TGLenum, value: TGLdouble){.
+    dynlib: dllname, importc: "gluTessProperty".}
+proc gluTessNormal*(tess: PGLUtesselator, x, y, z: TGLdouble){.dynlib: dllname, 
+    importc: "gluTessNormal".}
+proc gluTessCallback*(tess: PGLUtesselator, which: TGLenum, fn: TCallBack){.
+    dynlib: dllname, importc: "gluTessCallback".}
+proc gluGetTessProperty*(tess: PGLUtesselator, which: TGLenum, value: PGLdouble){.
+    dynlib: dllname, importc: "gluGetTessProperty".}
+proc gluNewNurbsRenderer*(): PGLUnurbs{.dynlib: dllname, 
+                                        importc: "gluNewNurbsRenderer".}
+proc gluDeleteNurbsRenderer*(nobj: PGLUnurbs){.dynlib: dllname, 
+    importc: "gluDeleteNurbsRenderer".}
+proc gluBeginSurface*(nobj: PGLUnurbs){.dynlib: dllname, 
+                                        importc: "gluBeginSurface".}
+proc gluBeginCurve*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluBeginCurve".}
+proc gluEndCurve*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluEndCurve".}
+proc gluEndSurface*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluEndSurface".}
+proc gluBeginTrim*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluBeginTrim".}
+proc gluEndTrim*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluEndTrim".}
+proc gluPwlCurve*(nobj: PGLUnurbs, count: TGLint, aarray: PGLfloat, 
+                  stride: TGLint, atype: TGLenum){.dynlib: dllname, 
+    importc: "gluPwlCurve".}
+proc gluNurbsCurve*(nobj: PGLUnurbs, nknots: TGLint, knot: PGLfloat, 
+                    stride: TGLint, ctlarray: PGLfloat, order: TGLint, 
+                    atype: TGLenum){.dynlib: dllname, importc: "gluNurbsCurve".}
+proc gluNurbsSurface*(nobj: PGLUnurbs, sknot_count: TGLint, sknot: PGLfloat, 
+                      tknot_count: TGLint, tknot: PGLfloat, 
+                      s_stride, t_stride: TGLint, ctlarray: PGLfloat, 
+                      sorder, torder: TGLint, atype: TGLenum){.dynlib: dllname, 
+    importc: "gluNurbsSurface".}
+proc gluLoadSamplingMatrices*(nobj: PGLUnurbs, 
+                              modelMatrix, projMatrix: var T16dArray, 
+                              viewport: var TViewPortArray){.dynlib: dllname, 
+    importc: "gluLoadSamplingMatrices".}
+proc gluNurbsProperty*(nobj: PGLUnurbs, aproperty: TGLenum, value: TGLfloat){.
+    dynlib: dllname, importc: "gluNurbsProperty".}
+proc gluGetNurbsProperty*(nobj: PGLUnurbs, aproperty: TGLenum, value: PGLfloat){.
+    dynlib: dllname, importc: "gluGetNurbsProperty".}
+proc gluNurbsCallback*(nobj: PGLUnurbs, which: TGLenum, fn: TCallBack){.
+    dynlib: dllname, importc: "gluNurbsCallback".}
+  #*** Callback function prototypes ***
+type                          # gluQuadricCallback
+  GLUquadricErrorProc* = proc (p: TGLenum) # gluTessCallback
+  GLUtessBeginProc* = proc (p: TGLenum)
+  GLUtessEdgeFlagProc* = proc (p: TGLboolean)
+  GLUtessVertexProc* = proc (p: Pointer)
+  GLUtessEndProc* = proc ()
+  GLUtessErrorProc* = proc (p: TGLenum)
+  GLUtessCombineProc* = proc (p1: var T3dArray, p2: T4pArray, p3: T4fArray, 
+                              p4: PPointer)
+  GLUtessBeginDataProc* = proc (p1: TGLenum, p2: Pointer)
+  GLUtessEdgeFlagDataProc* = proc (p1: TGLboolean, p2: Pointer)
+  GLUtessVertexDataProc* = proc (p1, p2: Pointer)
+  GLUtessEndDataProc* = proc (p: Pointer)
+  GLUtessErrorDataProc* = proc (p1: TGLenum, p2: Pointer)
+  GLUtessCombineDataProc* = proc (p1: var T3dArray, p2: var T4pArray, 
+                                  p3: var T4fArray, p4: PPointer, p5: Pointer) # 
+                                                                               # 
+                                                                               # gluNurbsCallback
+  GLUnurbsErrorProc* = proc (p: TGLenum) #***           Generic constants               ****/
+
+const                         # Version
+  GLU_VERSION_1_1* = 1
+  GLU_VERSION_1_2* = 1        # Errors: (return value 0 = no error)
+  GLU_INVALID_ENUM* = 100900
+  GLU_INVALID_VALUE* = 100901
+  GLU_OUT_OF_MEMORY* = 100902
+  GLU_INCOMPATIBLE_GL_VERSION* = 100903 # StringName
+  GLU_VERSION* = 100800
+  GLU_EXTENSIONS* = 100801    # Boolean
+  GLU_TRUE* = GL_TRUE
+  GLU_FALSE* = GL_FALSE #***           Quadric constants               ****/
+                        # QuadricNormal
+  GLU_SMOOTH* = 100000
+  GLU_FLAT* = 100001
+  GLU_NONE* = 100002          # QuadricDrawStyle
+  GLU_POINT* = 100010
+  GLU_LINE* = 100011
+  GLU_FILL* = 100012
+  GLU_SILHOUETTE* = 100013    # QuadricOrientation
+  GLU_OUTSIDE* = 100020
+  GLU_INSIDE* = 100021        # Callback types:
+                              #      GLU_ERROR       = 100103;
+                              #***           Tesselation constants           ****/
+  GLU_TESS_MAX_COORD* = 1.00000e+150 # TessProperty
+  GLU_TESS_WINDING_RULE* = 100140
+  GLU_TESS_BOUNDARY_ONLY* = 100141
+  GLU_TESS_TOLERANCE* = 100142 # TessWinding
+  GLU_TESS_WINDING_ODD* = 100130
+  GLU_TESS_WINDING_NONZERO* = 100131
+  GLU_TESS_WINDING_POSITIVE* = 100132
+  GLU_TESS_WINDING_NEGATIVE* = 100133
+  GLU_TESS_WINDING_ABS_GEQ_TWO* = 100134 # TessCallback
+  GLU_TESS_BEGIN* = 100100    # void (CALLBACK*)(TGLenum    type)
+  constGLU_TESS_VERTEX* = 100101 # void (CALLBACK*)(void      *data)
+  GLU_TESS_END* = 100102      # void (CALLBACK*)(void)
+  GLU_TESS_ERROR* = 100103    # void (CALLBACK*)(TGLenum    errno)
+  GLU_TESS_EDGE_FLAG* = 100104 # void (CALLBACK*)(TGLboolean boundaryEdge)
+  GLU_TESS_COMBINE* = 100105 # void (CALLBACK*)(TGLdouble  coords[3],
+                             #                                                            void      *data[4],
+                             #                                                            TGLfloat   weight[4],
+                             #                                                            void      **dataOut) 
+  GLU_TESS_BEGIN_DATA* = 100106 # void (CALLBACK*)(TGLenum    type,
+                                #                                                            void      *polygon_data) 
+  GLU_TESS_VERTEX_DATA* = 100107 # void (CALLBACK*)(void      *data,
+                                 #                                                            void      *polygon_data) 
+  GLU_TESS_END_DATA* = 100108 # void (CALLBACK*)(void      *polygon_data)
+  GLU_TESS_ERROR_DATA* = 100109 # void (CALLBACK*)(TGLenum    errno,
+                                #                                                            void      *polygon_data) 
+  GLU_TESS_EDGE_FLAG_DATA* = 100110 # void (CALLBACK*)(TGLboolean boundaryEdge,
+                                    #                                                            void      *polygon_data) 
+  GLU_TESS_COMBINE_DATA* = 100111 # void (CALLBACK*)(TGLdouble  coords[3],
+                                  #                                                            void      *data[4],
+                                  #                                                            TGLfloat   weight[4],
+                                  #                                                            void      **dataOut,
+                                  #                                                            void      *polygon_data) 
+                                  # TessError
+  GLU_TESS_ERROR1* = 100151
+  GLU_TESS_ERROR2* = 100152
+  GLU_TESS_ERROR3* = 100153
+  GLU_TESS_ERROR4* = 100154
+  GLU_TESS_ERROR5* = 100155
+  GLU_TESS_ERROR6* = 100156
+  GLU_TESS_ERROR7* = 100157
+  GLU_TESS_ERROR8* = 100158
+  GLU_TESS_MISSING_BEGIN_POLYGON* = GLU_TESS_ERROR1
+  GLU_TESS_MISSING_BEGIN_CONTOUR* = GLU_TESS_ERROR2
+  GLU_TESS_MISSING_END_POLYGON* = GLU_TESS_ERROR3
+  GLU_TESS_MISSING_END_CONTOUR* = GLU_TESS_ERROR4
+  GLU_TESS_COORD_TOO_LARGE* = GLU_TESS_ERROR5
+  GLU_TESS_NEED_COMBINE_CALLBACK* = GLU_TESS_ERROR6 #***           NURBS constants                 ****/
+                                                    # NurbsProperty
+  GLU_AUTO_LOAD_MATRIX* = 100200
+  GLU_CULLING* = 100201
+  GLU_SAMPLING_TOLERANCE* = 100203
+  GLU_DISPLAY_MODE* = 100204
+  GLU_PARAMETRIC_TOLERANCE* = 100202
+  GLU_SAMPLING_METHOD* = 100205
+  GLU_U_STEP* = 100206
+  GLU_V_STEP* = 100207        # NurbsSampling
+  GLU_PATH_LENGTH* = 100215
+  GLU_PARAMETRIC_ERROR* = 100216
+  GLU_DOMAIN_DISTANCE* = 100217 # NurbsTrim
+  GLU_MAP1_TRIM_2* = 100210
+  GLU_MAP1_TRIM_3* = 100211   # NurbsDisplay
+                              #      GLU_FILL                = 100012;
+  GLU_OUTLINE_POLYGON* = 100240
+  GLU_OUTLINE_PATCH* = 100241 # NurbsCallback
+                              #      GLU_ERROR               = 100103;
+                              # NurbsErrors
+  GLU_NURBS_ERROR1* = 100251
+  GLU_NURBS_ERROR2* = 100252
+  GLU_NURBS_ERROR3* = 100253
+  GLU_NURBS_ERROR4* = 100254
+  GLU_NURBS_ERROR5* = 100255
+  GLU_NURBS_ERROR6* = 100256
+  GLU_NURBS_ERROR7* = 100257
+  GLU_NURBS_ERROR8* = 100258
+  GLU_NURBS_ERROR9* = 100259
+  GLU_NURBS_ERROR10* = 100260
+  GLU_NURBS_ERROR11* = 100261
+  GLU_NURBS_ERROR12* = 100262
+  GLU_NURBS_ERROR13* = 100263
+  GLU_NURBS_ERROR14* = 100264
+  GLU_NURBS_ERROR15* = 100265
+  GLU_NURBS_ERROR16* = 100266
+  GLU_NURBS_ERROR17* = 100267
+  GLU_NURBS_ERROR18* = 100268
+  GLU_NURBS_ERROR19* = 100269
+  GLU_NURBS_ERROR20* = 100270
+  GLU_NURBS_ERROR21* = 100271
+  GLU_NURBS_ERROR22* = 100272
+  GLU_NURBS_ERROR23* = 100273
+  GLU_NURBS_ERROR24* = 100274
+  GLU_NURBS_ERROR25* = 100275
+  GLU_NURBS_ERROR26* = 100276
+  GLU_NURBS_ERROR27* = 100277
+  GLU_NURBS_ERROR28* = 100278
+  GLU_NURBS_ERROR29* = 100279
+  GLU_NURBS_ERROR30* = 100280
+  GLU_NURBS_ERROR31* = 100281
+  GLU_NURBS_ERROR32* = 100282
+  GLU_NURBS_ERROR33* = 100283
+  GLU_NURBS_ERROR34* = 100284
+  GLU_NURBS_ERROR35* = 100285
+  GLU_NURBS_ERROR36* = 100286
+  GLU_NURBS_ERROR37* = 100287 #***           Backwards compatibility for old tesselator           ****/
+
+proc gluBeginPolygon*(tess: PGLUtesselator){.dynlib: dllname, 
+    importc: "gluBeginPolygon".}
+proc gluNextContour*(tess: PGLUtesselator, atype: TGLenum){.dynlib: dllname, 
+    importc: "gluNextContour".}
+proc gluEndPolygon*(tess: PGLUtesselator){.dynlib: dllname, 
+    importc: "gluEndPolygon".}
+const                         # Contours types -- obsolete!
+  GLU_CW* = 100120
+  GLU_CCW* = 100121
+  GLU_INTERIOR* = 100122
+  GLU_EXTERIOR* = 100123
+  GLU_UNKNOWN* = 100124       # Names without "TESS_" prefix
+  GLU_BEGIN* = GLU_TESS_BEGIN
+  GLU_VERTEX* = constGLU_TESS_VERTEX
+  GLU_END* = GLU_TESS_END
+  GLU_ERROR* = GLU_TESS_ERROR
+  GLU_EDGE_FLAG* = GLU_TESS_EDGE_FLAG
+
+{.pop.}
+# implementation
diff --git a/tests/manyloc/keineschweine/lib/glut.nim b/tests/manyloc/keineschweine/lib/glut.nim
new file mode 100644
index 0000000000..ff157c3273
--- /dev/null
+++ b/tests/manyloc/keineschweine/lib/glut.nim
@@ -0,0 +1,438 @@
+#
+#
+#  Adaption of the delphi3d.net OpenGL units to FreePascal
+#  Sebastian Guenther (sg@freepascal.org) in 2002
+#  These units are free to use
+#
+
+# Copyright (c) Mark J. Kilgard, 1994, 1995, 1996.
+# This program is freely distributable without licensing fees  and is
+#   provided without guarantee or warrantee expressed or  implied. This
+#   program is -not- in the public domain.
+#******************************************************************************
+# Converted to Delphi by Tom Nuydens (tom@delphi3d.net)
+#   Contributions by Igor Karpov (glygrik@hotbox.ru)
+#   For the latest updates, visit Delphi3D: http://www.delphi3d.net
+#******************************************************************************
+
+import 
+  GL
+
+when defined(windows): 
+  const 
+    dllname = "glut32.dll"
+elif defined(macosx): 
+  const 
+    dllname = "/System/Library/Frameworks/GLUT.framework/GLUT"
+else: 
+  const 
+    dllname = "libglut.so.3"
+type
+  TGlutVoidCallback* = proc (){.cdecl.}
+  TGlut1IntCallback* = proc (value: cint){.cdecl.}
+  TGlut2IntCallback* = proc (v1, v2: cint){.cdecl.}
+  TGlut3IntCallback* = proc (v1, v2, v3: cint){.cdecl.}
+  TGlut4IntCallback* = proc (v1, v2, v3, v4: cint){.cdecl.}
+  TGlut1Char2IntCallback* = proc (c: int8, v1, v2: cint){.cdecl.}
+  TGlut1UInt3IntCallback* = proc (u, v1, v2, v3: cint){.cdecl.}
+
+const 
+  GLUT_API_VERSION* = 3
+  GLUT_XLIB_IMPLEMENTATION* = 12 # Display mode bit masks.
+  GLUT_RGB* = 0
+  GLUT_RGBA* = GLUT_RGB
+  GLUT_INDEX* = 1
+  GLUT_SINGLE* = 0
+  GLUT_DOUBLE* = 2
+  GLUT_ACCUM* = 4
+  GLUT_ALPHA* = 8
+  GLUT_DEPTH* = 16
+  GLUT_STENCIL* = 32
+  GLUT_MULTISAMPLE* = 128
+  GLUT_STEREO* = 256
+  GLUT_LUMINANCE* = 512       # Mouse buttons.
+  GLUT_LEFT_BUTTON* = 0
+  GLUT_MIDDLE_BUTTON* = 1
+  GLUT_RIGHT_BUTTON* = 2      # Mouse button state.
+  GLUT_DOWN* = 0
+  GLUT_UP* = 1                # function keys
+  GLUT_KEY_F1* = 1
+  GLUT_KEY_F2* = 2
+  GLUT_KEY_F3* = 3
+  GLUT_KEY_F4* = 4
+  GLUT_KEY_F5* = 5
+  GLUT_KEY_F6* = 6
+  GLUT_KEY_F7* = 7
+  GLUT_KEY_F8* = 8
+  GLUT_KEY_F9* = 9
+  GLUT_KEY_F10* = 10
+  GLUT_KEY_F11* = 11
+  GLUT_KEY_F12* = 12          # directional keys
+  GLUT_KEY_LEFT* = 100
+  GLUT_KEY_UP* = 101
+  GLUT_KEY_RIGHT* = 102
+  GLUT_KEY_DOWN* = 103
+  GLUT_KEY_PAGE_UP* = 104
+  GLUT_KEY_PAGE_DOWN* = 105
+  GLUT_KEY_HOME* = 106
+  GLUT_KEY_END* = 107
+  GLUT_KEY_INSERT* = 108      # Entry/exit  state.
+  GLUT_LEFT* = 0
+  GLUT_ENTERED* = 1           # Menu usage state.
+  GLUT_MENU_NOT_IN_USE* = 0
+  GLUT_MENU_IN_USE* = 1       # Visibility  state.
+  GLUT_NOT_VISIBLE* = 0
+  GLUT_VISIBLE* = 1           # Window status  state.
+  GLUT_HIDDEN* = 0
+  GLUT_FULLY_RETAINED* = 1
+  GLUT_PARTIALLY_RETAINED* = 2
+  GLUT_FULLY_COVERED* = 3     # Color index component selection values.
+  GLUT_RED* = 0
+  GLUT_GREEN* = 1
+  GLUT_BLUE* = 2              # Layers for use.
+  GLUT_NORMAL* = 0
+  GLUT_OVERLAY* = 1
+
+when defined(Windows): 
+  const                       # Stroke font constants (use these in GLUT program).
+    GLUT_STROKE_ROMAN* = cast[Pointer](0)
+    GLUT_STROKE_MONO_ROMAN* = cast[Pointer](1) # Bitmap font constants (use these in GLUT program).
+    GLUT_BITMAP_9_BY_15* = cast[Pointer](2)
+    GLUT_BITMAP_8_BY_13* = cast[Pointer](3)
+    GLUT_BITMAP_TIMES_ROMAN_10* = cast[Pointer](4)
+    GLUT_BITMAP_TIMES_ROMAN_24* = cast[Pointer](5)
+    GLUT_BITMAP_HELVETICA_10* = cast[Pointer](6)
+    GLUT_BITMAP_HELVETICA_12* = cast[Pointer](7)
+    GLUT_BITMAP_HELVETICA_18* = cast[Pointer](8)
+else: 
+  var                         # Stroke font constants (use these in GLUT program).
+    GLUT_STROKE_ROMAN*: Pointer
+    GLUT_STROKE_MONO_ROMAN*: Pointer # Bitmap font constants (use these in GLUT program).
+    GLUT_BITMAP_9_BY_15*: Pointer
+    GLUT_BITMAP_8_BY_13*: Pointer
+    GLUT_BITMAP_TIMES_ROMAN_10*: Pointer
+    GLUT_BITMAP_TIMES_ROMAN_24*: Pointer
+    GLUT_BITMAP_HELVETICA_10*: Pointer
+    GLUT_BITMAP_HELVETICA_12*: Pointer
+    GLUT_BITMAP_HELVETICA_18*: Pointer
+const                         # glutGet parameters.
+  GLUT_WINDOW_X* = 100
+  GLUT_WINDOW_Y* = 101
+  GLUT_WINDOW_WIDTH* = 102
+  GLUT_WINDOW_HEIGHT* = 103
+  GLUT_WINDOW_BUFFER_SIZE* = 104
+  GLUT_WINDOW_STENCIL_SIZE* = 105
+  GLUT_WINDOW_DEPTH_SIZE* = 106
+  GLUT_WINDOW_RED_SIZE* = 107
+  GLUT_WINDOW_GREEN_SIZE* = 108
+  GLUT_WINDOW_BLUE_SIZE* = 109
+  GLUT_WINDOW_ALPHA_SIZE* = 110
+  GLUT_WINDOW_ACCUM_RED_SIZE* = 111
+  GLUT_WINDOW_ACCUM_GREEN_SIZE* = 112
+  GLUT_WINDOW_ACCUM_BLUE_SIZE* = 113
+  GLUT_WINDOW_ACCUM_ALPHA_SIZE* = 114
+  GLUT_WINDOW_DOUBLEBUFFER* = 115
+  GLUT_WINDOW_RGBA* = 116
+  GLUT_WINDOW_PARENT* = 117
+  GLUT_WINDOW_NUM_CHILDREN* = 118
+  GLUT_WINDOW_COLORMAP_SIZE* = 119
+  GLUT_WINDOW_NUM_SAMPLES* = 120
+  GLUT_WINDOW_STEREO* = 121
+  GLUT_WINDOW_CURSOR* = 122
+  GLUT_SCREEN_WIDTH* = 200
+  GLUT_SCREEN_HEIGHT* = 201
+  GLUT_SCREEN_WIDTH_MM* = 202
+  GLUT_SCREEN_HEIGHT_MM* = 203
+  GLUT_MENU_NUM_ITEMS* = 300
+  GLUT_DISPLAY_MODE_POSSIBLE* = 400
+  GLUT_INIT_WINDOW_X* = 500
+  GLUT_INIT_WINDOW_Y* = 501
+  GLUT_INIT_WINDOW_WIDTH* = 502
+  GLUT_INIT_WINDOW_HEIGHT* = 503
+  constGLUT_INIT_DISPLAY_MODE* = 504
+  GLUT_ELAPSED_TIME* = 700
+  GLUT_WINDOW_FORMAT_ID* = 123 # glutDeviceGet parameters.
+  GLUT_HAS_KEYBOARD* = 600
+  GLUT_HAS_MOUSE* = 601
+  GLUT_HAS_SPACEBALL* = 602
+  GLUT_HAS_DIAL_AND_BUTTON_BOX* = 603
+  GLUT_HAS_TABLET* = 604
+  GLUT_NUM_MOUSE_BUTTONS* = 605
+  GLUT_NUM_SPACEBALL_BUTTONS* = 606
+  GLUT_NUM_BUTTON_BOX_BUTTONS* = 607
+  GLUT_NUM_DIALS* = 608
+  GLUT_NUM_TABLET_BUTTONS* = 609
+  GLUT_DEVICE_IGNORE_KEY_REPEAT* = 610
+  GLUT_DEVICE_KEY_REPEAT* = 611
+  GLUT_HAS_JOYSTICK* = 612
+  GLUT_OWNS_JOYSTICK* = 613
+  GLUT_JOYSTICK_BUTTONS* = 614
+  GLUT_JOYSTICK_AXES* = 615
+  GLUT_JOYSTICK_POLL_RATE* = 616 # glutLayerGet parameters.
+  GLUT_OVERLAY_POSSIBLE* = 800
+  GLUT_LAYER_IN_USE* = 801
+  GLUT_HAS_OVERLAY* = 802
+  GLUT_TRANSPARENT_INDEX* = 803
+  GLUT_NORMAL_DAMAGED* = 804
+  GLUT_OVERLAY_DAMAGED* = 805 # glutVideoResizeGet parameters.
+  GLUT_VIDEO_RESIZE_POSSIBLE* = 900
+  GLUT_VIDEO_RESIZE_IN_USE* = 901
+  GLUT_VIDEO_RESIZE_X_DELTA* = 902
+  GLUT_VIDEO_RESIZE_Y_DELTA* = 903
+  GLUT_VIDEO_RESIZE_WIDTH_DELTA* = 904
+  GLUT_VIDEO_RESIZE_HEIGHT_DELTA* = 905
+  GLUT_VIDEO_RESIZE_X* = 906
+  GLUT_VIDEO_RESIZE_Y* = 907
+  GLUT_VIDEO_RESIZE_WIDTH* = 908
+  GLUT_VIDEO_RESIZE_HEIGHT* = 909 # glutGetModifiers return mask.
+  GLUT_ACTIVE_SHIFT* = 1
+  GLUT_ACTIVE_CTRL* = 2
+  GLUT_ACTIVE_ALT* = 4        # glutSetCursor parameters.
+                              # Basic arrows.
+  GLUT_CURSOR_RIGHT_ARROW* = 0
+  GLUT_CURSOR_LEFT_ARROW* = 1 # Symbolic cursor shapes.
+  GLUT_CURSOR_INFO* = 2
+  GLUT_CURSOR_DESTROY* = 3
+  GLUT_CURSOR_HELP* = 4
+  GLUT_CURSOR_CYCLE* = 5
+  GLUT_CURSOR_SPRAY* = 6
+  GLUT_CURSOR_WAIT* = 7
+  GLUT_CURSOR_TEXT* = 8
+  GLUT_CURSOR_CROSSHAIR* = 9  # Directional cursors.
+  GLUT_CURSOR_UP_DOWN* = 10
+  GLUT_CURSOR_LEFT_RIGHT* = 11 # Sizing cursors.
+  GLUT_CURSOR_TOP_SIDE* = 12
+  GLUT_CURSOR_BOTTOM_SIDE* = 13
+  GLUT_CURSOR_LEFT_SIDE* = 14
+  GLUT_CURSOR_RIGHT_SIDE* = 15
+  GLUT_CURSOR_TOP_LEFT_CORNER* = 16
+  GLUT_CURSOR_TOP_RIGHT_CORNER* = 17
+  GLUT_CURSOR_BOTTOM_RIGHT_CORNER* = 18
+  GLUT_CURSOR_BOTTOM_LEFT_CORNER* = 19 # Inherit from parent window.
+  GLUT_CURSOR_INHERIT* = 100  # Blank cursor.
+  GLUT_CURSOR_NONE* = 101     # Fullscreen crosshair (if available).
+  GLUT_CURSOR_FULL_CROSSHAIR* = 102 # GLUT device control sub-API.
+                                    # glutSetKeyRepeat modes.
+  GLUT_KEY_REPEAT_OFF* = 0
+  GLUT_KEY_REPEAT_ON* = 1
+  GLUT_KEY_REPEAT_DEFAULT* = 2 # Joystick button masks.
+  GLUT_JOYSTICK_BUTTON_A* = 1
+  GLUT_JOYSTICK_BUTTON_B* = 2
+  GLUT_JOYSTICK_BUTTON_C* = 4
+  GLUT_JOYSTICK_BUTTON_D* = 8 # GLUT game mode sub-API.
+                              # glutGameModeGet.
+  GLUT_GAME_MODE_ACTIVE* = 0
+  GLUT_GAME_MODE_POSSIBLE* = 1
+  GLUT_GAME_MODE_WIDTH* = 2
+  GLUT_GAME_MODE_HEIGHT* = 3
+  GLUT_GAME_MODE_PIXEL_DEPTH* = 4
+  GLUT_GAME_MODE_REFRESH_RATE* = 5
+  GLUT_GAME_MODE_DISPLAY_CHANGED* = 6 # GLUT initialization sub-API.
+
+proc glutInit*(argcp: ptr cint, argv: pointer){.dynlib: dllname, 
+    importc: "glutInit".}
+
+proc glutInit*() =
+  ## version that passes `argc` and `argc` implicitely.
+  var
+    cmdLine {.importc: "cmdLine".}: array[0..255, cstring]
+    cmdCount {.importc: "cmdCount".}: cint
+  glutInit(addr(cmdCount), addr(cmdLine))
+
+proc glutInitDisplayMode*(mode: int16){.dynlib: dllname, 
+                                        importc: "glutInitDisplayMode".}
+proc glutInitDisplayString*(str: cstring){.dynlib: dllname, 
+    importc: "glutInitDisplayString".}
+proc glutInitWindowPosition*(x, y: int){.dynlib: dllname, 
+    importc: "glutInitWindowPosition".}
+proc glutInitWindowSize*(width, height: int){.dynlib: dllname, 
+    importc: "glutInitWindowSize".}
+proc glutMainLoop*(){.dynlib: dllname, importc: "glutMainLoop".}
+  # GLUT window sub-API.
+proc glutCreateWindow*(title: cstring): int{.dynlib: dllname, 
+    importc: "glutCreateWindow".}
+proc glutCreateSubWindow*(win, x, y, width, height: int): int{.dynlib: dllname, 
+    importc: "glutCreateSubWindow".}
+proc glutDestroyWindow*(win: int){.dynlib: dllname, importc: "glutDestroyWindow".}
+proc glutPostRedisplay*(){.dynlib: dllname, importc: "glutPostRedisplay".}
+proc glutPostWindowRedisplay*(win: int){.dynlib: dllname, 
+    importc: "glutPostWindowRedisplay".}
+proc glutSwapBuffers*(){.dynlib: dllname, importc: "glutSwapBuffers".}
+proc glutGetWindow*(): int{.dynlib: dllname, importc: "glutGetWindow".}
+proc glutSetWindow*(win: int){.dynlib: dllname, importc: "glutSetWindow".}
+proc glutSetWindowTitle*(title: cstring){.dynlib: dllname, 
+    importc: "glutSetWindowTitle".}
+proc glutSetIconTitle*(title: cstring){.dynlib: dllname, 
+                                        importc: "glutSetIconTitle".}
+proc glutPositionWindow*(x, y: int){.dynlib: dllname, 
+                                     importc: "glutPositionWindow".}
+proc glutReshapeWindow*(width, height: int){.dynlib: dllname, 
+    importc: "glutReshapeWindow".}
+proc glutPopWindow*(){.dynlib: dllname, importc: "glutPopWindow".}
+proc glutPushWindow*(){.dynlib: dllname, importc: "glutPushWindow".}
+proc glutIconifyWindow*(){.dynlib: dllname, importc: "glutIconifyWindow".}
+proc glutShowWindow*(){.dynlib: dllname, importc: "glutShowWindow".}
+proc glutHideWindow*(){.dynlib: dllname, importc: "glutHideWindow".}
+proc glutFullScreen*(){.dynlib: dllname, importc: "glutFullScreen".}
+proc glutSetCursor*(cursor: int){.dynlib: dllname, importc: "glutSetCursor".}
+proc glutWarpPointer*(x, y: int){.dynlib: dllname, importc: "glutWarpPointer".}
+  # GLUT overlay sub-API.
+proc glutEstablishOverlay*(){.dynlib: dllname, importc: "glutEstablishOverlay".}
+proc glutRemoveOverlay*(){.dynlib: dllname, importc: "glutRemoveOverlay".}
+proc glutUseLayer*(layer: TGLenum){.dynlib: dllname, importc: "glutUseLayer".}
+proc glutPostOverlayRedisplay*(){.dynlib: dllname, 
+                                  importc: "glutPostOverlayRedisplay".}
+proc glutPostWindowOverlayRedisplay*(win: int){.dynlib: dllname, 
+    importc: "glutPostWindowOverlayRedisplay".}
+proc glutShowOverlay*(){.dynlib: dllname, importc: "glutShowOverlay".}
+proc glutHideOverlay*(){.dynlib: dllname, importc: "glutHideOverlay".}
+  # GLUT menu sub-API.
+proc glutCreateMenu*(callback: TGlut1IntCallback): int{.dynlib: dllname, 
+    importc: "glutCreateMenu".}
+proc glutDestroyMenu*(menu: int){.dynlib: dllname, importc: "glutDestroyMenu".}
+proc glutGetMenu*(): int{.dynlib: dllname, importc: "glutGetMenu".}
+proc glutSetMenu*(menu: int){.dynlib: dllname, importc: "glutSetMenu".}
+proc glutAddMenuEntry*(caption: cstring, value: int){.dynlib: dllname, 
+    importc: "glutAddMenuEntry".}
+proc glutAddSubMenu*(caption: cstring, submenu: int){.dynlib: dllname, 
+    importc: "glutAddSubMenu".}
+proc glutChangeToMenuEntry*(item: int, caption: cstring, value: int){.
+    dynlib: dllname, importc: "glutChangeToMenuEntry".}
+proc glutChangeToSubMenu*(item: int, caption: cstring, submenu: int){.
+    dynlib: dllname, importc: "glutChangeToSubMenu".}
+proc glutRemoveMenuItem*(item: int){.dynlib: dllname, 
+                                     importc: "glutRemoveMenuItem".}
+proc glutAttachMenu*(button: int){.dynlib: dllname, importc: "glutAttachMenu".}
+proc glutDetachMenu*(button: int){.dynlib: dllname, importc: "glutDetachMenu".}
+  # GLUT window callback sub-API.
+proc glutDisplayFunc*(f: TGlutVoidCallback){.dynlib: dllname, 
+    importc: "glutDisplayFunc".}
+proc glutReshapeFunc*(f: TGlut2IntCallback){.dynlib: dllname, 
+    importc: "glutReshapeFunc".}
+proc glutKeyboardFunc*(f: TGlut1Char2IntCallback){.dynlib: dllname, 
+    importc: "glutKeyboardFunc".}
+proc glutMouseFunc*(f: TGlut4IntCallback){.dynlib: dllname, 
+    importc: "glutMouseFunc".}
+proc glutMotionFunc*(f: TGlut2IntCallback){.dynlib: dllname, 
+    importc: "glutMotionFunc".}
+proc glutPassiveMotionFunc*(f: TGlut2IntCallback){.dynlib: dllname, 
+    importc: "glutPassiveMotionFunc".}
+proc glutEntryFunc*(f: TGlut1IntCallback){.dynlib: dllname, 
+    importc: "glutEntryFunc".}
+proc glutVisibilityFunc*(f: TGlut1IntCallback){.dynlib: dllname, 
+    importc: "glutVisibilityFunc".}
+proc glutIdleFunc*(f: TGlutVoidCallback){.dynlib: dllname, 
+    importc: "glutIdleFunc".}
+proc glutTimerFunc*(millis: int16, f: TGlut1IntCallback, value: int){.
+    dynlib: dllname, importc: "glutTimerFunc".}
+proc glutMenuStateFunc*(f: TGlut1IntCallback){.dynlib: dllname, 
+    importc: "glutMenuStateFunc".}
+proc glutSpecialFunc*(f: TGlut3IntCallback){.dynlib: dllname, 
+    importc: "glutSpecialFunc".}
+proc glutSpaceballMotionFunc*(f: TGlut3IntCallback){.dynlib: dllname, 
+    importc: "glutSpaceballMotionFunc".}
+proc glutSpaceballRotateFunc*(f: TGlut3IntCallback){.dynlib: dllname, 
+    importc: "glutSpaceballRotateFunc".}
+proc glutSpaceballButtonFunc*(f: TGlut2IntCallback){.dynlib: dllname, 
+    importc: "glutSpaceballButtonFunc".}
+proc glutButtonBoxFunc*(f: TGlut2IntCallback){.dynlib: dllname, 
+    importc: "glutButtonBoxFunc".}
+proc glutDialsFunc*(f: TGlut2IntCallback){.dynlib: dllname, 
+    importc: "glutDialsFunc".}
+proc glutTabletMotionFunc*(f: TGlut2IntCallback){.dynlib: dllname, 
+    importc: "glutTabletMotionFunc".}
+proc glutTabletButtonFunc*(f: TGlut4IntCallback){.dynlib: dllname, 
+    importc: "glutTabletButtonFunc".}
+proc glutMenuStatusFunc*(f: TGlut3IntCallback){.dynlib: dllname, 
+    importc: "glutMenuStatusFunc".}
+proc glutOverlayDisplayFunc*(f: TGlutVoidCallback){.dynlib: dllname, 
+    importc: "glutOverlayDisplayFunc".}
+proc glutWindowStatusFunc*(f: TGlut1IntCallback){.dynlib: dllname, 
+    importc: "glutWindowStatusFunc".}
+proc glutKeyboardUpFunc*(f: TGlut1Char2IntCallback){.dynlib: dllname, 
+    importc: "glutKeyboardUpFunc".}
+proc glutSpecialUpFunc*(f: TGlut3IntCallback){.dynlib: dllname, 
+    importc: "glutSpecialUpFunc".}
+proc glutJoystickFunc*(f: TGlut1UInt3IntCallback, pollInterval: int){.
+    dynlib: dllname, importc: "glutJoystickFunc".}
+  # GLUT color index sub-API.
+proc glutSetColor*(cell: int, red, green, blue: TGLfloat){.dynlib: dllname, 
+    importc: "glutSetColor".}
+proc glutGetColor*(ndx, component: int): TGLfloat{.dynlib: dllname, 
+    importc: "glutGetColor".}
+proc glutCopyColormap*(win: int){.dynlib: dllname, importc: "glutCopyColormap".}
+  # GLUT state retrieval sub-API.
+proc glutGet*(t: TGLenum): int{.dynlib: dllname, importc: "glutGet".}
+proc glutDeviceGet*(t: TGLenum): int{.dynlib: dllname, importc: "glutDeviceGet".}
+  # GLUT extension support sub-API
+proc glutExtensionSupported*(name: cstring): int{.dynlib: dllname, 
+    importc: "glutExtensionSupported".}
+proc glutGetModifiers*(): int{.dynlib: dllname, importc: "glutGetModifiers".}
+proc glutLayerGet*(t: TGLenum): int{.dynlib: dllname, importc: "glutLayerGet".}
+  # GLUT font sub-API
+proc glutBitmapCharacter*(font: pointer, character: int){.dynlib: dllname, 
+    importc: "glutBitmapCharacter".}
+proc glutBitmapWidth*(font: pointer, character: int): int{.dynlib: dllname, 
+    importc: "glutBitmapWidth".}
+proc glutStrokeCharacter*(font: pointer, character: int){.dynlib: dllname, 
+    importc: "glutStrokeCharacter".}
+proc glutStrokeWidth*(font: pointer, character: int): int{.dynlib: dllname, 
+    importc: "glutStrokeWidth".}
+proc glutBitmapLength*(font: pointer, str: cstring): int{.dynlib: dllname, 
+    importc: "glutBitmapLength".}
+proc glutStrokeLength*(font: pointer, str: cstring): int{.dynlib: dllname, 
+    importc: "glutStrokeLength".}
+  # GLUT pre-built models sub-API
+proc glutWireSphere*(radius: TGLdouble, slices, stacks: TGLint){.
+    dynlib: dllname, importc: "glutWireSphere".}
+proc glutSolidSphere*(radius: TGLdouble, slices, stacks: TGLint){.
+    dynlib: dllname, importc: "glutSolidSphere".}
+proc glutWireCone*(base, height: TGLdouble, slices, stacks: TGLint){.
+    dynlib: dllname, importc: "glutWireCone".}
+proc glutSolidCone*(base, height: TGLdouble, slices, stacks: TGLint){.
+    dynlib: dllname, importc: "glutSolidCone".}
+proc glutWireCube*(size: TGLdouble){.dynlib: dllname, importc: "glutWireCube".}
+proc glutSolidCube*(size: TGLdouble){.dynlib: dllname, importc: "glutSolidCube".}
+proc glutWireTorus*(innerRadius, outerRadius: TGLdouble, sides, rings: TGLint){.
+    dynlib: dllname, importc: "glutWireTorus".}
+proc glutSolidTorus*(innerRadius, outerRadius: TGLdouble, sides, rings: TGLint){.
+    dynlib: dllname, importc: "glutSolidTorus".}
+proc glutWireDodecahedron*(){.dynlib: dllname, importc: "glutWireDodecahedron".}
+proc glutSolidDodecahedron*(){.dynlib: dllname, importc: "glutSolidDodecahedron".}
+proc glutWireTeapot*(size: TGLdouble){.dynlib: dllname, 
+                                       importc: "glutWireTeapot".}
+proc glutSolidTeapot*(size: TGLdouble){.dynlib: dllname, 
+                                        importc: "glutSolidTeapot".}
+proc glutWireOctahedron*(){.dynlib: dllname, importc: "glutWireOctahedron".}
+proc glutSolidOctahedron*(){.dynlib: dllname, importc: "glutSolidOctahedron".}
+proc glutWireTetrahedron*(){.dynlib: dllname, importc: "glutWireTetrahedron".}
+proc glutSolidTetrahedron*(){.dynlib: dllname, importc: "glutSolidTetrahedron".}
+proc glutWireIcosahedron*(){.dynlib: dllname, importc: "glutWireIcosahedron".}
+proc glutSolidIcosahedron*(){.dynlib: dllname, importc: "glutSolidIcosahedron".}
+  # GLUT video resize sub-API.
+proc glutVideoResizeGet*(param: TGLenum): int{.dynlib: dllname, 
+    importc: "glutVideoResizeGet".}
+proc glutSetupVideoResizing*(){.dynlib: dllname, 
+                                importc: "glutSetupVideoResizing".}
+proc glutStopVideoResizing*(){.dynlib: dllname, importc: "glutStopVideoResizing".}
+proc glutVideoResize*(x, y, width, height: int){.dynlib: dllname, 
+    importc: "glutVideoResize".}
+proc glutVideoPan*(x, y, width, height: int){.dynlib: dllname, 
+    importc: "glutVideoPan".}
+  # GLUT debugging sub-API.
+proc glutReportErrors*(){.dynlib: dllname, importc: "glutReportErrors".}
+  # GLUT device control sub-API.
+proc glutIgnoreKeyRepeat*(ignore: int){.dynlib: dllname, 
+                                        importc: "glutIgnoreKeyRepeat".}
+proc glutSetKeyRepeat*(repeatMode: int){.dynlib: dllname, 
+    importc: "glutSetKeyRepeat".}
+proc glutForceJoystickFunc*(){.dynlib: dllname, importc: "glutForceJoystickFunc".}
+  # GLUT game mode sub-API.
+  #example glutGameModeString('1280x1024:32@75');
+proc glutGameModeString*(AString: cstring){.dynlib: dllname, 
+    importc: "glutGameModeString".}
+proc glutEnterGameMode*(): int{.dynlib: dllname, importc: "glutEnterGameMode".}
+proc glutLeaveGameMode*(){.dynlib: dllname, importc: "glutLeaveGameMode".}
+proc glutGameModeGet*(mode: TGLenum): int{.dynlib: dllname, 
+    importc: "glutGameModeGet".}
+# implementation
diff --git a/tests/manyloc/keineschweine/lib/glx.nim b/tests/manyloc/keineschweine/lib/glx.nim
new file mode 100644
index 0000000000..76c052d70a
--- /dev/null
+++ b/tests/manyloc/keineschweine/lib/glx.nim
@@ -0,0 +1,153 @@
+#
+#
+#  Translation of the Mesa GLX headers for FreePascal
+#  Copyright (C) 1999 Sebastian Guenther
+#
+#
+#  Mesa 3-D graphics library
+#  Version:  3.0
+#  Copyright (C) 1995-1998  Brian Paul
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Library General Public
+#  License as published by the Free Software Foundation; either
+#  version 2 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Library General Public License for more details.
+#
+#  You should have received a copy of the GNU Library General Public
+#  License along with this library; if not, write to the Free
+#  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import 
+  X, XLib, XUtil, gl
+
+when defined(windows): 
+  const 
+    dllname = "GL.dll"
+elif defined(macosx): 
+  const 
+    dllname = "/usr/X11R6/lib/libGL.dylib"
+else: 
+  const 
+    dllname = "libGL.so"
+const 
+  GLX_USE_GL* = 1
+  GLX_BUFFER_SIZE* = 2
+  GLX_LEVEL* = 3
+  GLX_RGBA* = 4
+  GLX_DOUBLEBUFFER* = 5
+  GLX_STEREO* = 6
+  GLX_AUX_BUFFERS* = 7
+  GLX_RED_SIZE* = 8
+  GLX_GREEN_SIZE* = 9
+  GLX_BLUE_SIZE* = 10
+  GLX_ALPHA_SIZE* = 11
+  GLX_DEPTH_SIZE* = 12
+  GLX_STENCIL_SIZE* = 13
+  GLX_ACCUM_RED_SIZE* = 14
+  GLX_ACCUM_GREEN_SIZE* = 15
+  GLX_ACCUM_BLUE_SIZE* = 16
+  GLX_ACCUM_ALPHA_SIZE* = 17  # GLX_EXT_visual_info extension
+  GLX_X_VISUAL_TYPE_EXT* = 0x00000022
+  GLX_TRANSPARENT_TYPE_EXT* = 0x00000023
+  GLX_TRANSPARENT_INDEX_VALUE_EXT* = 0x00000024
+  GLX_TRANSPARENT_RED_VALUE_EXT* = 0x00000025
+  GLX_TRANSPARENT_GREEN_VALUE_EXT* = 0x00000026
+  GLX_TRANSPARENT_BLUE_VALUE_EXT* = 0x00000027
+  GLX_TRANSPARENT_ALPHA_VALUE_EXT* = 0x00000028 # Error codes returned by glXGetConfig:
+  GLX_BAD_SCREEN* = 1
+  GLX_BAD_ATTRIBUTE* = 2
+  GLX_NO_EXTENSION* = 3
+  GLX_BAD_VISUAL* = 4
+  GLX_BAD_CONTEXT* = 5
+  GLX_BAD_VALUE* = 6
+  GLX_BAD_ENUM* = 7           # GLX 1.1 and later:
+  GLX_VENDOR* = 1
+  GLX_VERSION* = 2
+  GLX_EXTENSIONS* = 3         # GLX_visual_info extension
+  GLX_TRUE_COLOR_EXT* = 0x00008002
+  GLX_DIRECT_COLOR_EXT* = 0x00008003
+  GLX_PSEUDO_COLOR_EXT* = 0x00008004
+  GLX_STATIC_COLOR_EXT* = 0x00008005
+  GLX_GRAY_SCALE_EXT* = 0x00008006
+  GLX_STATIC_GRAY_EXT* = 0x00008007
+  GLX_NONE_EXT* = 0x00008000
+  GLX_TRANSPARENT_RGB_EXT* = 0x00008008
+  GLX_TRANSPARENT_INDEX_EXT* = 0x00008009
+
+type                          # From XLib:
+  XPixmap* = TXID
+  XFont* = TXID
+  XColormap* = TXID
+  GLXContext* = Pointer
+  GLXPixmap* = TXID
+  GLXDrawable* = TXID
+  GLXContextID* = TXID
+  TXPixmap* = XPixmap
+  TXFont* = XFont
+  TXColormap* = XColormap
+  TGLXContext* = GLXContext
+  TGLXPixmap* = GLXPixmap
+  TGLXDrawable* = GLXDrawable
+  TGLXContextID* = GLXContextID
+
+proc glXChooseVisual*(dpy: PDisplay, screen: int, attribList: ptr int32): PXVisualInfo{.
+    cdecl, dynlib: dllname, importc: "glXChooseVisual".}
+proc glXCreateContext*(dpy: PDisplay, vis: PXVisualInfo, shareList: GLXContext, 
+                       direct: bool): GLXContext{.cdecl, dynlib: dllname, 
+    importc: "glXCreateContext".}
+proc glXDestroyContext*(dpy: PDisplay, ctx: GLXContext){.cdecl, dynlib: dllname, 
+    importc: "glXDestroyContext".}
+proc glXMakeCurrent*(dpy: PDisplay, drawable: GLXDrawable, ctx: GLXContext): bool{.
+    cdecl, dynlib: dllname, importc: "glXMakeCurrent".}
+proc glXCopyContext*(dpy: PDisplay, src, dst: GLXContext, mask: int32){.cdecl, 
+    dynlib: dllname, importc: "glXCopyContext".}
+proc glXSwapBuffers*(dpy: PDisplay, drawable: GLXDrawable){.cdecl, 
+    dynlib: dllname, importc: "glXSwapBuffers".}
+proc glXCreateGLXPixmap*(dpy: PDisplay, visual: PXVisualInfo, pixmap: XPixmap): GLXPixmap{.
+    cdecl, dynlib: dllname, importc: "glXCreateGLXPixmap".}
+proc glXDestroyGLXPixmap*(dpy: PDisplay, pixmap: GLXPixmap){.cdecl, 
+    dynlib: dllname, importc: "glXDestroyGLXPixmap".}
+proc glXQueryExtension*(dpy: PDisplay, errorb, event: var int): bool{.cdecl, 
+    dynlib: dllname, importc: "glXQueryExtension".}
+proc glXQueryVersion*(dpy: PDisplay, maj, min: var int): bool{.cdecl, 
+    dynlib: dllname, importc: "glXQueryVersion".}
+proc glXIsDirect*(dpy: PDisplay, ctx: GLXContext): bool{.cdecl, dynlib: dllname, 
+    importc: "glXIsDirect".}
+proc glXGetConfig*(dpy: PDisplay, visual: PXVisualInfo, attrib: int, 
+                   value: var int): int{.cdecl, dynlib: dllname, 
+    importc: "glXGetConfig".}
+proc glXGetCurrentContext*(): GLXContext{.cdecl, dynlib: dllname, 
+    importc: "glXGetCurrentContext".}
+proc glXGetCurrentDrawable*(): GLXDrawable{.cdecl, dynlib: dllname, 
+    importc: "glXGetCurrentDrawable".}
+proc glXWaitGL*(){.cdecl, dynlib: dllname, importc: "glXWaitGL".}
+proc glXWaitX*(){.cdecl, dynlib: dllname, importc: "glXWaitX".}
+proc glXUseXFont*(font: XFont, first, count, list: int){.cdecl, dynlib: dllname, 
+    importc: "glXUseXFont".}
+  # GLX 1.1 and later
+proc glXQueryExtensionsString*(dpy: PDisplay, screen: int): cstring{.cdecl, 
+    dynlib: dllname, importc: "glXQueryExtensionsString".}
+proc glXQueryServerString*(dpy: PDisplay, screen, name: int): cstring{.cdecl, 
+    dynlib: dllname, importc: "glXQueryServerString".}
+proc glXGetClientString*(dpy: PDisplay, name: int): cstring{.cdecl, 
+    dynlib: dllname, importc: "glXGetClientString".}
+  # Mesa GLX Extensions
+proc glXCreateGLXPixmapMESA*(dpy: PDisplay, visual: PXVisualInfo, 
+                             pixmap: XPixmap, cmap: XColormap): GLXPixmap{.
+    cdecl, dynlib: dllname, importc: "glXCreateGLXPixmapMESA".}
+proc glXReleaseBufferMESA*(dpy: PDisplay, d: GLXDrawable): bool{.cdecl, 
+    dynlib: dllname, importc: "glXReleaseBufferMESA".}
+proc glXCopySubBufferMESA*(dpy: PDisplay, drawbale: GLXDrawable, 
+                           x, y, width, height: int){.cdecl, dynlib: dllname, 
+    importc: "glXCopySubBufferMESA".}
+proc glXGetVideoSyncSGI*(counter: var int32): int{.cdecl, dynlib: dllname, 
+    importc: "glXGetVideoSyncSGI".}
+proc glXWaitVideoSyncSGI*(divisor, remainder: int, count: var int32): int{.
+    cdecl, dynlib: dllname, importc: "glXWaitVideoSyncSGI".}
+# implementation
diff --git a/tests/manyloc/keineschweine/lib/wingl.nim b/tests/manyloc/keineschweine/lib/wingl.nim
new file mode 100644
index 0000000000..7ed78f9707
--- /dev/null
+++ b/tests/manyloc/keineschweine/lib/wingl.nim
@@ -0,0 +1,368 @@
+import 
+  gl, windows
+
+proc wglGetExtensionsStringARB*(hdc: HDC): cstring{.dynlib: dllname, 
+    importc: "wglGetExtensionsStringARB".}
+const 
+  WGL_FRONT_COLOR_BUFFER_BIT_ARB* = 0x00000001
+  WGL_BACK_COLOR_BUFFER_BIT_ARB* = 0x00000002
+  WGL_DEPTH_BUFFER_BIT_ARB* = 0x00000004
+  WGL_STENCIL_BUFFER_BIT_ARB* = 0x00000008
+
+proc WinChoosePixelFormat*(DC: HDC, p2: PPixelFormatDescriptor): int{.
+    dynlib: "gdi32", importc: "ChoosePixelFormat".}
+proc wglCreateBufferRegionARB*(hDC: HDC, iLayerPlane: TGLint, uType: TGLuint): THandle{.
+    dynlib: dllname, importc: "wglCreateBufferRegionARB".}
+proc wglDeleteBufferRegionARB*(hRegion: THandle){.dynlib: dllname, 
+    importc: "wglDeleteBufferRegionARB".}
+proc wglSaveBufferRegionARB*(hRegion: THandle, x: TGLint, y: TGLint, 
+                             width: TGLint, height: TGLint): BOOL{.
+    dynlib: dllname, importc: "wglSaveBufferRegionARB".}
+proc wglRestoreBufferRegionARB*(hRegion: THandle, x: TGLint, y: TGLint, 
+                                width: TGLint, height: TGLint, xSrc: TGLint, 
+                                ySrc: TGLint): BOOL{.dynlib: dllname, 
+    importc: "wglRestoreBufferRegionARB".}
+proc wglAllocateMemoryNV*(size: TGLsizei, readFrequency: TGLfloat, 
+                          writeFrequency: TGLfloat, priority: TGLfloat): PGLvoid{.
+    dynlib: dllname, importc: "wglAllocateMemoryNV".}
+proc wglFreeMemoryNV*(pointer: PGLvoid){.dynlib: dllname, 
+    importc: "wglFreeMemoryNV".}
+const 
+  WGL_IMAGE_BUFFER_MIN_ACCESS_I3D* = 0x00000001
+  WGL_IMAGE_BUFFER_LOCK_I3D* = 0x00000002
+
+proc wglCreateImageBufferI3D*(hDC: HDC, dwSize: DWORD, uFlags: UINT): PGLvoid{.
+    dynlib: dllname, importc: "wglCreateImageBufferI3D".}
+proc wglDestroyImageBufferI3D*(hDC: HDC, pAddress: PGLvoid): BOOL{.
+    dynlib: dllname, importc: "wglDestroyImageBufferI3D".}
+proc wglAssociateImageBufferEventsI3D*(hdc: HDC, pEvent: PHandle, 
+                                       pAddress: PGLvoid, pSize: PDWORD, 
+                                       count: UINT): BOOL{.dynlib: dllname, 
+    importc: "wglAssociateImageBufferEventsI3D".}
+proc wglReleaseImageBufferEventsI3D*(hdc: HDC, pAddress: PGLvoid, count: UINT): BOOL{.
+    dynlib: dllname, importc: "wglReleaseImageBufferEventsI3D".}
+proc wglEnableFrameLockI3D*(): BOOL{.dynlib: dllname, 
+                                     importc: "wglEnableFrameLockI3D".}
+proc wglDisableFrameLockI3D*(): BOOL{.dynlib: dllname, 
+                                      importc: "wglDisableFrameLockI3D".}
+proc wglIsEnabledFrameLockI3D*(pFlag: PBOOL): BOOL{.dynlib: dllname, 
+    importc: "wglIsEnabledFrameLockI3D".}
+proc wglQueryFrameLockMasterI3D*(pFlag: PBOOL): BOOL{.dynlib: dllname, 
+    importc: "wglQueryFrameLockMasterI3D".}
+proc wglGetFrameUsageI3D*(pUsage: PGLfloat): BOOL{.dynlib: dllname, 
+    importc: "wglGetFrameUsageI3D".}
+proc wglBeginFrameTrackingI3D*(): BOOL{.dynlib: dllname, 
+                                        importc: "wglBeginFrameTrackingI3D".}
+proc wglEndFrameTrackingI3D*(): BOOL{.dynlib: dllname, 
+                                      importc: "wglEndFrameTrackingI3D".}
+proc wglQueryFrameTrackingI3D*(pFrameCount: PDWORD, pMissedFrames: PDWORD, 
+                               pLastMissedUsage: PGLfloat): BOOL{.
+    dynlib: dllname, importc: "wglQueryFrameTrackingI3D".}
+const 
+  WGL_NUMBER_PIXEL_FORMATS_ARB* = 0x00002000
+  WGL_DRAW_TO_WINDOW_ARB* = 0x00002001
+  WGL_DRAW_TO_BITMAP_ARB* = 0x00002002
+  WGL_ACCELERATION_ARB* = 0x00002003
+  WGL_NEED_PALETTE_ARB* = 0x00002004
+  WGL_NEED_SYSTEM_PALETTE_ARB* = 0x00002005
+  WGL_SWAP_LAYER_BUFFERS_ARB* = 0x00002006
+  WGL_SWAP_METHOD_ARB* = 0x00002007
+  WGL_NUMBER_OVERLAYS_ARB* = 0x00002008
+  WGL_NUMBER_UNDERLAYS_ARB* = 0x00002009
+  WGL_TRANSPARENT_ARB* = 0x0000200A
+  WGL_TRANSPARENT_RED_VALUE_ARB* = 0x00002037
+  WGL_TRANSPARENT_GREEN_VALUE_ARB* = 0x00002038
+  WGL_TRANSPARENT_BLUE_VALUE_ARB* = 0x00002039
+  WGL_TRANSPARENT_ALPHA_VALUE_ARB* = 0x0000203A
+  WGL_TRANSPARENT_INDEX_VALUE_ARB* = 0x0000203B
+  WGL_SHARE_DEPTH_ARB* = 0x0000200C
+  WGL_SHARE_STENCIL_ARB* = 0x0000200D
+  WGL_SHARE_ACCUM_ARB* = 0x0000200E
+  WGL_SUPPORT_GDI_ARB* = 0x0000200F
+  WGL_SUPPORT_OPENGL_ARB* = 0x00002010
+  WGL_DOUBLE_BUFFER_ARB* = 0x00002011
+  WGL_STEREO_ARB* = 0x00002012
+  WGL_PIXEL_TYPE_ARB* = 0x00002013
+  WGL_COLOR_BITS_ARB* = 0x00002014
+  WGL_RED_BITS_ARB* = 0x00002015
+  WGL_RED_SHIFT_ARB* = 0x00002016
+  WGL_GREEN_BITS_ARB* = 0x00002017
+  WGL_GREEN_SHIFT_ARB* = 0x00002018
+  WGL_BLUE_BITS_ARB* = 0x00002019
+  WGL_BLUE_SHIFT_ARB* = 0x0000201A
+  WGL_ALPHA_BITS_ARB* = 0x0000201B
+  WGL_ALPHA_SHIFT_ARB* = 0x0000201C
+  WGL_ACCUM_BITS_ARB* = 0x0000201D
+  WGL_ACCUM_RED_BITS_ARB* = 0x0000201E
+  WGL_ACCUM_GREEN_BITS_ARB* = 0x0000201F
+  WGL_ACCUM_BLUE_BITS_ARB* = 0x00002020
+  WGL_ACCUM_ALPHA_BITS_ARB* = 0x00002021
+  WGL_DEPTH_BITS_ARB* = 0x00002022
+  WGL_STENCIL_BITS_ARB* = 0x00002023
+  WGL_AUX_BUFFERS_ARB* = 0x00002024
+  WGL_NO_ACCELERATION_ARB* = 0x00002025
+  WGL_GENERIC_ACCELERATION_ARB* = 0x00002026
+  WGL_FULL_ACCELERATION_ARB* = 0x00002027
+  WGL_SWAP_EXCHANGE_ARB* = 0x00002028
+  WGL_SWAP_COPY_ARB* = 0x00002029
+  WGL_SWAP_UNDEFINED_ARB* = 0x0000202A
+  WGL_TYPE_RGBA_ARB* = 0x0000202B
+  WGL_TYPE_COLORINDEX_ARB* = 0x0000202C
+
+proc wglGetPixelFormatAttribivARB*(hdc: HDC, iPixelFormat: TGLint, 
+                                   iLayerPlane: TGLint, nAttributes: TGLuint, 
+                                   piAttributes: PGLint, piValues: PGLint): BOOL{.
+    dynlib: dllname, importc: "wglGetPixelFormatAttribivARB".}
+proc wglGetPixelFormatAttribfvARB*(hdc: HDC, iPixelFormat: TGLint, 
+                                   iLayerPlane: TGLint, nAttributes: TGLuint, 
+                                   piAttributes: PGLint, pfValues: PGLfloat): BOOL{.
+    dynlib: dllname, importc: "wglGetPixelFormatAttribfvARB".}
+proc wglChoosePixelFormatARB*(hdc: HDC, piAttribIList: PGLint, 
+                              pfAttribFList: PGLfloat, nMaxFormats: TGLuint, 
+                              piFormats: PGLint, nNumFormats: PGLuint): BOOL{.
+    dynlib: dllname, importc: "wglChoosePixelFormatARB".}
+const 
+  WGL_ERROR_INVALID_PIXEL_TYPE_ARB* = 0x00002043
+  WGL_ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB* = 0x00002054
+
+proc wglMakeContextCurrentARB*(hDrawDC: HDC, hReadDC: HDC, hglrc: HGLRC): BOOL{.
+    dynlib: dllname, importc: "wglMakeContextCurrentARB".}
+proc wglGetCurrentReadDCARB*(): HDC{.dynlib: dllname, 
+                                     importc: "wglGetCurrentReadDCARB".}
+const 
+  WGL_DRAW_TO_PBUFFER_ARB* = 0x0000202D # WGL_DRAW_TO_PBUFFER_ARB  { already defined }
+  WGL_MAX_PBUFFER_PIXELS_ARB* = 0x0000202E
+  WGL_MAX_PBUFFER_WIDTH_ARB* = 0x0000202F
+  WGL_MAX_PBUFFER_HEIGHT_ARB* = 0x00002030
+  WGL_PBUFFER_LARGEST_ARB* = 0x00002033
+  WGL_PBUFFER_WIDTH_ARB* = 0x00002034
+  WGL_PBUFFER_HEIGHT_ARB* = 0x00002035
+  WGL_PBUFFER_LOST_ARB* = 0x00002036
+
+proc wglCreatePbufferARB*(hDC: HDC, iPixelFormat: TGLint, iWidth: TGLint, 
+                          iHeight: TGLint, piAttribList: PGLint): THandle{.
+    dynlib: dllname, importc: "wglCreatePbufferARB".}
+proc wglGetPbufferDCARB*(hPbuffer: THandle): HDC{.dynlib: dllname, 
+    importc: "wglGetPbufferDCARB".}
+proc wglReleasePbufferDCARB*(hPbuffer: THandle, hDC: HDC): TGLint{.
+    dynlib: dllname, importc: "wglReleasePbufferDCARB".}
+proc wglDestroyPbufferARB*(hPbuffer: THandle): BOOL{.dynlib: dllname, 
+    importc: "wglDestroyPbufferARB".}
+proc wglQueryPbufferARB*(hPbuffer: THandle, iAttribute: TGLint, piValue: PGLint): BOOL{.
+    dynlib: dllname, importc: "wglQueryPbufferARB".}
+proc wglSwapIntervalEXT*(interval: TGLint): BOOL{.dynlib: dllname, 
+    importc: "wglSwapIntervalEXT".}
+proc wglGetSwapIntervalEXT*(): TGLint{.dynlib: dllname, 
+                                       importc: "wglGetSwapIntervalEXT".}
+const 
+  WGL_BIND_TO_TEXTURE_RGB_ARB* = 0x00002070
+  WGL_BIND_TO_TEXTURE_RGBA_ARB* = 0x00002071
+  WGL_TEXTURE_FORMAT_ARB* = 0x00002072
+  WGL_TEXTURE_TARGET_ARB* = 0x00002073
+  WGL_MIPMAP_TEXTURE_ARB* = 0x00002074
+  WGL_TEXTURE_RGB_ARB* = 0x00002075
+  WGL_TEXTURE_RGBA_ARB* = 0x00002076
+  WGL_NO_TEXTURE_ARB* = 0x00002077
+  WGL_TEXTURE_CUBE_MAP_ARB* = 0x00002078
+  WGL_TEXTURE_1D_ARB* = 0x00002079
+  WGL_TEXTURE_2D_ARB* = 0x0000207A # WGL_NO_TEXTURE_ARB  { already defined }
+  WGL_MIPMAP_LEVEL_ARB* = 0x0000207B
+  WGL_CUBE_MAP_FACE_ARB* = 0x0000207C
+  WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB* = 0x0000207D
+  WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB* = 0x0000207E
+  WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB* = 0x0000207F
+  WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB* = 0x00002080
+  WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB* = 0x00002081
+  WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB* = 0x00002082
+  WGL_FRONT_LEFT_ARB* = 0x00002083
+  WGL_FRONT_RIGHT_ARB* = 0x00002084
+  WGL_BACK_LEFT_ARB* = 0x00002085
+  WGL_BACK_RIGHT_ARB* = 0x00002086
+  WGL_AUX0_ARB* = 0x00002087
+  WGL_AUX1_ARB* = 0x00002088
+  WGL_AUX2_ARB* = 0x00002089
+  WGL_AUX3_ARB* = 0x0000208A
+  WGL_AUX4_ARB* = 0x0000208B
+  WGL_AUX5_ARB* = 0x0000208C
+  WGL_AUX6_ARB* = 0x0000208D
+  WGL_AUX7_ARB* = 0x0000208E
+  WGL_AUX8_ARB* = 0x0000208F
+  WGL_AUX9_ARB* = 0x00002090
+
+proc wglBindTexImageARB*(hPbuffer: THandle, iBuffer: TGLint): BOOL{.
+    dynlib: dllname, importc: "wglBindTexImageARB".}
+proc wglReleaseTexImageARB*(hPbuffer: THandle, iBuffer: TGLint): BOOL{.
+    dynlib: dllname, importc: "wglReleaseTexImageARB".}
+proc wglSetPbufferAttribARB*(hPbuffer: THandle, piAttribList: PGLint): BOOL{.
+    dynlib: dllname, importc: "wglSetPbufferAttribARB".}
+proc wglGetExtensionsStringEXT*(): cstring{.dynlib: dllname, 
+    importc: "wglGetExtensionsStringEXT".}
+proc wglMakeContextCurrentEXT*(hDrawDC: HDC, hReadDC: HDC, hglrc: HGLRC): BOOL{.
+    dynlib: dllname, importc: "wglMakeContextCurrentEXT".}
+proc wglGetCurrentReadDCEXT*(): HDC{.dynlib: dllname, 
+                                     importc: "wglGetCurrentReadDCEXT".}
+const 
+  WGL_DRAW_TO_PBUFFER_EXT* = 0x0000202D
+  WGL_MAX_PBUFFER_PIXELS_EXT* = 0x0000202E
+  WGL_MAX_PBUFFER_WIDTH_EXT* = 0x0000202F
+  WGL_MAX_PBUFFER_HEIGHT_EXT* = 0x00002030
+  WGL_OPTIMAL_PBUFFER_WIDTH_EXT* = 0x00002031
+  WGL_OPTIMAL_PBUFFER_HEIGHT_EXT* = 0x00002032
+  WGL_PBUFFER_LARGEST_EXT* = 0x00002033
+  WGL_PBUFFER_WIDTH_EXT* = 0x00002034
+  WGL_PBUFFER_HEIGHT_EXT* = 0x00002035
+
+proc wglCreatePbufferEXT*(hDC: HDC, iPixelFormat: TGLint, iWidth: TGLint, 
+                          iHeight: TGLint, piAttribList: PGLint): THandle{.
+    dynlib: dllname, importc: "wglCreatePbufferEXT".}
+proc wglGetPbufferDCEXT*(hPbuffer: THandle): HDC{.dynlib: dllname, 
+    importc: "wglGetPbufferDCEXT".}
+proc wglReleasePbufferDCEXT*(hPbuffer: THandle, hDC: HDC): TGLint{.
+    dynlib: dllname, importc: "wglReleasePbufferDCEXT".}
+proc wglDestroyPbufferEXT*(hPbuffer: THandle): BOOL{.dynlib: dllname, 
+    importc: "wglDestroyPbufferEXT".}
+proc wglQueryPbufferEXT*(hPbuffer: THandle, iAttribute: TGLint, piValue: PGLint): BOOL{.
+    dynlib: dllname, importc: "wglQueryPbufferEXT".}
+const 
+  WGL_NUMBER_PIXEL_FORMATS_EXT* = 0x00002000
+  WGL_DRAW_TO_WINDOW_EXT* = 0x00002001
+  WGL_DRAW_TO_BITMAP_EXT* = 0x00002002
+  WGL_ACCELERATION_EXT* = 0x00002003
+  WGL_NEED_PALETTE_EXT* = 0x00002004
+  WGL_NEED_SYSTEM_PALETTE_EXT* = 0x00002005
+  WGL_SWAP_LAYER_BUFFERS_EXT* = 0x00002006
+  WGL_SWAP_METHOD_EXT* = 0x00002007
+  WGL_NUMBER_OVERLAYS_EXT* = 0x00002008
+  WGL_NUMBER_UNDERLAYS_EXT* = 0x00002009
+  WGL_TRANSPARENT_EXT* = 0x0000200A
+  WGL_TRANSPARENT_VALUE_EXT* = 0x0000200B
+  WGL_SHARE_DEPTH_EXT* = 0x0000200C
+  WGL_SHARE_STENCIL_EXT* = 0x0000200D
+  WGL_SHARE_ACCUM_EXT* = 0x0000200E
+  WGL_SUPPORT_GDI_EXT* = 0x0000200F
+  WGL_SUPPORT_OPENGL_EXT* = 0x00002010
+  WGL_DOUBLE_BUFFER_EXT* = 0x00002011
+  WGL_STEREO_EXT* = 0x00002012
+  WGL_PIXEL_TYPE_EXT* = 0x00002013
+  WGL_COLOR_BITS_EXT* = 0x00002014
+  WGL_RED_BITS_EXT* = 0x00002015
+  WGL_RED_SHIFT_EXT* = 0x00002016
+  WGL_GREEN_BITS_EXT* = 0x00002017
+  WGL_GREEN_SHIFT_EXT* = 0x00002018
+  WGL_BLUE_BITS_EXT* = 0x00002019
+  WGL_BLUE_SHIFT_EXT* = 0x0000201A
+  WGL_ALPHA_BITS_EXT* = 0x0000201B
+  WGL_ALPHA_SHIFT_EXT* = 0x0000201C
+  WGL_ACCUM_BITS_EXT* = 0x0000201D
+  WGL_ACCUM_RED_BITS_EXT* = 0x0000201E
+  WGL_ACCUM_GREEN_BITS_EXT* = 0x0000201F
+  WGL_ACCUM_BLUE_BITS_EXT* = 0x00002020
+  WGL_ACCUM_ALPHA_BITS_EXT* = 0x00002021
+  WGL_DEPTH_BITS_EXT* = 0x00002022
+  WGL_STENCIL_BITS_EXT* = 0x00002023
+  WGL_AUX_BUFFERS_EXT* = 0x00002024
+  WGL_NO_ACCELERATION_EXT* = 0x00002025
+  WGL_GENERIC_ACCELERATION_EXT* = 0x00002026
+  WGL_FULL_ACCELERATION_EXT* = 0x00002027
+  WGL_SWAP_EXCHANGE_EXT* = 0x00002028
+  WGL_SWAP_COPY_EXT* = 0x00002029
+  WGL_SWAP_UNDEFINED_EXT* = 0x0000202A
+  WGL_TYPE_RGBA_EXT* = 0x0000202B
+  WGL_TYPE_COLORINDEX_EXT* = 0x0000202C
+
+proc wglGetPixelFormatAttribivEXT*(hdc: HDC, iPixelFormat: TGLint, 
+                                   iLayerPlane: TGLint, nAttributes: TGLuint, 
+                                   piAttributes: PGLint, piValues: PGLint): BOOL{.
+    dynlib: dllname, importc: "wglGetPixelFormatAttribivEXT".}
+proc wglGetPixelFormatAttribfvEXT*(hdc: HDC, iPixelFormat: TGLint, 
+                                   iLayerPlane: TGLint, nAttributes: TGLuint, 
+                                   piAttributes: PGLint, pfValues: PGLfloat): BOOL{.
+    dynlib: dllname, importc: "wglGetPixelFormatAttribfvEXT".}
+proc wglChoosePixelFormatEXT*(hdc: HDC, piAttribIList: PGLint, 
+                              pfAttribFList: PGLfloat, nMaxFormats: TGLuint, 
+                              piFormats: PGLint, nNumFormats: PGLuint): BOOL{.
+    dynlib: dllname, importc: "wglChoosePixelFormatEXT".}
+const 
+  WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D* = 0x00002050
+  WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D* = 0x00002051
+  WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D* = 0x00002052
+  WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D* = 0x00002053
+
+proc wglGetDigitalVideoParametersI3D*(hDC: HDC, iAttribute: TGLint, 
+                                      piValue: PGLint): BOOL{.dynlib: dllname, 
+    importc: "wglGetDigitalVideoParametersI3D".}
+proc wglSetDigitalVideoParametersI3D*(hDC: HDC, iAttribute: TGLint, 
+                                      piValue: PGLint): BOOL{.dynlib: dllname, 
+    importc: "wglSetDigitalVideoParametersI3D".}
+const 
+  WGL_GAMMA_TABLE_SIZE_I3D* = 0x0000204E
+  WGL_GAMMA_EXCLUDE_DESKTOP_I3D* = 0x0000204F
+
+proc wglGetGammaTableParametersI3D*(hDC: HDC, iAttribute: TGLint, 
+                                    piValue: PGLint): BOOL{.dynlib: dllname, 
+    importc: "wglGetGammaTableParametersI3D".}
+proc wglSetGammaTableParametersI3D*(hDC: HDC, iAttribute: TGLint, 
+                                    piValue: PGLint): BOOL{.dynlib: dllname, 
+    importc: "wglSetGammaTableParametersI3D".}
+proc wglGetGammaTableI3D*(hDC: HDC, iEntries: TGLint, puRed: PGLUSHORT, 
+                          puGreen: PGLUSHORT, puBlue: PGLUSHORT): BOOL{.
+    dynlib: dllname, importc: "wglGetGammaTableI3D".}
+proc wglSetGammaTableI3D*(hDC: HDC, iEntries: TGLint, puRed: PGLUSHORT, 
+                          puGreen: PGLUSHORT, puBlue: PGLUSHORT): BOOL{.
+    dynlib: dllname, importc: "wglSetGammaTableI3D".}
+const 
+  WGL_GENLOCK_SOURCE_MULTIVIEW_I3D* = 0x00002044
+  WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D* = 0x00002045
+  WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D* = 0x00002046
+  WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D* = 0x00002047
+  WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D* = 0x00002048
+  WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D* = 0x00002049
+  WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D* = 0x0000204A
+  WGL_GENLOCK_SOURCE_EDGE_RISING_I3D* = 0x0000204B
+  WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D* = 0x0000204C
+  WGL_FLOAT_COMPONENTS_NV* = 0x000020B0
+  WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV* = 0x000020B1
+  WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV* = 0x000020B2
+  WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV* = 0x000020B3
+  WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV* = 0x000020B4
+  WGL_TEXTURE_FLOAT_R_NV* = 0x000020B5
+  WGL_TEXTURE_FLOAT_RG_NV* = 0x000020B6
+  WGL_TEXTURE_FLOAT_RGB_NV* = 0x000020B7
+  WGL_TEXTURE_FLOAT_RGBA_NV* = 0x000020B8
+
+proc wglEnableGenlockI3D*(hDC: HDC): BOOL{.dynlib: dllname, 
+    importc: "wglEnableGenlockI3D".}
+proc wglDisableGenlockI3D*(hDC: HDC): BOOL{.dynlib: dllname, 
+    importc: "wglDisableGenlockI3D".}
+proc wglIsEnabledGenlockI3D*(hDC: HDC, pFlag: PBOOL): BOOL{.dynlib: dllname, 
+    importc: "wglIsEnabledGenlockI3D".}
+proc wglGenlockSourceI3D*(hDC: HDC, uSource: TGLuint): BOOL{.dynlib: dllname, 
+    importc: "wglGenlockSourceI3D".}
+proc wglGetGenlockSourceI3D*(hDC: HDC, uSource: PGLUINT): BOOL{.dynlib: dllname, 
+    importc: "wglGetGenlockSourceI3D".}
+proc wglGenlockSourceEdgeI3D*(hDC: HDC, uEdge: TGLuint): BOOL{.dynlib: dllname, 
+    importc: "wglGenlockSourceEdgeI3D".}
+proc wglGetGenlockSourceEdgeI3D*(hDC: HDC, uEdge: PGLUINT): BOOL{.
+    dynlib: dllname, importc: "wglGetGenlockSourceEdgeI3D".}
+proc wglGenlockSampleRateI3D*(hDC: HDC, uRate: TGLuint): BOOL{.dynlib: dllname, 
+    importc: "wglGenlockSampleRateI3D".}
+proc wglGetGenlockSampleRateI3D*(hDC: HDC, uRate: PGLUINT): BOOL{.
+    dynlib: dllname, importc: "wglGetGenlockSampleRateI3D".}
+proc wglGenlockSourceDelayI3D*(hDC: HDC, uDelay: TGLuint): BOOL{.
+    dynlib: dllname, importc: "wglGenlockSourceDelayI3D".}
+proc wglGetGenlockSourceDelayI3D*(hDC: HDC, uDelay: PGLUINT): BOOL{.
+    dynlib: dllname, importc: "wglGetGenlockSourceDelayI3D".}
+proc wglQueryGenlockMaxSourceDelayI3D*(hDC: HDC, uMaxLineDelay: PGLUINT, 
+                                       uMaxPixelDelay: PGLUINT): BOOL{.
+    dynlib: dllname, importc: "wglQueryGenlockMaxSourceDelayI3D".}
+const 
+  WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV* = 0x000020A0
+  WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV* = 0x000020A1
+  WGL_TEXTURE_RECTANGLE_NV* = 0x000020A2
+
+const 
+  WGL_RGBA_FLOAT_MODE_ATI* = 0x00008820
+  WGL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI* = 0x00008835
+  WGL_TYPE_RGBA_FLOAT_ATI* = 0x000021A0
+
+# implementation
diff --git a/tests/manyloc/packages/package1/p1.babel b/tests/manyloc/packages/package1/p1.babel
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/manyloc/packages/package2/p2.babel b/tests/manyloc/packages/package2/p2.babel
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/matrix/tmatrix2.nim b/tests/matrix/tmatrix2.nim
index 442096e93a..82990f1a59 100644
--- a/tests/matrix/tmatrix2.nim
+++ b/tests/matrix/tmatrix2.nim
@@ -1,5 +1,5 @@
 discard """
-  output: "5.0000000000000000e+00"
+  output: "5.0"
 """
 
 type
diff --git a/tests/misc/tissue710.nim b/tests/misc/tissue710.nim
new file mode 100644
index 0000000000..9e8735eb3b
--- /dev/null
+++ b/tests/misc/tissue710.nim
@@ -0,0 +1,10 @@
+discard """
+  file: "tissue710.nim"
+  line: 8
+  errorMsg: "expression '||' cannot be called"
+"""
+var sum = 0
+for x in 3..1000:
+  if (x mod 3 == 0) || (x mod 5 == 0):
+    sum += x
+echo(sum)
diff --git a/tests/misc/tstrange.nim b/tests/misc/tstrange.nim
index 3947755fcf..8742011bb6 100644
--- a/tests/misc/tstrange.nim
+++ b/tests/misc/tstrange.nim
@@ -1,6 +1,8 @@
 discard """
   file: "tstrange.nim"
-  output: "hallo4"
+  output: '''hallo40
+1
+2'''
 """
 # test for extremely strange bug
 
@@ -19,5 +21,8 @@ gen("hallo")
 write(stdout, ack(5, 4))
 #OUT hallo4
 
-
+# bug #1442
+let h=3
+for x in 0..  y # works
+
+echo((40'i32) > (30'i32))
+echo((40'u32) > (30'u32)) # Error: ordinal type expected
diff --git a/tests/misc/tvarious1.nim b/tests/misc/tvarious1.nim
index 6e4612ae30..1f2da2ae5d 100644
--- a/tests/misc/tvarious1.nim
+++ b/tests/misc/tvarious1.nim
@@ -3,7 +3,8 @@ discard """
   output: '''1
 0
 Whopie
-12'''
+12
+1.7'''
 """
 
 echo len([1_000_000]) #OUT 1
@@ -39,3 +40,9 @@ var val12 = TSomeRange(hour: 12)
 
 value = $(if val12.hour > 12: val12.hour - 12 else: val12.hour)
 echo value
+
+# bug #1334
+
+var ys = @[4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2] 
+#var x = int(ys.high / 2) #echo ys[x] # Works 
+echo ys[int(ys.high / 2)] # Doesn't work
diff --git a/tests/objvariant/tcheckedfield1.nim b/tests/objvariant/tcheckedfield1.nim
index 5ade3a13a5..1963ceb8d5 100644
--- a/tests/objvariant/tcheckedfield1.nim
+++ b/tests/objvariant/tcheckedfield1.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "cannot prove that field 'x.s' is accessible"
+  msg: "Warning: cannot prove that field 'x.s' is accessible [ProveField]"
   line:51
 """
 
diff --git a/tests/overload/toverl4.nim b/tests/overload/toverl4.nim
new file mode 100644
index 0000000000..6bb3a53d10
--- /dev/null
+++ b/tests/overload/toverl4.nim
@@ -0,0 +1,77 @@
+discard """
+  output: '''true'''
+"""
+
+#bug #592
+
+type
+  ElementKind = enum inner, leaf
+  TElement[TKey, TData] = object
+    case kind: ElementKind
+    of inner:
+      key: TKey
+      left, right: ref TElement[Tkey, TData]
+    of leaf:
+      data: TData
+  PElement[TKey, TData] = ref TElement[TKey, TData]
+
+proc newElement[Tkey, TData](other: PElement[TKey, TData]): PElement[Tkey, TData] =
+  case other.kind:
+  of inner:
+    PElement[TKey, TData](kind: ElementKind.inner, key: other.key, left: other.left, right: other.right)
+  of leaf:
+    PElement[TKey, TData](kind: ElementKind.leaf, data: other.data)
+
+proc newElement[TKey, TData](key: TKey, left: PElement[TKey, TData] = nil, right: PElement[TKey, TData] = nil) : PElement[TKey, TData] =
+  PElement[TKey, TData](kind: ElementKind.inner, key: key, left: left, right: right)
+
+proc newElement[Tkey, TData](key: Tkey, data: TData) : PElement[Tkey, TData] =
+  PElement[TKey, TData](kind: ElementKind.leaf, data: data)
+
+proc find*[TKey, TData](root: PElement[TKey, TData], key: TKey): TData {.raises: [EInvalidKey].} =
+  if root.left == nil:
+    raise newException(EInvalidKey, "key does not exist: " & key)
+
+  var tmp_element = addr(root)
+
+  while tmp_element.kind == inner and tmp_element.right != nil:
+    tmp_element = if tmp_element.key > key:
+                    addr(tmp_element.left)
+                  else:
+                    addr(tmp_element.right)
+
+  if tmp_element.key == key:
+    return tmp_element.left.data
+  else:
+    raise newException(EInvalidKey, "key does not exist: " & key)
+
+proc add*[TKey, TData](root: var PElement[TKey, TData], key: TKey, data: TData) : bool =
+  if root.left == nil:
+    root.key = key
+    root.left = newElement[TKey, TData](key, data)
+    return true
+
+  var tmp_element = addr(root)
+
+  while tmp_element.kind == ElementKind.inner and tmp_element.right != nil:
+    tmp_element = if tmp_element.key > key:
+                    addr(tmp_element.left)
+                  else:
+                    addr(tmp_element.right)
+
+  if tmp_element.key == key:
+    return false
+
+  var old_element = newElement[TKey, TData](tmp_element[])
+  var new_element = newElement[TKey, TData](key, data)
+
+  tmp_element[] = if tmp_element.key < key:
+                    newElement(key, old_element, new_element)
+                  else:
+                    newElement(tmp_element.key, new_element, old_element)
+
+  return true
+
+var tree = PElement[int, int](kind: ElementKind.inner, key: 0, left: nil, right: nil)
+let result = add(tree, 1, 1)
+echo(result)
\ No newline at end of file
diff --git a/tests/parallel/tdeepcopy.nim b/tests/parallel/tdeepcopy.nim
new file mode 100644
index 0000000000..84e2edf3f4
--- /dev/null
+++ b/tests/parallel/tdeepcopy.nim
@@ -0,0 +1,18 @@
+discard """
+  output: '''13 abc'''
+"""
+
+type
+  PBinaryTree = ref object
+    le, ri: PBinaryTree
+    value: int
+
+
+proc main =
+  var x: PBinaryTree
+  deepCopy(x, PBinaryTree(ri: PBinaryTree(le: PBinaryTree(value: 13))))
+  var y: string
+  deepCopy y, "abc"
+  echo x.ri.le.value, " ", y
+
+main()
diff --git a/tests/range/tmatrix3.nim b/tests/range/tmatrix3.nim
index 9004045249..80d38d63d9 100644
--- a/tests/range/tmatrix3.nim
+++ b/tests/range/tmatrix3.nim
@@ -1,6 +1,6 @@
 discard """
-  output: '''0.0000000000000000e+00
-0.0000000000000000e+00
+  output: '''0.0
+0.0
 0
 0
 0
diff --git a/tests/sets/tsets3.nim b/tests/sets/tsets3.nim
index d2b15d72d1..f599f8e7d6 100644
--- a/tests/sets/tsets3.nim
+++ b/tests/sets/tsets3.nim
@@ -74,8 +74,27 @@ block symmetricDifference:
   assert((s3 -+- s3) == initSet[int]())
   assert((s3 -+- s1) == s1_s3)
 
+block difference:
+  let
+    s1_s2 = difference(s1, s2)
+    s1_s3 = difference(s1, s3)
+    s2_s3 = s2 - s3
+
+  assert s1_s2.len == 2
+  assert s1_s3.len == 5
+  assert s2_s3.len == 3
+
+  for i in s1:
+    assert i in s1_s2 xor i in s2
+    assert i in s1_s3 xor i in s3
+  for i in s2:
+    assert i in s2_s3 xor i in s3
+
+  assert((s2 - s2) == initSet[int]())
+  assert((s1 - s3 - s1) == s1 -+- s3)
+
 block disjoint:
   assert(not disjoint(s1, s2))
   assert disjoint(s1, s3)
   assert(not disjoint(s2, s3))
-  assert(not disjoint(s2, s2))
\ No newline at end of file
+  assert(not disjoint(s2, s2))
diff --git a/tests/showoff/tdrdobbs_examples.nim b/tests/showoff/tdrdobbs_examples.nim
index 8a39990ba5..13a685950e 100644
--- a/tests/showoff/tdrdobbs_examples.nim
+++ b/tests/showoff/tdrdobbs_examples.nim
@@ -1,7 +1,7 @@
 discard """
   output: '''108
 11 -1 1936
-4.0000000000000002e-01
+0.4
 true
 truefalse'''
 """
diff --git a/tests/stdlib/testequivalence.nim b/tests/stdlib/testequivalence.nim
index 7c5d9e3e90..7acaad3408 100644
--- a/tests/stdlib/testequivalence.nim
+++ b/tests/stdlib/testequivalence.nim
@@ -1,7 +1,6 @@
 discard """
   output: ''''''
 """
-import unittest
 import sets
 
 doAssert(toSet(@[1,2,3]) <= toSet(@[1,2,3,4]), "equivalent or subset")
diff --git a/tests/system/tfloatToString.nim b/tests/system/tfloatToString.nim
new file mode 100644
index 0000000000..bb45a91d70
--- /dev/null
+++ b/tests/system/tfloatToString.nim
@@ -0,0 +1,22 @@
+discard """
+  output:'''2.3242
+2.982
+123912.1
+123912.1823
+5.0
+1e+100
+inf
+-inf
+nan
+'''
+"""
+
+echo($(2.3242))
+echo($(2.982))
+echo($(123912.1))
+echo($(123912.1823))
+echo($(5.0))
+echo($(1e100))
+echo($(1e1000000))
+echo($(-1e1000000))
+echo($(0.0/0.0))
diff --git a/tests/system/toString.nim b/tests/system/toString.nim
index 17dcb3cb48..52e7a4b92a 100644
--- a/tests/system/toString.nim
+++ b/tests/system/toString.nim
@@ -1,11 +1,9 @@
 discard """
   output:'''@[23, 45]
-@[, foo, bar]
-[, foo, bar]
-[23, 45]'''
+@[, foo, bar]'''
 """
 
 echo($(@[23, 45]))
 echo($(@["", "foo", "bar"]))
-echo($(["", "foo", "bar"]))
-echo($([23, 45]))
+#echo($(["", "foo", "bar"]))
+#echo($([23, 45]))
diff --git a/tests/table/ptables.nim b/tests/table/ptables.nim
index ec52d08c33..79a9aab171 100644
--- a/tests/table/ptables.nim
+++ b/tests/table/ptables.nim
@@ -104,6 +104,15 @@ block countTableTest1:
 block SyntaxTest:
   var x = newTable[int, string]({:})
 
+block nilTest:
+  var i, j: PTable[int, int] = nil
+  assert i == j
+  j = newTable[int, int]()
+  assert i != j
+  assert j != i
+  i = newTable[int, int]()
+  assert i == j
+
 proc orderedTableSortTest() =
   var t = newOrderedTable[string, int](2)
   for key, val in items(data): t[key] = val
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index 841eb8159f..02f7dc1d7f 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -312,7 +312,7 @@ proc testBabelPackages(r: var TResults, cat: Category, filter: PackageFilter) =
 
 # ----------------------------------------------------------------------------
 
-const AdditionalCategories = ["debugger", "tools", "examples", "stdlib", "babel-core"]
+const AdditionalCategories = ["debugger", "examples", "stdlib", "babel-core"]
 
 proc `&.?`(a, b: string): string =
   # candidate for the stdlib?
@@ -336,9 +336,6 @@ proc processCategory(r: var TResults, cat: Category, options: string) =
     gcTests(r, cat, options)
   of "debugger":
     debuggerTests(r, cat, options)
-  of "tools":
-    testSpec r, makeTest("compiler/c2nim/c2nim.nim", options, cat)
-    testSpec r, makeTest("compiler/pas2nim/pas2nim.nim", options, cat)
   of "manyloc":
     manyLoc r, cat, options
   of "threads":
diff --git a/tests/testament/specs.nim b/tests/testament/specs.nim
index 6e72f4b5e3..184f07c510 100644
--- a/tests/testament/specs.nim
+++ b/tests/testament/specs.nim
@@ -53,7 +53,7 @@ const
   targetToExt*: array[TTarget, string] = ["c", "cpp", "m", "js"]
   targetToCmd*: array[TTarget, string] = ["c", "cpp", "objc", "js"]
 
-when not defined(parseCfgBool):
+when not declared(parseCfgBool):
   # candidate for the stdlib:
   proc parseCfgBool(s: string): bool =
     case normalize(s)
diff --git a/tests/threads/tthreadanalysis.nim b/tests/threads/tthreadanalysis.nim
index 383680d816..37369b79cc 100644
--- a/tests/threads/tthreadanalysis.nim
+++ b/tests/threads/tthreadanalysis.nim
@@ -1,7 +1,7 @@
 discard """
   outputsub: "101"
-  msg: "Warning: write to foreign heap"
-  line: 37
+  errormsg: "'threadFunc' is not GC-safe"
+  line: 39
   cmd: "nimrod $target --hints:on --threads:on $options $file"
 """
 
diff --git a/tests/threads/tthreadheapviolation1.nim b/tests/threads/tthreadheapviolation1.nim
index f3a36e036d..e0629ed083 100644
--- a/tests/threads/tthreadheapviolation1.nim
+++ b/tests/threads/tthreadheapviolation1.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 12
-  errormsg: "write to foreign heap"
+  line: 11
+  errormsg: "'horrible' is not GC-safe"
   cmd: "nimrod $target --hints:on --threads:on $options $file"
 """
 
diff --git a/tests/vm/twrongarray.nim b/tests/vm/twrongarray.nim
new file mode 100644
index 0000000000..c1514d0e9b
--- /dev/null
+++ b/tests/vm/twrongarray.nim
@@ -0,0 +1,17 @@
+discard """
+  errormsg: "cannot evaluate at compile time: size"
+  line: 16
+"""
+
+#bug #1343
+
+when false:
+  proc one(dummy: int, size: int) =
+    var x: array[size, int] # compile error: constant expression expected
+
+  proc three(size: int) =
+    var x: array[size * 1, int] # compile error: cannot evaluate at compile time: size
+
+proc two(dummy: int, size: int) =
+  var x: array[size * 1, int] # compiles, but shouldn't?
+  #assert(x.len == size) # just for fun
diff --git a/tests/vm/twrongconst.nim b/tests/vm/twrongconst.nim
index 5c0c80f9fd..68ab2757cf 100644
--- a/tests/vm/twrongconst.nim
+++ b/tests/vm/twrongconst.nim
@@ -4,6 +4,6 @@ discard """
 """
 
 var x: array[100, char]
-template Foo : expr = x[42]
+template foo : expr = x[42]
 
 const myConst = foo
diff --git a/todo.txt b/todo.txt
index d1387669d6..d8085226da 100644
--- a/todo.txt
+++ b/todo.txt
@@ -2,21 +2,25 @@ version 0.9.6
 =============
 
 - scopes are still broken for generic instantiation!
-- integrate the new LL into the devel branch
-- start experimental branch
+- implicit deref for parameter matching
 
 Concurrency
 -----------
 
-- 'gcsafe' inferrence needs to be fixed
+- 'deepCopy' needs to be instantiated for
+  generics *when the type is constructed*
+- test 'deepCopy'
+- overloading of '='; general lift mechanism
+
 - the disjoint checker needs to deal with 'a = spawn f(); g = spawn f()'
-- implement 'deepCopy' builtin
 - implement 'foo[1..4] = spawn(f[4..7])'
-- support for exception propagation
-- Minor: The copying of the 'ref Promise' into the thead local storage only
+- document the new 'spawn' and 'parallel' statements
+
+Low priority:
+- support for exception propagation? (hard to implement)
+- the copying of the 'ref Promise' into the thead local storage only
   happens to work due to the write barrier's implementation
 - implement lock levels --> first without the more complex race avoidance
-- document the new 'spawn' and 'parallel' statements
 
 
 Misc
@@ -27,8 +31,6 @@ Misc
 - fix the tuple unpacking in lambda bug
 - make tuple unpacking work in a non-var/let context
 - special rule for ``[]=``
-- ``=`` should be overloadable; requires specialization for ``=``; general
-  lift mechanism in the compiler is already implemented for 'fields'
 - built-in 'getImpl'
 - type API for macros; make 'spawn' a macro
 - markAndSweepGC should expose an API for fibers
@@ -57,13 +59,9 @@ version 0.9.x
 - implement 'bits' pragmas
 - we need a magic thisModule symbol
 - provide --nilChecks:on|off
-- fix closures/lambdalifting
 - ensure (ref T)(a, b) works as a type conversion and type constructor
 - optimize 'genericReset'; 'newException' leads to code bloat
 - stack-less GC
-- implicit deref for parameter matching
-
-- VM: optimize opcAsgnStr
 
 
 version 0.9.X
diff --git a/tools/niminst/EnvVarUpdate.nsh b/tools/niminst/EnvVarUpdate.nsh
new file mode 100644
index 0000000000..4340b8f3c1
--- /dev/null
+++ b/tools/niminst/EnvVarUpdate.nsh
@@ -0,0 +1,346 @@
+/**
+ *  EnvVarUpdate.nsh
+ *    : Environmental Variables: append, prepend, and remove entries
+ *
+ *     WARNING: If you use StrFunc.nsh header then include it before this file
+ *              with all required definitions. This is to avoid conflicts
+ *
+ *  Usage:
+ *    ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString"
+ *
+ *  Credits:
+ *  Version 1.0 
+ *  * Cal Turney (turnec2)
+ *  * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this
+ *    function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar,
+ *    WriteEnvStr, and un.DeleteEnvStr
+ *  * Diego Pedroso (deguix) for StrTok
+ *  * Kevin English (kenglish_hi) for StrContains
+ *  * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry  
+ *    (dandaman32) for StrReplace
+ *
+ *  Version 1.1 (compatibility with StrFunc.nsh)
+ *  * techtonik
+ *
+ *  http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries
+ *
+ */
+
+
+!ifndef ENVVARUPDATE_FUNCTION
+!define ENVVARUPDATE_FUNCTION
+!verbose push
+!verbose 3
+!include "LogicLib.nsh"
+!include "WinMessages.NSH"
+!include "StrFunc.nsh"
+
+; ---- Fix for conflict if StrFunc.nsh is already includes in main file -----------------------
+!macro _IncludeStrFunction StrFuncName
+  !ifndef ${StrFuncName}_INCLUDED
+    ${${StrFuncName}}
+  !endif
+  !ifndef Un${StrFuncName}_INCLUDED
+    ${Un${StrFuncName}}
+  !endif
+  !define un.${StrFuncName} "${Un${StrFuncName}}"
+!macroend
+
+!insertmacro _IncludeStrFunction StrTok
+!insertmacro _IncludeStrFunction StrStr
+!insertmacro _IncludeStrFunction StrRep
+
+; ---------------------------------- Macro Definitions ----------------------------------------
+!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
+  Push "${EnvVarName}"
+  Push "${Action}"
+  Push "${RegLoc}"
+  Push "${PathString}"
+    Call EnvVarUpdate
+  Pop "${ResultVar}"
+!macroend
+!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"'
+ 
+!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
+  Push "${EnvVarName}"
+  Push "${Action}"
+  Push "${RegLoc}"
+  Push "${PathString}"
+    Call un.EnvVarUpdate
+  Pop "${ResultVar}"
+!macroend
+!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"'
+; ---------------------------------- Macro Definitions end-------------------------------------
+ 
+;----------------------------------- EnvVarUpdate start----------------------------------------
+!define hklm_all_users     'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
+!define hkcu_current_user  'HKCU "Environment"'
+ 
+!macro EnvVarUpdate UN
+ 
+Function ${UN}EnvVarUpdate
+ 
+  Push $0
+  Exch 4
+  Exch $1
+  Exch 3
+  Exch $2
+  Exch 2
+  Exch $3
+  Exch
+  Exch $4
+  Push $5
+  Push $6
+  Push $7
+  Push $8
+  Push $9
+  Push $R0
+ 
+  /* After this point:
+  -------------------------
+     $0 = ResultVar     (returned)
+     $1 = EnvVarName    (input)
+     $2 = Action        (input)
+     $3 = RegLoc        (input)
+     $4 = PathString    (input)
+     $5 = Orig EnvVar   (read from registry)
+     $6 = Len of $0     (temp)
+     $7 = tempstr1      (temp)
+     $8 = Entry counter (temp)
+     $9 = tempstr2      (temp)
+     $R0 = tempChar     (temp)  */
+ 
+  ; Step 1:  Read contents of EnvVarName from RegLoc
+  ;
+  ; Check for empty EnvVarName
+  ${If} $1 == ""
+    SetErrors
+    DetailPrint "ERROR: EnvVarName is blank"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ; Check for valid Action
+  ${If}    $2 != "A"
+  ${AndIf} $2 != "P"
+  ${AndIf} $2 != "R"
+    SetErrors
+    DetailPrint "ERROR: Invalid Action - must be A, P, or R"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ${If} $3 == HKLM
+    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5
+  ${ElseIf} $3 == HKCU
+    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5
+  ${Else}
+    SetErrors
+    DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"'
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ; Check for empty PathString
+  ${If} $4 == ""
+    SetErrors
+    DetailPrint "ERROR: PathString is blank"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  Push $6
+  Push $7
+  Push $8
+  StrLen $7 $4  
+  StrLen $6 $5
+  IntOp $8 $6 + $7
+  ${If} $5 == ""
+  ${OrIf} $8 >= ${NSIS_MAX_STRLEN}
+    SetErrors
+    DetailPrint "Current $1 length ($6) too long to modify in NSIS; set manually if needed"
+    Pop $8
+    Pop $7
+    Pop $6
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+  Pop $8
+  Pop $7
+  Pop $6
+
+  ; Make sure we've got some work to do
+  ${If} $5 == ""
+  ${AndIf} $2 == "R"
+    SetErrors
+    DetailPrint "$1 is empty - Nothing to remove"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ; Step 2: Scrub EnvVar
+  ;
+  StrCpy $0 $5                             ; Copy the contents to $0
+  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or
+  ; after the last one are not removed here but instead in Step 3)
+  ${If} $0 != ""                           ; If EnvVar is not empty ...
+    ${Do}
+      ${${UN}StrStr} $7 $0 " ;"
+      ${If} $7 == ""
+        ${ExitDo}
+      ${EndIf}
+      ${${UN}StrRep} $0  $0 " ;" ";"         ; Remove ';'
+    ${Loop}
+    ${Do}
+      ${${UN}StrStr} $7 $0 "; "
+      ${If} $7 == ""
+        ${ExitDo}
+      ${EndIf}
+      ${${UN}StrRep} $0  $0 "; " ";"         ; Remove ';'
+    ${Loop}
+    ${Do}
+      ${${UN}StrStr} $7 $0 ";;" 
+      ${If} $7 == ""
+        ${ExitDo}
+      ${EndIf}
+      ${${UN}StrRep} $0  $0 ";;" ";"
+    ${Loop}
+ 
+    ; Remove a leading or trailing semicolon from EnvVar
+    StrCpy  $7  $0 1 0
+    ${If} $7 == ";"
+      StrCpy $0  $0 "" 1                   ; Change ';' to ''
+    ${EndIf}
+    StrLen $6 $0
+    IntOp $6 $6 - 1
+    StrCpy $7  $0 1 $6
+    ${If} $7 == ";"
+     StrCpy $0  $0 $6                      ; Change ';' to ''
+    ${EndIf}
+    ; DetailPrint "Scrubbed $1: [$0]"      ; Uncomment to debug
+  ${EndIf}
+ 
+  /* Step 3. Remove all instances of the target path/string (even if "A" or "P")
+     $6 = bool flag (1 = found and removed PathString)
+     $7 = a string (e.g. path) delimited by semicolon(s)
+     $8 = entry counter starting at 0
+     $9 = copy of $0
+     $R0 = tempChar      */
+ 
+  ${If} $5 != ""                           ; If EnvVar is not empty ...
+    StrCpy $9 $0
+    StrCpy $0 ""
+    StrCpy $8 0
+    StrCpy $6 0
+ 
+    ${Do}
+      ${${UN}StrTok} $7 $9 ";" $8 "0"      ; $7 = next entry, $8 = entry counter
+ 
+      ${If} $7 == ""                       ; If we've run out of entries,
+        ${ExitDo}                          ;    were done
+      ${EndIf}                             ;
+ 
+      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)
+      ${Do}
+        StrCpy $R0  $7 1
+        ${If} $R0 != " "
+          ${ExitDo}
+        ${EndIf}
+        StrCpy $7   $7 "" 1                ;  Remove leading space
+      ${Loop}
+      ${Do}
+        StrCpy $R0  $7 1 -1
+        ${If} $R0 != " "
+          ${ExitDo}
+        ${EndIf}
+        StrCpy $7   $7 -1                  ;  Remove trailing space
+      ${Loop}
+      ${If} $7 == $4                       ; If string matches, remove it by not appending it
+        StrCpy $6 1                        ; Set 'found' flag
+      ${ElseIf} $7 != $4                   ; If string does NOT match
+      ${AndIf}  $0 == ""                   ;    and the 1st string being added to $0,
+        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon
+      ${ElseIf} $7 != $4                   ; If string does NOT match
+      ${AndIf}  $0 != ""                   ;    and this is NOT the 1st string to be added to $0,
+        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon
+      ${EndIf}                             ;
+ 
+      IntOp $8 $8 + 1                      ; Bump counter
+    ${Loop}                                ; Check for duplicates until we run out of paths
+  ${EndIf}
+ 
+  ; Step 4:  Perform the requested Action
+  ;
+  ${If} $2 != "R"                          ; If Append or Prepend
+    ${If} $6 == 1                          ; And if we found the target
+      DetailPrint "Target is already present in $1. It will be removed and"
+    ${EndIf}
+    ${If} $0 == ""                         ; If EnvVar is (now) empty
+      StrCpy $0 $4                         ;   just copy PathString to EnvVar
+      ${If} $6 == 0                        ; If found flag is either 0
+      ${OrIf} $6 == ""                     ; or blank (if EnvVarName is empty)
+        DetailPrint "$1 was empty and has been updated with the target"
+      ${EndIf}
+    ${ElseIf} $2 == "A"                    ;  If Append (and EnvVar is not empty),
+      StrCpy $0 $0;$4                      ;     append PathString
+      ${If} $6 == 1
+        DetailPrint "appended to $1"
+      ${Else}
+        DetailPrint "Target was appended to $1"
+      ${EndIf}
+    ${Else}                                ;  If Prepend (and EnvVar is not empty),
+      StrCpy $0 $4;$0                      ;     prepend PathString
+      ${If} $6 == 1
+        DetailPrint "prepended to $1"
+      ${Else}
+        DetailPrint "Target was prepended to $1"
+      ${EndIf}
+    ${EndIf}
+  ${Else}                                  ; If Action = Remove
+    ${If} $6 == 1                          ;   and we found the target
+      DetailPrint "Target was found and removed from $1"
+    ${Else}
+      DetailPrint "Target was NOT found in $1 (nothing to remove)"
+    ${EndIf}
+    ${If} $0 == ""
+      DetailPrint "$1 is now empty"
+    ${EndIf}
+  ${EndIf}
+ 
+  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change
+  ;
+  ClearErrors
+  ${If} $3  == HKLM
+    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section
+  ${ElseIf} $3 == HKCU
+    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section
+  ${EndIf}
+ 
+  IfErrors 0 +4
+    MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3"
+    DetailPrint "Could not write updated $1 to $3"
+    Goto EnvVarUpdate_Restore_Vars
+ 
+  ; "Export" our change
+  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+ 
+  EnvVarUpdate_Restore_Vars:
+  ;
+  ; Restore the user's variables and return ResultVar
+  Pop $R0
+  Pop $9
+  Pop $8
+  Pop $7
+  Pop $6
+  Pop $5
+  Pop $4
+  Pop $3
+  Pop $2
+  Pop $1
+  Push $0  ; Push my $0 (ResultVar)
+  Exch
+  Pop $0   ; Restore his $0
+ 
+FunctionEnd
+ 
+!macroend   ; EnvVarUpdate UN
+!insertmacro EnvVarUpdate ""
+!insertmacro EnvVarUpdate "un."
+;----------------------------------- EnvVarUpdate end----------------------------------------
+ 
+!verbose pop
+!endif
diff --git a/tools/niminst/inno.tmpl b/tools/niminst/inno.tmpl
index b9d04755ee..3460c22a29 100644
--- a/tools/niminst/inno.tmpl
+++ b/tools/niminst/inno.tmpl
@@ -44,9 +44,9 @@ Name: modifypath; Description: &Add $c.displayName to your system path (if not i
 [Code]
 function GiveMeAPath(const DefaultPathName: string): string;
 begin
-  if IsAdminLoggedOn then Result := ExpandConstant('{pf}')
-  else Result := ExpandConstant('{userdocs}');
-  Result := Result + '\' + DefaultPathName;
+  if IsAdminLoggedOn then result := ExpandConstant('{pf}')
+  else result := ExpandConstant('{userdocs}');
+  result := result + '\' + DefaultPathName;
 end;
 
   #if c.binPaths.len > 0:
diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim
index bf8a7a84ff..53de52f0a4 100644
--- a/tools/niminst/niminst.nim
+++ b/tools/niminst/niminst.nim
@@ -31,6 +31,7 @@ type
     actionNone,   # action not yet known
     actionCSource # action: create C sources
     actionInno,   # action: create Inno Setup installer
+    actionNsis,   # action: create NSIS installer
     actionScripts # action: create install and deinstall scripts
     actionZip,    # action: create zip file
     actionDeb     # action: prepare deb package
@@ -50,10 +51,10 @@ type
   TConfigData = object of TObject
     actions: set[TAction]
     cat: array[TFileCategory, seq[string]]
-    binPaths, authors, oses, cpus: seq[string]
+    binPaths, authors, oses, cpus, downloads: seq[string]
     cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]]
     platforms: array[1..maxOS, array[1..maxCPU, bool]]
-    ccompiler, linker, innosetup: tuple[path, flags: string]
+    ccompiler, linker, innosetup, nsisSetup: tuple[path, flags: string]
     name, displayName, version, description, license, infile, outdir: string
     libpath: string
     innoSetupFlag, installScript, uninstallScript: bool
@@ -75,9 +76,11 @@ proc initConfigData(c: var TConfigData) =
   c.authors = @[]
   c.oses = @[]
   c.cpus = @[]
+  c.downloads = @[]
   c.ccompiler = ("", "")
   c.linker = ("", "")
   c.innosetup = ("", "")
+  c.nsisSetup = ("", "")
   c.name = ""
   c.displayName = ""
   c.version = ""
@@ -117,6 +120,7 @@ proc skipRoot(f: string): string =
   if result.len == 0: result = f
 
 include "inno.tmpl"
+include "nsis.tmpl"
 include "buildsh.tmpl"
 include "buildbat.tmpl"
 include "install.tmpl"
@@ -125,10 +129,10 @@ include "deinstall.tmpl"
 # ------------------------- configuration file -------------------------------
 
 const
-  Version = "0.9"
+  Version = "1.0"
   Usage = "niminst - Nimrod Installation Generator Version " & Version & """
 
-  (c) 2013 Andreas Rumpf
+  (c) 2014 Andreas Rumpf
 Usage:
   niminst [options] command[;command2...] ini-file[.ini] [compile_options]
 Command:
@@ -136,6 +140,7 @@ Command:
   scripts             build install and deinstall scripts
   zip                 build the ZIP file
   inno                build the Inno Setup installer
+  nsis                build the NSIS Setup installer
   deb                 create files for debhelper
 Options:
   -o, --output:dir    set the output directory
@@ -162,6 +167,7 @@ proc parseCmdLine(c: var TConfigData) =
           of "scripts": incl(c.actions, actionScripts)
           of "zip": incl(c.actions, actionZip)
           of "inno": incl(c.actions, actionInno)
+          of "nsis": incl(c.actions, actionNsis)
           of "deb": incl(c.actions, actionDeb)
           else: quit(Usage)
       else:
@@ -190,7 +196,7 @@ proc walkDirRecursively(s: var seq[string], root: string) =
     case k
     of pcFile, pcLinkToFile: add(s, unixToNativePath(f))
     of pcDir: walkDirRecursively(s, f)
-    of pcLinkToDir: nil
+    of pcLinkToDir: discard
 
 proc addFiles(s: var seq[string], patterns: seq[string]) =
   for p in items(patterns):
@@ -288,7 +294,7 @@ proc parseIniFile(c: var TConfigData) =
             else: quit(errorStr(p, "expected: console or gui"))
           of "license": c.license = unixToNativePath(k.value)
           else: quit(errorStr(p, "unknown variable: " & k.key))
-        of "var": nil
+        of "var": discard
         of "winbin": filesOnly(p, k.key, v, c.cat[fcWinBin])
         of "config": filesOnly(p, k.key, v, c.cat[fcConfig])
         of "data": filesOnly(p, k.key, v, c.cat[fcData])
@@ -304,6 +310,7 @@ proc parseIniFile(c: var TConfigData) =
           of "files": addFiles(c.cat[fcWindows], split(v, {';'}))
           of "binpath": c.binPaths = split(v, {';'})
           of "innosetup": c.innoSetupFlag = yesno(p, v)
+          of "download": c.downloads.add(v)
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "unix":
           case normalize(k.key)
@@ -313,6 +320,7 @@ proc parseIniFile(c: var TConfigData) =
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin])
         of "innosetup": pathFlags(p, k.key, v, c.innosetup)
+        of "nsis": pathFlags(p, k.key, v, c.nsisSetup)
         of "ccompiler": pathFlags(p, k.key, v, c.ccompiler)
         of "linker": pathFlags(p, k.key, v, c.linker)
         of "deb":
@@ -479,14 +487,14 @@ proc srcdist(c: var TConfigData) =
 
 # --------------------- generate inno setup -----------------------------------
 proc setupDist(c: var TConfigData) =
-  var scrpt = generateInnoSetup(c)
-  var n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
+  let scrpt = generateInnoSetup(c)
+  let n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
   writeFile(n, scrpt, "\13\10")
   when defined(windows):
     if c.innosetup.path.len == 0:
       c.innosetup.path = "iscc.exe"
-    var outcmd = if c.outdir.len == 0: "build" else: c.outdir
-    var cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
+    let outcmd = if c.outdir.len == 0: "build" else: c.outdir
+    let cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
                                  c.innosetup.flags, outcmd, n]
     echo(cmd)
     if execShellCmd(cmd) == 0:
@@ -494,6 +502,23 @@ proc setupDist(c: var TConfigData) =
     else:
       quit("External program failed")
 
+# --------------------- generate NSIS setup -----------------------------------
+proc setupDist2(c: var TConfigData) =
+  let scrpt = generateNsisSetup(c)
+  let n = "build" / "install_$#_$#.nsi" % [toLower(c.name), c.version]
+  writeFile(n, scrpt, "\13\10")
+  when defined(windows):
+    if c.nsisSetup.path.len == 0:
+      c.nsisSetup.path = "makensis.exe"
+    let outcmd = if c.outdir.len == 0: "build" else: c.outdir
+    let cmd = "$# $# /O$# $#" % [quoteShell(c.nsisSetup.path),
+                                 c.nsisSetup.flags, outcmd, n]
+    echo(cmd)
+    if execShellCmd(cmd) == 0:
+      removeFile(n)
+    else:
+      quit("External program failed")
+
 # ------------------ generate ZIP file ---------------------------------------
 when haveZipLib:
   proc zipDist(c: var TConfigData) =
@@ -503,17 +528,17 @@ when haveZipLib:
     else: n = c.outdir / n
     var z: TZipArchive
     if open(z, n, fmWrite):
-      addFile(z, proj / buildBatFile32, buildBatFile32)
-      addFile(z, proj / buildBatFile64, buildBatFile64)
-      addFile(z, proj / buildShFile, buildShFile)
+      addFile(z, proj / buildBatFile32, "build" / buildBatFile32)
+      addFile(z, proj / buildBatFile64, "build" / buildBatFile64)
+      addFile(z, proj / buildShFile, "build" / buildShFile)
       addFile(z, proj / installShFile, installShFile)
       addFile(z, proj / deinstallShFile, deinstallShFile)
       for f in walkFiles(c.libpath / "lib/*.h"):
-        addFile(z, proj / "build" / extractFilename(f), f)
+        addFile(z, proj / "c_code" / extractFilename(f), f)
       for osA in 1..c.oses.len:
         for cpuA in 1..c.cpus.len:
           var dir = buildDir(osA, cpuA)
-          for k, f in walkDir(dir):
+          for k, f in walkDir("build" / dir):
             if k == pcFile: addFile(z, proj / dir / extractFilename(f), f)
 
       for cat in items({fcConfig..fcOther, fcUnix}):
@@ -576,6 +601,8 @@ parseCmdLine(c)
 parseIniFile(c)
 if actionInno in c.actions:
   setupDist(c)
+if actionNsis in c.actions:
+  setupDist2(c)
 if actionCSource in c.actions:
   srcdist(c)
 if actionScripts in c.actions:
diff --git a/tools/niminst/nsis.tmpl b/tools/niminst/nsis.tmpl
new file mode 100644
index 0000000000..c4270081e2
--- /dev/null
+++ b/tools/niminst/nsis.tmpl
@@ -0,0 +1,255 @@
+#! stdtmpl(subsChar='?') | standard
+#proc generateNsisSetup(c: TConfigData): string = 
+#  result = "; NSIS script generated by niminst\n" &
+#           "; To regenerate run ``niminst nsis`` or ``koch nsis``\n"
+
+;--------------------------------
+; Included headers
+  ; Modern User Interface 2.0 Header
+  !include "MUI2.nsh"
+
+  ; File Functions Header, used to get the current drive root.
+  !include "FileFunc.nsh"
+
+  ; *Patched* Environment Variable Manipulation Header, used to add
+  ; tools to the user's PATH environment variable.
+  !include "EnvVarUpdate.nsh"
+
+;--------------------------------
+; Global variables and defines
+  !define PRODUCT_NAME "?c.displayName"
+  !define PRODUCT_VERSION "?c.version"
+  !define PRODUCT_PUBLISHER "?c.authors"
+  !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\?{c.name}.exe"
+  !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+  !define PRODUCT_UNINST_ROOT_KEY "HKCU"
+  !define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"
+
+
+;--------------------------------
+; General Setup Information
+
+  ; Name and output file
+  Name "?{c.name} ?{c.version}"
+  OutFile "?{c.name}_?{c.version}.exe"
+
+  ; Default installation folder
+  ; This is changed later (in .onInit) to the root directory, if possible.
+  InstallDir "$LOCALAPPDATA\?{c.name}"
+  
+  ; Get installation folder from registry if available
+  InstallDirRegKey HKCU "Software\c.name\c.version" ""
+
+  ; Request user level application privileges.
+  RequestExecutionLevel user
+
+  ; Allow installation to the root drive directory.
+  AllowRootDirInstall true
+
+  ; Maximum compression!
+  SetCompressor /SOLID /FINAL lzma
+
+  ; Installer and Uninstaller Icons
+  ; Icon "nimrod.ico"
+  ; UninstallIcon "nimrod.ico"
+
+  ; Set installation details to be shown by default
+  ShowInstDetails show
+  ShowUnInstDetails show
+
+;--------------------------------
+; Interface Settings
+
+  ; Warn the user if aborting during installation/uninstallation
+  !define MUI_ABORTWARNING
+  !define MUI_UNABORTWARNING
+
+  ; Don't show a description for sections
+  !define MUI_COMPONENTSPAGE_NODESC
+
+;--------------------------------
+; Pages
+
+  ; Setup the installer pages
+  !insertmacro MUI_PAGE_WELCOME
+  !insertmacro MUI_PAGE_LICENSE "?{expandFilename(c.license)}"
+  !insertmacro MUI_PAGE_COMPONENTS
+  !insertmacro MUI_PAGE_DIRECTORY
+
+  ; Setup the start menu entry page
+  var ICONS_GROUP
+  !define MUI_STARTMENUPAGE_DEFAULTFOLDER "?{c.displayName}"
+  !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
+  !define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
+  !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
+  !insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
+
+  !insertmacro MUI_PAGE_INSTFILES
+  !insertmacro MUI_PAGE_FINISH
+  
+  ; Setup the uninstaller pages
+  !insertmacro MUI_UNPAGE_CONFIRM
+  !insertmacro MUI_UNPAGE_INSTFILES
+  
+;--------------------------------
+;Languages
+ 
+  !insertmacro MUI_LANGUAGE "English"
+
+;--------------------------------
+;Installer Sections
+
+  ; The core section. This is comprised of a base Nim installation,
+  ; such as what would be retrieved via git, and an already bootstrapped
+  ; Nim binary.
+  Section "Core Files" CoreSection
+    ; This is a mandotory section
+    SectionIn RO 
+
+    ; Output files to the base installation directory
+    SetOutPath "$INSTDIR"
+
+    ; Only overwrite newer files
+    SetOverwrite ifnewer
+
+    ; Write all the files to the output directory.
+    #for i in low(TFileCategory)..fcWindows:
+    #  for f in items(c.cat[i]):
+         SetOutPath "$INSTDIR\?{splitFile(f).dir.toWin}"
+         File "?{expandFilename(f).toWin}"
+    #  end for
+    #end for
+
+    ; Write out the uninstaller
+    WriteUninstaller "$INSTDIR\uninstaller.exe"
+  SectionEnd
+
+  Section "-Add Registry Keys" RegistrySection
+    ; Write application registry keys
+    WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+    ; Reset the output path
+    SetOutPath "$INSTDIR"
+  SectionEnd
+
+  ; Section for adding the shortcuts related to files and applications
+  Section "-Setup Shortcuts" ShortcutsSection
+    !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+      CreateDirectory "$SMPROGRAMS\$ICONS_GROUP"
+
+      #if c.app == appConsole:
+        CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
+        CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
+      #else:
+        CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
+        CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
+      #end if
+
+      ; Add shortcuts for the documentation
+      #for f in items(c.cat[fcDocStart]):
+        CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{splitFile(f).name}.lnk" "$INSTDIR\?{f.toWin}"
+      #end for
+
+      ; Write the shortcut to the uninstaller
+      CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninstaller.exe"
+    !insertmacro MUI_STARTMENU_WRITE_END
+  SectionEnd
+
+  ; Section for adding tools to the PATH variable
+  Section "Setup Path Environment" PathSection
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\mingw"
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\bin"
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\babel"
+  SectionEnd
+
+  ; The downloadable sections. These sections are automatically generated by
+  ; niminst and the template filters.
+  #var i = 0 
+  #for download in c.downloads:
+  #  inc i
+  #  let d = download.split('|')
+  #  if d.len != 5 and d.len != 6:
+  #    quit("download string needs 5..6 parts: " & download)
+  #  end if
+  #  let sectionName = d[0]
+  #  let dir = d[1]
+  #  let zipName = d[2]
+  #  let size = d[3]
+  #  let url = d[4]
+  Section /o "?sectionName" ?{i}Section
+    ; Add the section size to the total size.
+    AddSize ?size
+
+    ; Download the file, and if successful, extract it to the given directory
+    ; otherwise,
+    retry:
+    NSISdl::download "?url" "$TEMP\?zipName"
+    Pop $0
+    ${If} $0 == "success"
+      ZipDLL::extractall "$TEMP\?zipName" "$INSTDIR\?dir"
+      Delete "$TEMP\?zipName"
+    ${Else}
+      MessageBox MB_ICONSTOP|MB_ABORTRETRYIGNORE "Error: $0" IDRETRY retry IDIGNORE ignore
+      abort
+    ${EndIf}
+
+    #  if d.len >= 6:
+    #    let startMenuEntry = d[5]
+    #    let e = splitFile(startMenuEntry).name.capitalize
+      CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}"
+    #  end if
+
+    ; Shortcuts
+      !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+      !insertmacro MUI_STARTMENU_WRITE_END
+    ignore:
+  SectionEnd
+  #end
+
+;--------------------------------
+; Section Descriptions
+  ; Series of strings describing each section
+  ; LangString DESC_CoreSection ${LANG_ENGLISH} "Core Nim files"
+
+  ; The macros to actually insert the descriptions into the sections.
+  ; Each description above should have a corresponding MUI_DESCRIPTION_TEXT
+  ; macro linking the section to the description.
+  ; !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+  ;   !insertmacro MUI_DESCRIPTION_TEXT ${CoreSection} $(DESC_CoreSection)
+  ; !insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+
+;--------------------------------
+; Uninstaller Sections
+
+  Section "Uninstall"
+    ; Remove previously created shortcuts
+    !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
+    Delete "$DESKTOP\?{c.displayName}.lnk"
+
+    ; Remove installed application files
+    RMDir /r "$SMPROGRAMS\$ICONS_GROUP"
+    RMDir /r "$INSTDIR"
+
+    ; Remove the previously created registry key
+    DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+    DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}"
+    SetAutoClose true
+
+    ; Remove entries from the PATH environment variable
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\mingw"
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\bin"
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\babel"
+  SectionEnd
+
+;--------------------------------
+; Function hooks
+
+  Function .onInit
+    ${GetRoot} "$EXEDIR" $R0
+    strCpy $INSTDIR "$R0\?{c.name}"
+  FunctionEnd
\ No newline at end of file
diff --git a/tools/nimrepl.nim b/tools/nimrepl.nim
index 8e43b4431d..4b6379bd59 100644
--- a/tools/nimrepl.nim
+++ b/tools/nimrepl.nim
@@ -24,7 +24,7 @@ proc execCode(code: string): string =
     f.close()
     result = osproc.execProcess(
       "$# $# --verbosity:0 --hint[Conf]:off temp.nim" % [nimExe, runCmd],
-      {poStdErrToStdOut})
+      options = {poStdErrToStdOut})
   else:
     result = "cannot open file 'temp.nim'"
 
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index 9a83a5ccaa..00faecc01b 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -21,6 +21,7 @@ type
     nimrodArgs: string
     gitCommit: string
     quotations: TTable[string, tuple[quote, author: string]]
+    numProcessors: int # Set by parallelBuild:n, only works for values > 0.
   TRssItem = object
     year, month, day, title: string
 
@@ -42,6 +43,7 @@ proc initConfigData(c: var TConfigData) =
   c.ticker = ""
   c.vars = newStringTable(modeStyleInsensitive)
   c.gitCommit = "master"
+  c.numProcessors = countProcessors()
   # Attempts to obtain the git current commit.
   let (output, code) = execCmdEx("git log -n 1 --format=%H")
   if code == 0 and output.strip.len == 40:
@@ -121,6 +123,12 @@ proc parseCmdLine(c: var TConfigData) =
         stdout.write(Version & "\n")
         quit(0)
       of "o", "output": c.outdir = val
+      of "parallelbuild":
+        try:
+          let num = parseInt(val)
+          if num != 0: c.numProcessors = num
+        except EInvalidValue:
+          quit("invalid numeric value for --parallelBuild")
       of "var":
         var idx = val.find('=')
         if idx < 0: quit("invalid command line")
@@ -187,6 +195,12 @@ proc parseIniFile(c: var TConfigData) =
           of "srcdoc": addFiles(c.srcdoc, "lib", ".nim", split(v, {';'}))
           of "srcdoc2": addFiles(c.srcdoc2, "lib", ".nim", split(v, {';'}))
           of "webdoc": addFiles(c.webdoc, "lib", ".nim", split(v, {';'}))
+          of "parallelbuild":
+            try:
+              let num = parseInt(v)
+              if num != 0: c.numProcessors = num
+            except EInvalidValue:
+              quit("invalid numeric value for --parallelBuild in config")
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "quotations":
           let vSplit = v.split('-')
@@ -215,6 +229,20 @@ proc exec(cmd: string) =
   echo(cmd)
   if os.execShellCmd(cmd) != 0: quit("external program failed")
 
+proc sexec(cmds: openarray[string]) =
+  ## Serial queue wrapper around exec.
+  for cmd in cmds: exec(cmd)
+
+proc mexec(cmds: openarray[string], processors: int) =
+  ## Multiprocessor version of exec
+  if processors < 2:
+    sexec(cmds)
+    return
+
+  if execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}) != 0:
+    echo "external program failed, retrying serial work queue for logs!"
+    sexec(cmds)
+
 proc buildDocSamples(c: var TConfigData, destPath: string) =
   ## Special case documentation sample proc.
   ##
@@ -229,18 +257,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
 
 proc buildDoc(c: var TConfigData, destPath: string) =
   # call nim for the documentation:
+  var
+    commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2))
+    i = 0
   for d in items(c.doc):
-    exec("nimrod rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
+    commands[i] = "nimrod rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(d).name, "html"), d]
+    i.inc
   for d in items(c.srcdoc):
-    exec("nimrod doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
+    commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(d).name, "html"), d]
+    i.inc
   for d in items(c.srcdoc2):
-    exec("nimrod doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
+    commands[i] = "nimrod doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(d).name, "html"), d]
+    i.inc
+
+  mexec(commands, c.numProcessors)
   exec("nimrod buildIndex -o:$1/theindex.html $1" % [destPath])
 
 proc buildPdfDoc(c: var TConfigData, destPath: string) =
@@ -253,8 +289,10 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
       exec("pdflatex " & changeFileExt(d, "tex"))
       exec("pdflatex " & changeFileExt(d, "tex"))
       # delete all the crappy temporary files:
-      var pdf = splitFile(d).name & ".pdf"
-      moveFile(dest=destPath / pdf, source=pdf)
+      let pdf = splitFile(d).name & ".pdf"
+      let dest = destPath / pdf
+      removeFile(dest)
+      moveFile(dest=dest, source=pdf)
       removeFile(changeFileExt(pdf, "aux"))
       if existsFile(changeFileExt(pdf, "toc")):
         removeFile(changeFileExt(pdf, "toc"))
@@ -264,10 +302,12 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
 
 proc buildAddDoc(c: var TConfigData, destPath: string) =
   # build additional documentation (without the index):
-  for d in items(c.webdoc):
-    exec("nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" %
+  var commands = newSeq[string](c.webdoc.len)
+  for i, doc in pairs(c.webdoc):
+    commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(doc).name, "html"), doc]
+  mexec(commands, c.numProcessors)
 
 proc parseNewsTitles(inputFilename: string): seq[TRssItem] =
   # parses the file for titles and returns them as TRssItem blocks.
@@ -394,4 +434,7 @@ var c: TConfigData
 initConfigData(c)
 parseCmdLine(c)
 parseIniFile(c)
-main(c)
+when false:
+  buildPdfDoc(c, "doc")
+else:
+  main(c)
diff --git a/tools/trimcc.nim b/tools/trimcc.nim
index 6271d2b9a6..4d96861953 100644
--- a/tools/trimcc.nim
+++ b/tools/trimcc.nim
@@ -18,7 +18,7 @@ proc walker(dir: string) =
       else:
         echo "Required: ", path
         # copy back:
-        moveFile(dest=path, sourc=newName(path))
+        moveFile(dest=path, source=newName(path))
     of pcDir:
       walker(path)
     else: discard
diff --git a/web/babelpkglist.nim b/web/babelpkglist.nim
index 8745c9f997..5da7d60a9c 100644
--- a/web/babelpkglist.nim
+++ b/web/babelpkglist.nim
@@ -21,7 +21,7 @@ proc processContent(content: string) =
   var jsonArr = jsonDoc.elems
 
   jsonArr.sort do (x, y: PJsonNode) -> int:
-    system.cmp(x["name"].str, y["name"].str)
+    strutils.cmpIgnoreCase(x["name"].str, y["name"].str)
 
   var
     officialList = ""
@@ -38,8 +38,7 @@ proc processContent(content: string) =
       else: pkg["url"].str
     let
       desc = pkg["description"].str
-      # Review array index access when #1291 is solved.
-      dot = if desc.high > 0 and desc[ 0 and desc[desc.high] in endings: "" else: "."
       listItem = li(a(href=pkgWeb, pkg["name"].str), " ", desc & dot)
     if pkg["url"].str.startsWith("git://github.com/nimrod-code") or
        "official" in pkg["tags"].elems:
@@ -51,19 +50,17 @@ proc processContent(content: string) =
 
   var officialPkgListDiv = document.getElementById("officialPkgList")
 
-  officialPkgListDiv.innerHTML.add(
+  officialPkgListDiv.innerHTML =
     p("There are currently " & $officialCount &
       " official packages in the Babel package repository.") &
     ul(officialList)
-  )
 
   var unofficialPkgListDiv = document.getElementById("unofficialPkgList")
 
-  unofficialPkgListDiv.innerHTML.add(
+  unofficialPkgListDiv.innerHTML =
     p("There are currently " & $unofficialCount &
       " unofficial packages in the Babel package repository.") &
     ul(unofficialList)
-  )
 
 proc gotPackageList(apiReply: TData) {.exportc.} =
   let decoded = decodeContent($apiReply.content)
diff --git a/web/download.txt b/web/download.txt
index 5577882174..31777fad00 100644
--- a/web/download.txt
+++ b/web/download.txt
@@ -1,127 +1,39 @@
-You can download the latest version of the Nimrod compiler here. You can
-use the binaries provided or build from source.
-
-Binaries
-========
-
-All installers and archives contain the html documentation and tools
-(nimgrep, c2nim and babel).
+You can download the latest version of the Nimrod compiler here.
 
 **Note:** The Nimrod compiler requires a C compiler to compile software. On
 Windows we recommend that you use
 `Mingw-w64 `_. GCC is recommended on Linux
 and clang on Mac OS X.
 
-Installers
-----------
 
-The "full" version includes a full mingw distribution which includes a C
-compiler. The "slim" version lacks this.
+Binaries
+========
 
-* Full (i386, 32bit): ``_
+Unfortunately for now we only provide 32 bit builds for
+Windows: `nimrod_0.9.6.exe `_
 
-  .. raw:: html
-    

- SHA256: dca7c63d0c1861d2d7c51b2e7a29fa98371750a10ab282d5df9de22a07719c24 -

-* Slim (i386, 32bit): ``_ +Installation based on generated C code +====================================== - .. raw:: html -

- SHA256: c0fcd1201bd20fad1e14b9d2cc2529494057068de1dd01f871cf129f088a8242 -

+This installation method is the preferred way for Linux, Mac OS X, and other Unix +like systems. Binary packages may be provided later. -* Full (amd64, 64bit): ``_ - .. raw:: html -

- SHA256: af9d478c2f3361e0f238fcb07fa8e7ae5821938c0f9063c6670e925c9ae9d16e -

+Download `nimrod_0.9.6.zip `_, extract it and follow +these instructions: -* Slim (amd64, 64bit): ``_ +* sh build.sh +* Add ``$your_install_dir/bin`` to your PATH. - .. raw:: html -

- SHA256: 90c380721a46be2b9b8d5437187f701940aefc2e1fb9722dbc543f5c5a3bb85e -

+There are other ways to install Nimrod (like using the ``install.sh`` script), +but these tend to cause more problems. -Archives --------- -Windows -~~~~~~~ +Installation from github +======================== -The "full" version includes a full mingw distribution which includes a C -compiler. The "slim" version lacks this. - -* Full (i386, 32bit): ``_ - - .. raw:: html -

- SHA256: 8ee18faaa3a3d5df482c7abd6aa7ea87a350d7328b80ce1e2d486b59a7a93956 -

- -* Slim (i386, 32bit): ``_ - - .. raw:: html -

- SHA256: 7024fb8ad8f98c0bd4949ae36ed11b52b4e401754bbd62a11199d6dc8628d857 -

- -* Full (amd64, 64bit): ``_ - - .. raw:: html -

- SHA256: cb33cacc1a84fec771323d24cb6d9795f4803882466a9f417b424990aa49e18a -

- -* Slim (amd64, 64bit): ``_ - - .. raw:: html -

- SHA256: fcf877e4bd1ebfa214749af6e4811cd8539af19f1d7b23017e4bd7f6cbfb3eba -

- -Linux -~~~~~ - -* Linux (i386, 32bit): ``_ - - .. raw:: html -

- SHA256: 79DD337A77AC4313A75F2C5EED8252F00BBBDEB1E0C3504660D4A52EA63DBA92 -

-* Linux (amd64, 64bit): ``_ - - .. raw:: html -

- SHA256: 6F6CB3C727BA8059B7605C02942AE7910C20C2A3DC6A8A600D90D50FE61F0D8C -

-* Linux (ppc64, 64bit): ``_ - - .. raw:: html -

- SHA256: 5DAC2D9F7F545929E04540E6E2594C68FC3126A3B2F7B1FA7DBA5E295B4A7D31 -

- -Mac OS X -~~~~~~~~ - -* Mac OS X (amd64, 64bit): ``_ - - .. raw:: html -

- SHA256: E6F3A8E434DF3E89686F043954C6DFC09ABEBC0FC09D3B9A6B35C2B3102F7C3C -

- -If a binary for your platform is not available then you must build from source. -Bleeding edge binaries are available from the `Nimrod build farm `_. - -Source -====== - -Starting with 0.9.4 we now advise people to build directly from the +It is also possible to build directly from the github `master `_ branch:: git clone -b master git://github.com/Araq/Nimrod.git @@ -135,4 +47,3 @@ github `master `_ branch:: The ``master`` branch always contains the latest stable version of the compiler. If you want bleeding edge then switch to the ``devel`` branch and follow the same instructions outlined above. - diff --git a/web/index.txt b/web/index.txt index c3459d56bc..947ebb7060 100644 --- a/web/index.txt +++ b/web/index.txt @@ -101,5 +101,5 @@ Roadmap to 1.0 ============== Please have a look at -this `wiki page `_ for +this `wiki page `_ for an up-to-date overview. diff --git a/web/news.txt b/web/news.txt index a3019df517..acf1930888 100644 --- a/web/news.txt +++ b/web/news.txt @@ -2,26 +2,60 @@ News ==== -.. - 2014-06-29 Version 0.9.6 released - ================================= +2014-10-19 Nimrod version 0.9.6 released +======================================== - Changes affecting backwards compatibility - ----------------------------------------- +**Note: 0.9.6 is the last release of Nimrod. The language has been renamed to +Nim. Nim slightly breaks compatibility.** - - ``spawn`` now uses an elaborate self-adapting thread pool and as such - has been moved into its own module. So to use it, you now have to import - ``threadpool``. - - The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is - now considered for implicit early binding. +This is a maintenance release. The upcoming 0.10.0 release has +the new features and exciting developments. - Library Additions - ----------------- +Changes affecting backwards compatibility +----------------------------------------- - - Added module ``cpuinfo``. - - Added module ``threadpool``. - - ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``. +- ``spawn`` now uses an elaborate self-adapting thread pool and as such + has been moved into its own module. So to use it, you now have to import + ``threadpool``. +- The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is + now considered for implicit early binding. +- ``c2nim`` moved into its own repository and is now a Babel package. +- ``pas2nim`` moved into its own repository and is now a Babel package. +- ``system.$`` for floating point types now produces a human friendly string + representation. +- ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour + of the new ``TUri`` type in the ``uri`` module. +- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma + instead. The destructor's name has to be ``destroy`` now. +- ``lambda`` is not a keyword anymore. +- **system.defined has been split into system.defined and system.declared**. + You have to use ``--symbol`` to declare new conditional symbols that can be + set via ``--define``. +- ``--threadanalysis:on`` is now the default. To make your program compile + you can disable it but this is only a temporary solution as this option + will disappear soon! + + +Language Additions +------------------ + +- This version introduces the new ``deprecated`` pragma statement that is used + to handle the upcoming massive amount of symbol renames. +- ``spawn`` can now wrap proc that have a return value. It then returns a flow + variable of the wrapped return type. + + +Library Additions +----------------- + +- Added module ``cpuinfo``. +- Added module ``threadpool``. +- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``. +- Added ``algorithm.reversed`` +- Added ``uri.combine`` and ``uri.parseUri``. +- Some sockets procedures now support a ``SafeDisconn`` flag which causes + them to handle disconnection errors and not raise them. 2014-04-21 Version 0.9.4 released diff --git a/web/nimrod.ini b/web/nimrod.ini index af9ac0cd9f..64376cd66e 100644 --- a/web/nimrod.ini +++ b/web/nimrod.ini @@ -37,11 +37,11 @@ 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" -doc: "tools;c2nim;niminst;nimgrep;gc;estp;idetools;docgen;koch;backends.txt" -pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst;gc" +doc: "tools;niminst;nimgrep;gc;estp;idetools;docgen;koch;backends.txt" +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" +srcdoc2: "impure/re;pure/sockets;pure/typetraits" srcdoc: "system/threads.nim;system/channels.nim;js/dom" srcdoc2: "pure/os;pure/strutils;pure/math;pure/matchers;pure/algorithm" srcdoc2: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib" @@ -54,10 +54,10 @@ srcdoc2: "pure/httpserver;pure/httpclient;pure/smtp;impure/ssl;pure/fsmonitor" srcdoc2: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser" srcdoc2: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors;pure/mimetypes" srcdoc2: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics" -srcdoc2: "impure/rdstdin;wrappers/zmq;wrappers/sphinx" +srcdoc2: "impure/rdstdin;wrappers/sphinx" srcdoc2: "pure/collections/tables;pure/collections/sets;pure/collections/lists" srcdoc2: "pure/collections/intsets;pure/collections/queues;pure/encodings" -srcdoc2: "pure/events;pure/collections/sequtils;pure/irc;pure/cookies" +srcdoc2: "pure/events;pure/collections/sequtils;pure/cookies" srcdoc2: "pure/ftpclient;pure/memfiles;pure/subexes;pure/collections/critbits" srcdoc2: "pure/asyncio;pure/actors;core/locks;pure/oids;pure/endians;pure/uri" srcdoc2: "pure/nimprof;pure/unittest;packages/docutils/highlite" diff --git a/web/question.txt b/web/question.txt index 89e242e354..be90cc67a9 100644 --- a/web/question.txt +++ b/web/question.txt @@ -28,6 +28,14 @@ one of the even fewer that produces native binaries that require no runtime or interpreter. +What have been the major influences in the language's design? +------------------------------------------------------------- + +The language borrows heavily from: Modula 3, Delphi, Ada, C++, Python, Lisp, +Oberon. As far as possible the list is sorted by the impact of influence. + + + What is Nimrod's take on concurrency? ------------------------------------- @@ -89,8 +97,8 @@ Why is it named ``proc``? *Procedure* used to be the common term as opposed to a *function* which is a mathematical entity that has no side effects. It was planned to have ``func`` -as syntactic sugar for ``proc {.noSideEffect.}`` but the more fine-grained -effect system makes that unimportant. +as syntactic sugar for ``proc {.noSideEffect.}`` but with the more fine-grained +effect system it is not yet clear what ``func`` should be a shortcut for. Compilation @@ -117,15 +125,16 @@ Change the value of the ``cc`` variable to one of the following: ============== ============================================ Abbreviation C/C++ Compiler ============== ============================================ -``dmc`` Digital Mars C++ ``vcc`` Microsoft's Visual C++ ``gcc`` Gnu C -``tcc`` Tiny C ``llvm_gcc`` LLVM-GCC compiler ``icc`` Intel C++ compiler +``clang`` Clang compiler ``ucc`` Generic UNIX C compiler ============== ============================================ +Other C compilers are not officially supported, but might work too. + If your C compiler is not in the above list, try using the *generic UNIX C compiler* (``ucc``). If the C compiler needs different command line arguments try the ``--passc`` and ``--passl`` switches. diff --git a/web/ticker.txt b/web/ticker.txt index f06b005727..98ad25905b 100644 --- a/web/ticker.txt +++ b/web/ticker.txt @@ -1,3 +1,8 @@ + +

Oct 19, 2014

+

Nimrod version 0.9.6 has been released!

+
+

Apr 21, 2014

Nimrod version 0.9.4 has been released!