summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorMiguel <leu-gim@moy-server.ru>2014-02-10 01:20:42 +0400
committerMiguel <leu-gim@moy-server.ru>2014-02-10 01:20:42 +0400
commiteb9964fbbb9e1311edd72fcd6d47048db6178ed6 (patch)
tree402a1dcbfc2dd4bea122cd27d233ded67309c7ed
parenta8b4e3c764dd967e1ac90305a574c4cd5e0d019b (diff)
parente478374e0d16cf42051e753ccdd364aec13cf7d7 (diff)
downloadNim-eb9964fbbb9e1311edd72fcd6d47048db6178ed6.tar.gz
Merge branch 'devel' of git://github.com/Araq/Nimrod
-rw-r--r--compiler/ast.nim6
-rw-r--r--compiler/astalgo.nim33
-rw-r--r--compiler/ccgexprs.nim4
-rw-r--r--compiler/evalffi.nim56
-rw-r--r--compiler/lambdalifting.nim84
-rw-r--r--compiler/lookups.nim14
-rw-r--r--compiler/main.nim7
-rw-r--r--compiler/parser.nim50
-rw-r--r--compiler/sem.nim4
-rw-r--r--compiler/semdata.nim3
-rw-r--r--compiler/semexprs.nim20
-rw-r--r--compiler/semgnrc.nim11
-rw-r--r--compiler/semstmts.nim17
-rw-r--r--compiler/semthreads.nim2
-rw-r--r--compiler/semtypes.nim41
-rw-r--r--compiler/semtypinst.nim2
-rw-r--r--compiler/sigmatch.nim20
-rw-r--r--compiler/types.nim7
-rw-r--r--compiler/vm.nim27
-rw-r--r--compiler/vmdef.nim2
-rw-r--r--compiler/vmgen.nim146
-rw-r--r--config/nimdoc.cfg2
-rw-r--r--config/nimdoc.tex.cfg2
-rw-r--r--copying.txt2
-rw-r--r--devel/logging.nim210
-rw-r--r--doc/gc.txt17
-rw-r--r--doc/grammar.txt3
-rw-r--r--doc/lib.txt3
-rw-r--r--doc/manual.txt233
-rw-r--r--doc/tut1.txt24
-rw-r--r--doc/tut2.txt4
-rw-r--r--koch.nim5
-rw-r--r--lib/core/macros.nim28
-rw-r--r--lib/impure/db_mongo.nim4
-rw-r--r--lib/impure/db_sqlite.nim6
-rw-r--r--lib/packages/docutils/highlite.nim8
-rw-r--r--lib/posix/epoll.nim88
-rw-r--r--lib/posix/posix.nim901
-rw-r--r--lib/pure/algorithm.nim33
-rw-r--r--lib/pure/asyncio.nim2
-rw-r--r--lib/pure/asyncio2.nim485
-rw-r--r--lib/pure/collections/sequtils.nim39
-rw-r--r--lib/pure/collections/sets.nim17
-rw-r--r--lib/pure/collections/tables.nim10
-rw-r--r--lib/pure/dynlib.nim20
-rw-r--r--lib/pure/htmlparser.nim4
-rw-r--r--lib/pure/irc.nim4
-rw-r--r--lib/pure/logging.nim267
-rw-r--r--lib/pure/matchers.nim2
-rw-r--r--lib/pure/net.nim40
-rw-r--r--lib/pure/oids.nim2
-rw-r--r--lib/pure/os.nim80
-rw-r--r--lib/pure/osproc.nim185
-rw-r--r--lib/pure/parsecsv.nim2
-rw-r--r--lib/pure/parsesql.nim6
-rw-r--r--lib/pure/selectors.nim249
-rw-r--r--lib/pure/smtp.nim4
-rw-r--r--lib/pure/sockets.nim7
-rw-r--r--lib/pure/sockets2.nim202
-rw-r--r--lib/pure/strutils.nim10
-rw-r--r--lib/pure/times.nim8
-rw-r--r--lib/pure/xmlparser.nim4
-rw-r--r--lib/system.nim38
-rw-r--r--lib/system/excpt.nim2
-rw-r--r--lib/system/gc.nim2
-rw-r--r--lib/system/gc_ms.nim28
-rw-r--r--lib/windows/winlean.nim101
-rw-r--r--lib/wrappers/mongo.nim52
-rw-r--r--lib/wrappers/openssl.nim24
-rw-r--r--readme.md2
-rw-r--r--readme.txt2
-rw-r--r--tests/collections/ttables.nim22
-rw-r--r--tests/exprs/tstmtexprs.nim19
-rw-r--r--tests/gc/gcleak4.nim2
-rw-r--r--tests/gc/gcleak5.nim25
-rw-r--r--tests/generics/tgenericrefs.nim12
-rw-r--r--tests/iter/tanoniter1.nim4
-rw-r--r--tests/macros/tdebugstmt.nim29
-rw-r--r--tests/macros/tdumpast.nim2
-rw-r--r--tests/macros/tdumpast2.nim2
-rw-r--r--tests/macros/tmacrogenerics.nim6
-rw-r--r--tests/macros/tmacrotypes.nim4
-rw-r--r--tests/macros/tmemit.nim2
-rw-r--r--tests/macros/tstringinterp.nim6
-rw-r--r--tests/parser/tcommand_as_expr.nim21
-rw-r--r--tests/sets/testequivalence.nim15
-rw-r--r--tests/specials.nim238
-rw-r--r--tests/stdlib/talgorithm.nim8
-rw-r--r--tests/template/tprefer_immediate.nim17
-rw-r--r--tests/testament/backend.nim12
-rw-r--r--tests/testament/categories.nim5
-rw-r--r--tests/testament/htmlgen.nim19
-rw-r--r--tests/testament/tester.nim15
-rw-r--r--tests/tester.nim457
-rw-r--r--todo.txt11
-rw-r--r--web/nimrod.ini2
96 files changed, 3071 insertions, 1913 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 7138b5f52..cd002eef1 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1129,7 +1129,7 @@ proc newType(kind: TTypeKind, owner: PSym): PType =
   result.align = 2            # default alignment
   result.id = getID()
   when debugIds:
-    RegisterId(result)
+    registerId(result)
   #if result.id < 2000 then
   #  MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
   
@@ -1166,7 +1166,7 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType =
   if keepId: 
     result.id = t.id
   else: 
-    when debugIds: RegisterId(result)
+    when debugIds: registerId(result)
   result.sym = t.sym          # backend-info should not be copied
   
 proc copySym(s: PSym, keepId: bool = false): PSym = 
@@ -1177,7 +1177,7 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
     result.id = s.id
   else: 
     result.id = getID()
-    when debugIds: RegisterId(result)
+    when debugIds: registerId(result)
   result.flags = s.flags
   result.magic = s.magic
   if s.kind == skModule:
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index 2505bc687..64c1b717c 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -561,14 +561,31 @@ proc strTableContains(t: TStrTable, n: PSym): bool =
 
 proc strTableRawInsert(data: var TSymSeq, n: PSym) = 
   var h: THash = n.name.h and high(data)
-  while data[h] != nil: 
-    if data[h] == n:
-      # allowed for 'export' feature:
-      #InternalError(n.info, "StrTableRawInsert: " & n.name.s)
-      return
-    h = nextTry(h, high(data))
-  assert(data[h] == nil)
-  data[h] = n
+  if sfImmediate notin n.flags:
+    # fast path:
+    while data[h] != nil:
+      if data[h] == n:
+        # allowed for 'export' feature:
+        #InternalError(n.info, "StrTableRawInsert: " & n.name.s)
+        return
+      h = nextTry(h, high(data))
+    assert(data[h] == nil)
+    data[h] = n
+  else:
+    # slow path; we have to ensure immediate symbols are preferred for
+    # symbol lookups.
+    # consider the chain: foo (immediate), foo, bar, bar (immediate)
+    # then bar (immediate) gets replaced with foo (immediate) and the non
+    # immediate foo is picked! Thus we need to replace it with the first
+    # slot that has in fact the same identifier stored in it!
+    var favPos = -1
+    while data[h] != nil:
+      if data[h] == n: return
+      if favPos < 0 and data[h].name.id == n.name.id: favPos = h
+      h = nextTry(h, high(data))
+    assert(data[h] == nil)
+    data[h] = n
+    if favPos >= 0: swap data[h], data[favPos]
 
 proc symTabReplaceRaw(data: var TSymSeq, prevSym: PSym, newSym: PSym) =
   assert prevSym.name.h == newSym.name.h
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index ba543039e..031ab8d70 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -343,7 +343,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString,
      tyInt..tyUInt64, tyRange, tyVar:
     linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
-  else: internalError("genAssignment(" & $ty.kind & ')')
+  else: internalError("genAssignment: " & $ty.kind)
 
 proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
   if d.k == locNone: getTemp(p, typ, d)
@@ -1049,7 +1049,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
     app(tmp2.r, field.loc.r)
     tmp2.k = locTemp
     tmp2.t = field.loc.t
-    tmp2.s = OnHeap
+    tmp2.s = if isRef: OnHeap else: OnStack
     tmp2.heapRoot = tmp.r
     expr(p, it.sons[1], tmp2)
   if d.k == locNone:
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index 74f0663f3..54be0ccb2 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -102,7 +102,7 @@ proc mapCallConv(cc: TCallingConvention, info: TLineInfo): TABI =
   of ccStdCall: result = when defined(windows): STDCALL else: DEFAULT_ABI
   of ccCDecl: result = DEFAULT_ABI
   else:
-    GlobalError(info, "cannot map calling convention to FFI")
+    globalError(info, "cannot map calling convention to FFI")
 
 template rd(T, p: expr): expr {.immediate.} = (cast[ptr T](p))[]
 template wr(T, p, v: expr) {.immediate.} = (cast[ptr T](p))[] = v
@@ -164,7 +164,7 @@ proc packObject(x: PNode, typ: PType, res: pointer) =
       let field = getField(typ.n, i)
       pack(it, field.typ, res +! field.offset)
     else:
-      GlobalError(x.info, "cannot pack unnamed tuple")
+      globalError(x.info, "cannot pack unnamed tuple")
 
 const maxPackDepth = 20
 var packRecCheck = 0
@@ -193,7 +193,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
     of 4: awr(int32, v.intVal.int32)
     of 8: awr(int64, v.intVal.int64)
     else:
-      GlobalError(v.info, "cannot map value to FFI (tyEnum, tySet)")
+      globalError(v.info, "cannot map value to FFI (tyEnum, tySet)")
   of tyFloat: awr(float, v.floatVal)
   of tyFloat32: awr(float32, v.floatVal)
   of tyFloat64: awr(float64, v.floatVal)
@@ -207,7 +207,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
     elif v.kind in {nkStrLit..nkTripleStrLit}:
       awr(cstring, cstring(v.strVal))
     else:
-      GlobalError(v.info, "cannot map pointer/proc value to FFI")
+      globalError(v.info, "cannot map pointer/proc value to FFI")
   of tyPtr, tyRef, tyVar:
     if v.kind == nkNilLit:
       # nothing to do since the memory is 0 initialized anyway
@@ -217,7 +217,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
     else:
       if packRecCheck > maxPackDepth:
         packRecCheck = 0
-        GlobalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
+        globalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
       inc packRecCheck
       pack(v.sons[0], typ.sons[0], res +! sizeof(pointer))
       dec packRecCheck
@@ -233,7 +233,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
   of tyDistinct, tyGenericInst:
     pack(v, typ.sons[0], res)
   else:
-    GlobalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
+    globalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
 
 proc unpack(x: pointer, typ: PType, n: PNode): PNode
 
@@ -243,7 +243,7 @@ proc unpackObjectAdd(x: pointer, n, result: PNode) =
     for i in countup(0, sonsLen(n) - 1):
       unpackObjectAdd(x, n.sons[i], result)
   of nkRecCase:
-    GlobalError(result.info, "case objects cannot be unpacked")
+    globalError(result.info, "case objects cannot be unpacked")
   of nkSym:
     var pair = newNodeI(nkExprColonExpr, result.info, 2)
     pair.sons[0] = n
@@ -262,14 +262,14 @@ proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
     result = newNode(nkPar)
     result.typ = typ
     if typ.n.isNil:
-      InternalError("cannot unpack unnamed tuple")
+      internalError("cannot unpack unnamed tuple")
     unpackObjectAdd(x, typ.n, result)
   else:
     result = n
     if result.kind notin {nkObjConstr, nkPar}:
-      GlobalError(n.info, "cannot map value from FFI")
+      globalError(n.info, "cannot map value from FFI")
     if typ.n.isNil:
-      GlobalError(n.info, "cannot unpack unnamed tuple")
+      globalError(n.info, "cannot unpack unnamed tuple")
     for i in countup(ord(n.kind == nkObjConstr), sonsLen(n) - 1):
       var it = n.sons[i]
       if it.kind == nkExprColonExpr:
@@ -288,7 +288,7 @@ proc unpackArray(x: pointer, typ: PType, n: PNode): PNode =
   else:
     result = n
     if result.kind != nkBracket:
-      GlobalError(n.info, "cannot map value from FFI")
+      globalError(n.info, "cannot map value from FFI")
   let baseSize = typ.sons[1].getSize
   for i in 0 .. < result.len:
     result.sons[i] = unpack(x +! i * baseSize, typ.sons[1], result.sons[i])
@@ -312,7 +312,7 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
         #echo "expected ", k, " but got ", result.kind
         #debug result
         return newNodeI(nkExceptBranch, n.info)
-        #GlobalError(n.info, "cannot map value from FFI")
+        #globalError(n.info, "cannot map value from FFI")
     result.field = v
 
   template setNil() =
@@ -337,19 +337,19 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
   of tyInt16: awi(nkInt16Lit, rd(int16, x))
   of tyInt32: awi(nkInt32Lit, rd(int32, x))
   of tyInt64: awi(nkInt64Lit, rd(int64, x))
-  of tyUInt: awi(nkUIntLit, rd(uint, x).biggestInt)
-  of tyUInt8: awi(nkUInt8Lit, rd(uint8, x).biggestInt)
-  of tyUInt16: awi(nkUInt16Lit, rd(uint16, x).biggestInt)
-  of tyUInt32: awi(nkUInt32Lit, rd(uint32, x).biggestInt)
-  of tyUInt64: awi(nkUInt64Lit, rd(uint64, x).biggestInt)
+  of tyUInt: awi(nkUIntLit, rd(uint, x).BiggestInt)
+  of tyUInt8: awi(nkUInt8Lit, rd(uint8, x).BiggestInt)
+  of tyUInt16: awi(nkUInt16Lit, rd(uint16, x).BiggestInt)
+  of tyUInt32: awi(nkUInt32Lit, rd(uint32, x).BiggestInt)
+  of tyUInt64: awi(nkUInt64Lit, rd(uint64, x).BiggestInt)
   of tyEnum:
     case typ.getSize
-    of 1: awi(nkIntLit, rd(uint8, x).biggestInt)
-    of 2: awi(nkIntLit, rd(uint16, x).biggestInt)
-    of 4: awi(nkIntLit, rd(int32, x).biggestInt)
-    of 8: awi(nkIntLit, rd(int64, x).biggestInt)
+    of 1: awi(nkIntLit, rd(uint8, x).BiggestInt)
+    of 2: awi(nkIntLit, rd(uint16, x).BiggestInt)
+    of 4: awi(nkIntLit, rd(int32, x).BiggestInt)
+    of 8: awi(nkIntLit, rd(int64, x).BiggestInt)
     else:
-      GlobalError(n.info, "cannot map value from FFI (tyEnum, tySet)")
+      globalError(n.info, "cannot map value from FFI (tyEnum, tySet)")
   of tyFloat: awf(nkFloatLit, rd(float, x))
   of tyFloat32: awf(nkFloat32Lit, rd(float32, x))
   of tyFloat64: awf(nkFloat64Lit, rd(float64, x))
@@ -374,7 +374,7 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
       n.sons[0] = unpack(p, typ.sons[0], n.sons[0])
       result = n
     else:
-      GlobalError(n.info, "cannot map value from FFI " & typeToString(typ))
+      globalError(n.info, "cannot map value from FFI " & typeToString(typ))
   of tyObject, tyTuple:
     result = unpackObject(x, typ, n)
   of tyArray, tyArrayConstr:
@@ -391,7 +391,7 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
     result = unpack(x, typ.sons[0], n)
   else:
     # XXX what to do with 'array' here?
-    GlobalError(n.info, "cannot map value from FFI " & typeToString(typ))
+    globalError(n.info, "cannot map value from FFI " & typeToString(typ))
 
 proc fficast*(x: PNode, destTyp: PType): PNode =
   if x.kind == nkPtrLit and x.typ.kind in {tyPtr, tyRef, tyVar, tyPointer, 
@@ -414,7 +414,7 @@ proc fficast*(x: PNode, destTyp: PType): PNode =
     dealloc a
 
 proc callForeignFunction*(call: PNode): PNode =
-  InternalAssert call.sons[0].kind == nkPtrLit
+  internalAssert call.sons[0].kind == nkPtrLit
   
   var cif: TCif
   var sig: TParamList
@@ -422,12 +422,12 @@ proc callForeignFunction*(call: PNode): PNode =
   for i in 1..call.len-1:
     sig[i-1] = mapType(call.sons[i].typ)
     if sig[i-1].isNil:
-      GlobalError(call.info, "cannot map FFI type")
+      globalError(call.info, "cannot map FFI type")
   
   let typ = call.sons[0].typ
   if prep_cif(cif, mapCallConv(typ.callConv, call.info), cuint(call.len-1),
               mapType(typ.sons[0]), sig) != OK:
-    GlobalError(call.info, "error in FFI call")
+    globalError(call.info, "error in FFI call")
   
   var args: TArgList
   let fn = cast[pointer](call.sons[0].intVal)
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 00fa04556..3738f89b2 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -116,7 +116,8 @@ type
   TDep = tuple[e: PEnv, field: PSym]
   TEnv {.final.} = object of TObject
     attachedNode: PNode
-    createdVar: PSym         # if != nil it is a used environment
+    createdVar: PSym        # if != nil it is a used environment
+    createdVarComesFromIter: bool
     capturedVars: seq[PSym] # captured variables in this environment
     deps: seq[TDep]         # dependencies
     up: PEnv
@@ -571,7 +572,14 @@ proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode =
       # maybe later: (sfByCopy in local.flags)
       # add ``env.param = param``
       result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
-    idNodeTablePut(o.localsToAccess, local, fieldAccess)
+    # it can happen that we already captured 'local' in some other environment
+    # then we capture by copy for now. This is not entirely correct but better
+    # than nothing:
+    let existing = idNodeTableGet(o.localsToAccess, local)
+    if existing.isNil:
+      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``
@@ -584,14 +592,19 @@ proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode =
 
 proc generateIterClosureCreation(o: POuterContext; env: PEnv;
                                  scope: PNode): PSym =
-  result = newClosureCreationVar(o, env)
-  let cc = rawClosureCreation(o, env, result)
-  var insertPoint = scope.sons[0]
-  if insertPoint.kind == nkEmpty: scope.sons[0] = cc
+  if env.createdVarComesFromIter or env.createdVar.isNil:
+    # we have to create a new closure:
+    result = newClosureCreationVar(o, env)
+    let cc = rawClosureCreation(o, env, result)
+    var insertPoint = scope.sons[0]
+    if insertPoint.kind == nkEmpty: scope.sons[0] = cc
+    else:
+      assert cc.kind == nkStmtList and insertPoint.kind == nkStmtList
+      for x in cc: insertPoint.add(x)
+    if env.createdVar == nil: env.createdVar = result
   else:
-    assert cc.kind == nkStmtList and insertPoint.kind == nkStmtList
-    for x in cc: insertPoint.add(x)
-  if env.createdVar == nil: env.createdVar = result
+    result = env.createdVar
+  env.createdVarComesFromIter = true
 
 proc interestingIterVar(s: PSym): bool {.inline.} =
   result = s.kind in {skVar, skLet, skTemp, skForVar} and sfGlobal notin s.flags
@@ -637,6 +650,22 @@ proc outerProcSons(o: POuterContext, n: PNode) =
     let x = transformOuterProc(o, n.sons[i])
     if x != nil: n.sons[i] = x
 
+proc liftIterSym*(n: PNode): PNode =
+  # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env)) 
+  let iter = n.sym
+  assert iter.kind == skIterator
+
+  result = newNodeIT(nkStmtListExpr, n.info, n.typ)
+  
+  var env = copySym(getHiddenParam(iter))
+  env.kind = skLet
+  var v = newNodeI(nkVarSection, n.info)
+  addVar(v, newSymNode(env))
+  result.add(v)
+  # add 'new' statement:
+  result.add(newCall(getSysSym"internalNew", env))
+  result.add makeClosure(iter, env, n.info)
+
 proc transformOuterProc(o: POuterContext, n: PNode): PNode =
   if n == nil: return nil
   case n.kind
@@ -649,17 +678,22 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
       return indirectAccess(newSymNode(o.closureParam), local, n.info)
 
     var closure = PEnv(idTableGet(o.lambdasToEnv, local))
-    if closure != nil:
-      # we need to replace the lambda with '(lambda, env)':
-      if local.kind == skIterator and local.typ.callConv == ccClosure:
-        # 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)
-        # XXX why doesn't this work?
+
+    if local.kind == skIterator and local.typ.callConv == ccClosure:
+      # 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)
+      # XXX why doesn't this work?
+      if closure.isNil:
+        return liftIterSym(n)
+      else:
         let createdVar = generateIterClosureCreation(o, closure,
                                                      closure.attachedNode)
         return makeClosure(local, createdVar, n.info)
+
+    if closure != nil:
+      # we need to replace the lambda with '(lambda, env)':
       
       let a = closure.createdVar
       if a != nil:
@@ -773,22 +807,6 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
 
 # ------------------- iterator transformation --------------------------------
 
-proc liftIterSym*(n: PNode): PNode =
-  # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env)) 
-  let iter = n.sym
-  assert iter.kind == skIterator
-
-  result = newNodeIT(nkStmtListExpr, n.info, n.typ)
-  
-  var env = copySym(getHiddenParam(iter))
-  env.kind = skLet
-  var v = newNodeI(nkVarSection, n.info)
-  addVar(v, newSymNode(env))
-  result.add(v)
-  # add 'new' statement:
-  result.add(newCall(getSysSym"internalNew", env))
-  result.add makeClosure(iter, env, n.info)
-
 proc liftForLoop*(body: PNode): PNode =
   # problem ahead: the iterator could be invoked indirectly, but then
   # we don't know what environment to create here: 
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 6dfd25968..c31eb3121 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -339,4 +339,16 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
                                    n.sons[0].sym.name, o.inSymChoice)
   
   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.considerAcc.s)
+      result = errorSym(c, n)
diff --git a/compiler/main.nim b/compiler/main.nim
index cdea7b5ca..f6d11d960 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -135,7 +135,7 @@ proc interactivePasses =
   #setTarget(osNimrodVM, cpuNimrodVM)
   initDefines()
   defineSymbol("nimrodvm")
-  when hasFFI: DefineSymbol("nimffi")
+  when hasFFI: defineSymbol("nimffi")
   registerPass(verbosePass)
   registerPass(semPass)
   registerPass(evalPass)
@@ -324,7 +324,7 @@ proc mainCommand* =
     wantMainModule()
     when hasTinyCBackend:
       extccomp.setCC("tcc")
-      CommandCompileToC()
+      commandCompileToC()
     else:
       rawMessage(errInvalidCommandX, command)
   of "js", "compiletojs":
@@ -450,7 +450,8 @@ proc mainCommand* =
     echo "  tries : ", gCacheTries
     echo "  misses: ", gCacheMisses
     echo "  int tries: ", gCacheIntTries
-    echo "  efficiency: ", formatFloat(1-(gCacheMisses.float/gCacheTries.float), ffDecimal, 3)
+    echo "  efficiency: ", formatFloat(1-(gCacheMisses.float/gCacheTries.float),
+                                       ffDecimal, 3)
 
   when SimiluateCaasMemReset:
     resetMemory()
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 3765557b9..ff3324b47 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -35,6 +35,7 @@ type
     lex*: TLexer              # the lexer that is used for parsing
     tok*: TToken              # the current token
     inPragma: int
+    inSemiStmtList: int
 
 proc parseAll*(p: var TParser): PNode
 proc openParser*(p: var TParser, filename: string, inputstream: PLLStream)
@@ -455,11 +456,13 @@ proc complexOrSimpleStmt(p: var TParser): PNode
 proc simpleExpr(p: var TParser, mode = pmNormal): PNode
 
 proc semiStmtList(p: var TParser, result: PNode) =
+  inc p.inSemiStmtList
   result.add(complexOrSimpleStmt(p))
   while p.tok.tokType == tkSemiColon:
     getTok(p)
     optInd(p, result)
     result.add(complexOrSimpleStmt(p))
+  dec p.inSemiStmtList
   result.kind = nkStmtListExpr
 
 proc parsePar(p: var TParser): PNode =
@@ -642,8 +645,7 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
   #|               | '.' optInd ('type' | 'addr' | symbol) generalizedLit?
   #|               | '[' optInd indexExprList optPar ']'
   #|               | '{' optInd indexExprList optPar '}'
-  #|               | &( '`'|IDENT|literal|'cast') expr ^+ ',' # command syntax
-  #|                      (doBlock | macroColon)?
+  #|               | &( '`'|IDENT|literal|'cast') expr # command syntax
   result = r
   while p.tok.indent < 0:
     case p.tok.tokType
@@ -672,16 +674,18 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
         let a = result
         result = newNodeP(nkCommand, p)
         addSon(result, a)
-        while p.tok.tokType != tkEof:
-          let a = parseExpr(p)
-          addSon(result, a)
-          if p.tok.tokType != tkComma: break
-          getTok(p)
-          optInd(p, a)
-        if p.tok.tokType == tkDo:
-          parseDoBlocks(p, result)
-        else:
-          result = parseMacroColon(p, result)
+        addSon result, parseExpr(p)
+        when false:
+          while p.tok.tokType != tkEof:
+            let a = parseExpr(p)
+            addSon(result, a)
+            if p.tok.tokType != tkComma: break
+            getTok(p)
+            optInd(p, a)
+          if p.tok.tokType == tkDo:
+            parseDoBlocks(p, result)
+          else:
+            result = parseMacroColon(p, result)
       break
     else:
       break
@@ -1103,7 +1107,9 @@ proc parseExprStmt(p: var TParser): PNode =
   #|              doBlocks
   #|               / macroColon
   #|            ))?
+  inc p.inPragma
   var a = simpleExpr(p)
+  dec p.inPragma
   if p.tok.tokType == tkEquals: 
     getTok(p)
     optInd(p, result)
@@ -1878,14 +1884,18 @@ proc parseStmt(p: var TParser): PNode =
       parMessage(p, errComplexStmtRequiresInd)
       result = ast.emptyNode
     else:
-      result = newNodeP(nkStmtList, p)
-      while true:
-        if p.tok.indent >= 0: parMessage(p, errInvalidIndentation)     
-        let a = simpleStmt(p)
-        if a.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
-        result.add(a)
-        if p.tok.tokType != tkSemiColon: break
-        getTok(p)
+      if p.inSemiStmtList > 0:
+        result = simpleStmt(p)
+        if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
+      else:
+        result = newNodeP(nkStmtList, p)
+        while true:
+          if p.tok.indent >= 0: parMessage(p, errInvalidIndentation)     
+          let a = simpleStmt(p)
+          if a.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
+          result.add(a)
+          if p.tok.tokType != tkSemiColon: break
+          getTok(p)
   
 proc parseAll(p: var TParser): PNode = 
   result = newNodeP(nkStmtList, p)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index e89e32f4e..00ac79716 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -83,7 +83,9 @@ proc commonType*(x, y: PType): PType =
   elif a.kind == tyTypeDesc:
     # turn any concrete typedesc into the abstract typedesc type
     if a.sons == nil: result = a
-    else: result = newType(tyTypeDesc, a.owner)
+    else:
+      result = newType(tyTypeDesc, a.owner)
+      rawAddSon(result, newType(tyNone, a.owner))
   elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and 
       a.kind == b.kind:
     # check for seq[empty] vs. seq[int]
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 980abb865..c9d95e1bf 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -42,7 +42,7 @@ type
 
   TExprFlag* = enum 
     efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType,
-    efAllowDestructor
+    efAllowDestructor, efWantValue
   TExprFlags* = set[TExprFlag]
 
   PContext* = ref TContext
@@ -211,6 +211,7 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
 
 proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
   let typedesc = makeTypeDesc(c, typ)
+  rawAddSon(typedesc, newTypeS(tyNone, c))
   let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
   return newSymNode(sym, info)
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 84303b6cd..a8a16672d 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -35,7 +35,7 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     result.typ = errorType(c)
 
 proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
-  result = semExpr(c, n, flags)
+  result = semExpr(c, n, flags+{efWantValue})
   if result.isNil or result.kind == nkEmpty: 
     # do not produce another redundant error message:
     #raiseRecoverableError("")
@@ -1706,8 +1706,8 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = n
   result.typ = t
   result.kind = nkObjConstr
-  t = skipTypes(t, abstractInst)
-  if t.kind == tyRef: t = skipTypes(t.sons[0], abstractInst)
+  t = skipTypes(t, {tyGenericInst})
+  if t.kind == tyRef: t = skipTypes(t.sons[0], {tyGenericInst})
   if t.kind != tyObject:
     localError(n.info, errGenerated, "object constructor needs an object type")
     return
@@ -1819,6 +1819,10 @@ proc semExport(c: PContext, n: PNode): PNode =
   c.module.ast.add x
   result = n
 
+proc setGenericParams(c: PContext, n: PNode) =
+  for i in 1 .. <n.len:
+    n[i].typ = semTypeNode(c, n[i], nil)
+
 proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 
   result = n
   if gCmd == cmdIdeTools: suggestExpr(c, n)
@@ -1924,10 +1928,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       else:
         #liMessage(n.info, warnUser, renderTree(n));
         result = semIndirectOp(c, n, flags)
-    elif isSymChoice(n.sons[0]) or n[0].kind == nkBracketExpr and 
-        isSymChoice(n[0][0]):
+    elif n[0].kind == nkBracketExpr and isSymChoice(n[0][0]):
+      # indirectOp can deal with explicit instantiations; the fixes
+      # the 'newSeq[T](x)' bug
+      setGenericParams(c, n.sons[0])
       result = semDirectOp(c, n, flags)
-    elif nfDelegate in n.flags:
+    elif isSymChoice(n.sons[0]) or nfDelegate in n.flags:
       result = semDirectOp(c, n, flags)
     else:
       result = semIndirectOp(c, n, flags)
@@ -1993,7 +1999,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     result = semStaticExpr(c, n)
   of nkAsgn: result = semAsgn(c, n)
   of nkBlockStmt, nkBlockExpr: result = semBlock(c, n)
-  of nkStmtList, nkStmtListExpr: result = semStmtList(c, n)
+  of nkStmtList, nkStmtListExpr: result = semStmtList(c, n, flags)
   of nkRaiseStmt: result = semRaise(c, n)
   of nkVarSection: result = semVarOrLet(c, n, skVar)
   of nkLetSection: result = semVarOrLet(c, n, skLet)
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 89a167b96..b21d851c9 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -215,8 +215,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a)
       checkMinSonsLen(a, 3)
       var L = sonsLen(a)
-      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, 
-                                   ctx)
+      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
       a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
       for j in countup(0, L-3):
         addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
@@ -226,8 +225,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       if (a.kind != nkIdentDefs): illFormedAst(a)
       checkMinSonsLen(a, 3)
       var L = sonsLen(a)
-      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, 
-                                   ctx) 
+      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx) 
       # do not perform symbol lookup for default expressions 
       for j in countup(0, L-3): 
         addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
@@ -281,8 +279,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       if (a.kind != nkIdentDefs): illFormedAst(a)
       checkMinSonsLen(a, 3)
       var L = sonsLen(a)
-      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, 
-                                   ctx)
+      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
       a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
       for j in countup(0, L-3): 
         addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index caa719c7e..0871b7fb7 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -740,7 +740,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       # we fill it out later. For magic generics like 'seq', it won't be filled
       # so we use tyEmpty instead of nil to not crash for strange conversions
       # like: mydata.seq
-      rawAddSon(s.typ, newTypeS(tyEmpty, c))
+      rawAddSon(s.typ, newTypeS(tyNone, c))
       s.ast = a
       inc c.inGenericContext
       var body = semTypeNode(c, a.sons[2], nil)
@@ -748,7 +748,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       if body != nil:
         body.sym = s
         body.size = -1 # could not be computed properly
-      s.typ.sons[sonsLen(s.typ) - 1] = body
+        s.typ.sons[sonsLen(s.typ) - 1] = body
       popOwner()
       closeScope(c)
     elif a.sons[2].kind != nkEmpty: 
@@ -972,6 +972,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   else:
     s = n[namePos].sym
     typeIsDetermined = s.typ == nil
+    s.ast = n
+    s.scope = c.currentScope
+
     # if typeIsDetermined: assert phase == stepCompileBody
     # else: assert phase == stepDetermineType
   # before compiling the proc body, set as current the scope
@@ -1206,7 +1209,7 @@ proc usesResult(n: PNode): bool =
       for c in n:
         if usesResult(c): return true
 
-proc semStmtList(c: PContext, n: PNode): PNode =
+proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # these must be last statements in a block:
   const
     LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
@@ -1247,12 +1250,14 @@ proc semStmtList(c: PContext, n: PNode): PNode =
       if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
         voidContext = true
         n.typ = enforceVoidContext
-      if i != last or voidContext or c.inTypeClass > 0:
+      if i == last and efWantValue in flags:
+        n.typ = n.sons[i].typ
+        if not isEmptyType(n.typ): n.kind = nkStmtListExpr
+      elif i != last or voidContext or c.inTypeClass > 0:
         discardCheck(c, n.sons[i])
       else:
         n.typ = n.sons[i].typ
-        if not isEmptyType(n.typ):
-          n.kind = nkStmtListExpr
+        if not isEmptyType(n.typ): n.kind = nkStmtListExpr
       case n.sons[i].kind
       of nkVarSection, nkLetSection:
         let (outer, inner) = insertDestructors(c, n.sons[i])
diff --git a/compiler/semthreads.nim b/compiler/semthreads.nim
index f7322db80..d3426ca3e 100644
--- a/compiler/semthreads.nim
+++ b/compiler/semthreads.nim
@@ -358,7 +358,7 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
   of nkConstSection: result = analyseConstSection(c, n)
   of nkTypeSection, nkCommentStmt: result = toVoid
   of nkIfStmt, nkWhileStmt, nkTryStmt, nkCaseStmt, nkStmtList, nkBlockStmt, 
-     nkElifBranch, nkElse, nkExceptBranch, nkOfBranch:
+     nkElifBranch, nkElse, nkExceptBranch, nkOfBranch, nkFinally:
     for i in 0 .. <n.len: discard analyse(c, n[i])
     result = toVoid
   of nkBreakStmt, nkContinueStmt: result = toVoid
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 408b1b62e..44e414e9c 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -681,12 +681,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   of tySequence, tySet, tyArray, tyOpenArray,
      tyVar, tyPtr, tyRef, tyProc:
     # XXX: this is a bit strange, but proc(s: seq)
-    # produces tySequence(tyGenericParam, null).
+    # produces tySequence(tyGenericParam, tyNone).
     # This also seems to be true when creating aliases
     # like: type myseq = distinct seq.
     # Maybe there is another better place to associate
     # the seq type class with the seq identifier.
-    if paramType.kind == tySequence and paramType.lastSon == nil:
+    if paramType.kind == tySequence and paramType.lastSon.kind == tyNone:
       let typ = c.newTypeWithSons(tyBuiltInTypeClass,
                                   @[newTypeS(paramType.kind, c)])
       result = addImplicitGeneric(typ)
@@ -885,8 +885,12 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     for i in countup(1, sonsLen(n)-1):
       var elem = semGenericParamInInvokation(c, n.sons[i])
       addToResult(elem)
+  elif s.typ.kind != tyGenericBody:
+    #we likely got code of the form TypeA[TypeB] where TypeA is
+    #not generic.
+    localError(n.info, errNoGenericParamsAllowedForX, s.name.s)
+    return newOrPrevType(tyError, prev, c)
   else:
-    internalAssert s.typ.kind == tyGenericBody
 
     var m = newCandidate(c, s, n)
     matches(c, n, copyTree(n), m)
@@ -1133,15 +1137,26 @@ proc processMagicType(c: PContext, m: PSym) =
   of mNil: setMagicType(m, tyNil, ptrSize)
   of mExpr: setMagicType(m, tyExpr, 0)
   of mStmt: setMagicType(m, tyStmt, 0)
-  of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
+  of mTypeDesc: 
+    setMagicType(m, tyTypeDesc, 0)
+    rawAddSon(m.typ, newTypeS(tyNone, c))
   of mVoidType: setMagicType(m, tyEmpty, 0)
-  of mArray: setMagicType(m, tyArray, 0)
-  of mOpenArray: setMagicType(m, tyOpenArray, 0)
-  of mVarargs: setMagicType(m, tyVarargs, 0)
-  of mRange: setMagicType(m, tyRange, 0)
-  of mSet: setMagicType(m, tySet, 0) 
-  of mSeq: setMagicType(m, tySequence, 0)
-  of mOrdinal: setMagicType(m, tyOrdinal, 0)
+  of mArray:
+    setMagicType(m, tyArray, 0)
+  of mOpenArray:
+    setMagicType(m, tyOpenArray, 0)
+  of mVarargs:
+    setMagicType(m, tyVarargs, 0)
+  of mRange:
+    setMagicType(m, tyRange, 0)
+    rawAddSon(m.typ, newTypeS(tyNone, c))
+  of mSet:
+    setMagicType(m, tySet, 0) 
+  of mSeq: 
+    setMagicType(m, tySequence, 0)
+  of mOrdinal:
+    setMagicType(m, tyOrdinal, 0)
+    rawAddSon(m.typ, newTypeS(tyNone, c))
   of mPNimrodNode: discard
   else: localError(m.info, errTypeExpected)
   
@@ -1165,8 +1180,8 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
       typ = semTypeNode(c, constraint, nil)
       if typ.kind != tyStatic or typ.len == 0:
         if typ.kind == tyTypeDesc:
-          if typ.len == 0:
-            typ = newTypeS(tyTypeDesc, c)
+          if typ.sons[0].kind == tyNone:
+            typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)])
         else:
           typ = semGenericConstraints(c, typ)
     
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 1158335a8..a07d91241 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -358,7 +358,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
     if lookup != nil:
       result = lookup
       if tfUnresolved in t.flags: result = result.base
-    elif t.sonsLen > 0:
+    elif t.sons[0].kind != tyNone:
       result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0]))
  
   of tyUserTypeClass:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index d269e9e69..335ceafeb 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -105,6 +105,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
       var bound = binding[i].typ
       if bound != nil and formalTypeParam.kind != tyTypeDesc:
         bound = bound.skipTypes({tyTypeDesc})
+      assert bound != nil
       put(c.bindings, formalTypeParam, bound)
 
 proc newCandidate*(ctx: PContext, callee: PSym,
@@ -562,10 +563,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       #if result < isGeneric: result = isNone
       if result notin {isNone, isGeneric}:
         result = typeRangeRel(f, a)
-    elif skipTypes(f, {tyRange}).kind == a.kind:
-      result = isIntConv
-    elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
-      result = isConvertible  # a convertible to f
+    else:
+      if skipTypes(f, {tyRange}).kind == a.kind:
+        result = isIntConv
+      elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
+        result = isConvertible  # a convertible to f
   of tyInt:      result = handleRange(f, a, tyInt8, tyInt32)
   of tyInt8:     result = handleRange(f, a, tyInt8, tyInt8)
   of tyInt16:    result = handleRange(f, a, tyInt8, tyInt16)
@@ -636,7 +638,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyOrdinal:
     if isOrdinalType(a):
       var x = if a.kind == tyOrdinal: a.sons[0] else: a
-      if f.sonsLen == 0:
+      if f.sons[0].kind == tyNone:
         result = isGeneric
       else:
         result = typeRel(c, f.sons[0], x)
@@ -736,7 +738,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyGenericInst:
     let roota = a.skipGenericAlias
     let rootf = f.skipGenericAlias
-    if a.kind == tyGenericInst and roota.base == rootf.base :
+    if a.kind == tyGenericInst and roota.base == rootf.base:
       for i in 1 .. rootf.sonsLen-2:
         let ff = rootf.sons[i]
         let aa = roota.sons[i]
@@ -845,7 +847,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         # by a tyTypeDesc params. Unfortunately, this requires more substantial
         # changes in semtypinst and elsewhere.
         if a.kind == tyTypeDesc:
-          if f.sons == nil or f.sons.len == 0:
+          if f.sonsLen == 0:
             result = isGeneric
           else:
             internalAssert a.sons != nil and a.sons.len > 0
@@ -854,7 +856,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         else:
           result = isNone
       else:
-        if f.sonsLen > 0:
+        if f.sonsLen > 0 and f.sons[0].kind != tyNone:
           result = typeRel(c, f.lastSon, a)
         else:
           result = isGeneric
@@ -883,7 +885,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     var prev = PType(idTableGet(c.bindings, f))
     if prev == nil:
       if a.kind == tyTypeDesc:
-        if f.sonsLen == 0:
+        if f.sons[0].kind == tyNone:
           result = isGeneric
         else:
           result = typeRel(c, f.sons[0], a.sons[0])
diff --git a/compiler/types.nim b/compiler/types.nim
index 4a53a84c9..db75cd3c0 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -47,7 +47,8 @@ proc equalParams*(a, b: PNode): TParamsEquality
   # returns whether the parameter lists of the procs a, b are exactly the same
 proc isOrdinalType*(t: PType): bool
 proc enumHasHoles*(t: PType): bool
-const 
+
+const
   abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
                    tyConst, tyMutable, tyTypeDesc}
   abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal,
@@ -451,7 +452,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       of tyProc: "proc"
       of tyObject: "object"
       of tyTuple: "tuple"
-      else: (internalAssert false; "")
+      else: (internalAssert(false); "")
   of tyUserTypeClassInst:
     let body = t.base
     result = body.sym.name.s & "["
@@ -1257,7 +1258,7 @@ proc containsGenericTypeIter(t: PType, closure: PObject): bool =
     return true
 
   if t.kind == tyTypeDesc:
-    if t.sonsLen == 0: return true
+    if t.sons[0].kind == tyNone: return true
     if containsGenericTypeIter(t.base, closure): return true
     return false
   
diff --git a/compiler/vm.nim b/compiler/vm.nim
index deca288b5..10ac7aaaf 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -14,7 +14,7 @@ import ast except getstr
 
 import
   strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
-  parser, vmdeps, idents, trees, renderer, options
+  parser, vmdeps, idents, trees, renderer, options, transf
 
 from semfold import leValueConv, ordinalValToString
 from evaltempl import evalTemplate
@@ -337,7 +337,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       asgnRef(c.globals.sons[instr.regBx-wordExcess-1], regs[ra])
     of opcWrGlobal:
       asgnComplex(c.globals.sons[instr.regBx-wordExcess-1], regs[ra])
-    of opcLdArr:
+    of opcLdArr, opcLdArrRef:
       # a = b[c]
       let rb = instr.regB
       let rc = instr.regC
@@ -348,7 +348,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       assert regs[rb].kind != nkMetaNode
       let src = regs[rb]
       if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
-        asgnComplex(regs[ra], src.sons[idx])
+        if instr.opcode == opcLdArrRef and false:
+          # XXX activate when seqs are fixed
+          asgnRef(regs[ra], src.sons[idx])
+        else:
+          asgnComplex(regs[ra], src.sons[idx])
       else:
         stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcLdStrIdx:
@@ -379,9 +383,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       # a = b.c
       let rb = instr.regB
       let rc = instr.regC
-      # XXX this creates a wrong alias
       #Message(c.debug[pc], warnUser, $regs[rb].safeLen & " " & $rc)
       asgnComplex(regs[ra], regs[rb].sons[rc])
+    of opcLdObjRef:
+      # a = b.c
+      let rb = instr.regB
+      let rc = instr.regC
+      # XXX activate when seqs are fixed
+      asgnComplex(regs[ra], regs[rb].sons[rc])
+      #asgnRef(regs[ra], regs[rb].sons[rc])
     of opcWrObj:
       # a.b = c
       let rb = instr.regB
@@ -1037,7 +1047,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       # XXX only supports 'name' for now; we can use regC to encode the
       # type trait operation
       decodeB(nkStrLit)
-      let typ = regs[rb].sym.typ.skipTypes({tyTypeDesc})
+      var typ = regs[rb].typ
+      internalAssert typ != nil
+      while typ.kind == tyTypeDesc and typ.len > 0: typ = typ.sons[0]
       regs[ra].strVal = typ.typeToString(preferExported)
     of opcGlobalOnce:
       let rb = instr.regBx
@@ -1066,6 +1078,7 @@ proc execute(c: PCtx, start: int): PNode =
   result = rawExecute(c, start, tos)
 
 proc evalStmt*(c: PCtx, n: PNode) =
+  let n = transformExpr(c.module, n)
   let start = genStmt(c, n)
   # execute new instructions; this redundant opcEof check saves us lots
   # of allocations in 'execute':
@@ -1073,6 +1086,7 @@ proc evalStmt*(c: PCtx, n: PNode) =
     discard execute(c, start)
 
 proc evalExpr*(c: PCtx, n: PNode): PNode =
+  let n = transformExpr(c.module, n)
   let start = genExpr(c, n)
   assert c.code[start].opcode != opcEof
   result = execute(c, start)
@@ -1115,6 +1129,7 @@ proc myProcess(c: PPassContext, n: PNode): PNode =
 const evalPass* = makePass(myOpen, nil, myProcess, myProcess)
 
 proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
+  let n = transformExpr(module, n)
   setupGlobalCtx(module)
   var c = globalCtx
   c.mode = mode
@@ -1168,7 +1183,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   # doesn't end up in the parameter:
   #InternalAssert tos.slots.len >= L
   # return value:
-  tos.slots[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
+  tos.slots[0] = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
   # setup parameters:
   for i in 1 .. < min(tos.slots.len, L):
     tos.slots[i] = setupMacroParam(n.sons[i])
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index 480c7f31b..87159c813 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -34,9 +34,11 @@ type
     opcAsgnComplex,
 
     opcLdArr,  # a = b[c]
+    opcLdArrRef,
     opcWrArr,  # a[b] = c
     opcWrArrRef,
     opcLdObj,  # a = b.c
+    opcLdObjRef,
     opcWrObj,  # a.b = c
     opcWrObjRef,
     opcAddr,
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index a41e60e7d..d0e8dacf3 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.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.
@@ -13,9 +13,18 @@ import
   unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef, 
   trees, intsets, rodread, magicsys, options
 
+from os import splitFile
+
 when hasFFI:
   import evalffi
 
+type
+  TGenFlag = enum gfNone, gfAddrOf
+  TGenFlags = set[TGenFlag]
+
+proc debugInfo(info: TLineInfo): string =
+  result = info.toFilename.splitFile.name & ":" & $info.line
+
 proc codeListing(c: PCtx, result: var string, start=0) =
   # first iteration: compute all necessary labels:
   var jumpTargets = initIntSet()
@@ -44,7 +53,7 @@ proc codeListing(c: PCtx, result: var string, start=0) =
     else:
       result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, x.regBx-wordExcess)
     result.add("\t#")
-    result.add(toFileLine(c.debug[i]))
+    result.add(debugInfo(c.debug[i]))
     result.add("\n")
     inc i
 
@@ -100,7 +109,7 @@ proc patch(c: PCtx, p: TPosition) =
                uint32(diff+wordExcess) shl 16'u32).TInstr
 
 proc getSlotKind(t: PType): TSlotKind =
-  case t.skipTypes(abstractRange).kind
+  case t.skipTypes(abstractRange-{tyTypeDesc}).kind
   of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
     slotTempInt
   of tyString, tyCString:
@@ -190,20 +199,20 @@ template withBlock(labl: PSym; body: stmt) {.immediate, dirty.} =
   body
   popBlock(c, oldLen)
 
-proc gen(c: PCtx; n: PNode; dest: var TDest)
-proc gen(c: PCtx; n: PNode; dest: TRegister) =
+proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {})
+proc gen(c: PCtx; n: PNode; dest: TRegister; flags: TGenFlags = {}) =
   var d: TDest = dest
-  gen(c, n, d)
+  gen(c, n, d, flags)
   internalAssert d == dest
 
-proc gen(c: PCtx; n: PNode) =
+proc gen(c: PCtx; n: PNode; flags: TGenFlags = {}) =
   var tmp: TDest = -1
-  gen(c, n, tmp)
+  gen(c, n, tmp, flags)
   #if n.typ.isEmptyType: InternalAssert tmp < 0
 
-proc genx(c: PCtx; n: PNode): TRegister =
+proc genx(c: PCtx; n: PNode; flags: TGenFlags = {}): TRegister =
   var tmp: TDest = -1
-  gen(c, n, tmp)
+  gen(c, n, tmp, flags)
   internalAssert tmp >= 0
   result = TRegister(tmp)
 
@@ -400,7 +409,7 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
       let endExcept = c.xjmp(it, opcExcept, 0)
       for j in countup(0, blen - 2): 
         assert(it.sons[j].kind == nkType)
-        let typ = it.sons[j].typ.skipTypes(abstractPtrs)
+        let typ = it.sons[j].typ.skipTypes(abstractPtrs-{tyTypeDesc})
         c.gABx(it, opcExcept, 0, c.genType(typ))
       if blen == 1: 
         # general except section:
@@ -470,15 +479,16 @@ proc genNew(c: PCtx; n: PNode) =
   # we use the ref's base type here as the VM conflates 'ref object' 
   # and 'object' since internally we already have a pointer.
   c.gABx(n, opcNew, dest, 
-         c.genType(n.sons[1].typ.skipTypes(abstractVar).sons[0]))
+         c.genType(n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).sons[0]))
   c.genAsgnPatch(n.sons[1], dest)
   c.freeTemp(dest)
 
 proc genNewSeq(c: PCtx; n: PNode) =
   let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
              else: c.genx(n.sons[1])
-  c.gABx(n, opcNewSeq, dest, c.genType(n.sons[1].typ.skipTypes(abstractVar)))
   let tmp = c.genx(n.sons[2])
+  c.gABx(n, opcNewSeq, dest, c.genType(n.sons[1].typ.skipTypes(
+                                                  abstractVar-{tyTypeDesc})))
   c.gABx(n, opcNewSeq, tmp, 0)
   c.freeTemp(tmp)
   c.genAsgnPatch(n.sons[1], dest)
@@ -506,7 +516,7 @@ proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   c.freeTemp(tmp2)
 
 proc genSetType(c: PCtx; n: PNode; dest: TRegister) =
-  let t = skipTypes(n.typ, abstractInst)
+  let t = skipTypes(n.typ, abstractInst-{tyTypeDesc})
   if t.kind == tySet:
     c.gABx(n, opcSetType, dest, c.genType(t))
 
@@ -528,6 +538,14 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
   c.gABC(n, opc, dest, tmp, 0)
   c.freeTemp(tmp)
 
+proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
+  let
+    dest = c.genx(n.sons[1], {gfAddrOf})
+    tmp = c.genx(n.sons[2])
+  c.gABC(n, opc, dest, tmp, 0)
+  #c.genAsgnPatch(n.sons[1], dest)
+  c.freeTemp(tmp)
+
 proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
   let tmp = c.genx(n.sons[1])
   c.gABC(n, opc, tmp, 0, 0)
@@ -729,7 +747,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     var tmp = c.genx(n.sons[1])
     var idx = c.getTemp(getSysType(tyInt))
     var typ = n.sons[2].typ
-    if m == mOf: typ = typ.skipTypes(abstractPtrs)
+    if m == mOf: typ = typ.skipTypes(abstractPtrs-{tyTypeDesc})
     c.gABx(n, opcLdImmInt, idx, c.genType(typ))
     c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx)
     c.freeTemp(tmp)
@@ -739,7 +757,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
   of mHigh:
     if dest < 0: dest = c.getTemp(n.typ)
     let tmp = c.genx(n.sons[1])
-    if n.sons[1].typ.skipTypes(abstractVar).kind == tyString:
+    if n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).kind == tyString:
       c.gABI(n, opcLenStr, dest, tmp, 1)
     else:
       c.gABI(n, opcLenSeq, dest, tmp, 1)
@@ -754,13 +772,13 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     c.freeTempRange(x, n.len-1)
   of mAppendStrCh:
     unused(n, dest)
-    genBinaryStmt(c, n, opcAddStrCh)
+    genBinaryStmtVar(c, n, opcAddStrCh)
   of mAppendStrStr: 
     unused(n, dest)
-    genBinaryStmt(c, n, opcAddStrStr)
+    genBinaryStmtVar(c, n, opcAddStrStr)
   of mAppendSeqElem:
     unused(n, dest)
-    genBinaryStmt(c, n, opcAddSeqElem)
+    genBinaryStmtVar(c, n, opcAddSeqElem)
   of mParseExprToAst:
     genUnaryABC(c, n, dest, opcParseExprToAst)
   of mParseStmtToAst:
@@ -874,7 +892,7 @@ const
     tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64}
 
 proc requiresCopy(n: PNode): bool =
-  if n.typ.skipTypes(abstractInst).kind in atomicTypes:
+  if n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind in atomicTypes:
     result = false
   elif n.kind in ({nkCurly, nkBracket, nkPar, nkObjConstr}+nkCallKinds):
     result = false
@@ -882,7 +900,7 @@ proc requiresCopy(n: PNode): bool =
     result = true
 
 proc unneededIndirection(n: PNode): bool =
-  n.typ.skipTypes(abstractInst).kind == tyRef
+  n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef
 
 proc skipDeref(n: PNode): PNode =
   if n.kind in {nkDerefExpr, nkHiddenDeref} and unneededIndirection(n.sons[0]):
@@ -890,18 +908,20 @@ proc skipDeref(n: PNode): PNode =
   else:
     result = n
 
-proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = 
+proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
+                  flags: TGenFlags) = 
   # a nop for certain types
+  let flags = if opc == opcAddr: flags+{gfAddrOf} else: flags
   if unneededIndirection(n.sons[0]):
-    gen(c, n.sons[0], dest)
+    gen(c, n.sons[0], dest, flags)
   else:
-    let tmp = c.genx(n.sons[0])
+    let tmp = c.genx(n.sons[0], flags)
     if dest < 0: dest = c.getTemp(n.typ)
     gABC(c, n, opc, dest, tmp)
     c.freeTemp(tmp)
 
 proc whichAsgnOpc(n: PNode): TOpcode =
-  case n.typ.skipTypes(abstractRange).kind
+  case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind
   of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
     opcAsgnInt
   of tyString, tyCString:
@@ -913,7 +933,7 @@ proc whichAsgnOpc(n: PNode): TOpcode =
   else:
     opcAsgnComplex
 
-proc isRef(t: PType): bool = t.skipTypes(abstractRange).kind == tyRef
+proc isRef(t: PType): bool = t.skipTypes(abstractRange-{tyTypeDesc}).kind == tyRef
 
 proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode =
   if isRef(n.typ): succ(opc) else: opc
@@ -926,13 +946,22 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
 
 template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
 
+proc setSlot(c: PCtx; v: PSym) =
+  # XXX generate type initialization here?
+  if v.position == 0:
+    v.position = c.prc.maxSlots
+    c.prc.slots[v.position] = (inUse: true,
+        kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
+    inc c.prc.maxSlots
+
 proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
   case le.kind
   of nkBracketExpr:
     let dest = c.genx(le.sons[0])
     let idx = c.genx(le.sons[1])
     let tmp = c.genx(ri)
-    if le.sons[0].typ.skipTypes(abstractVarRange).kind in {tyString, tyCString}:
+    if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
+        tyString, tyCString}:
       c.gABC(le, opcWrStrIdx, dest, idx, tmp)
     else:
       c.gABC(le, whichAsgnOpc(le, opcWrArr), dest, idx, tmp)
@@ -952,8 +981,9 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
         gen(c, ri, tmp)
         c.gABx(le, whichAsgnOpc(le, opcWrGlobal), tmp, s.position)
     else:
+      if s.kind == skForVar and c.mode == emRepl: c.setSlot s
       internalAssert s.position > 0 or (s.position == 0 and
-                                        s.kind in {skParam,skResult,skForVar})
+                                        s.kind in {skParam,skResult})
       var dest: TRegister = s.position + ord(s.kind == skParam)
       gen(c, ri, dest)
   else:
@@ -1003,7 +1033,7 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
   if s.isGlobal:
     if sfCompileTime in s.flags or c.mode == emRepl:
       discard
-    else:
+    elif s.position == 0:
       cannotEval(n)
     if s.position == 0:
       if sfImportc in s.flags: c.importcSym(n.info, s)
@@ -1014,8 +1044,9 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
     else:
       c.gABx(n, opcLdGlobal, dest, s.position)
   else:
+    if s.kind == skForVar and c.mode == emRepl: c.setSlot s
     if s.position > 0 or (s.position == 0 and
-                          s.kind in {skParam,skResult,skForVar}):
+                          s.kind in {skParam,skResult}):
       if dest < 0:
         dest = s.position + ord(s.kind == skParam)
       else:
@@ -1024,28 +1055,29 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
     else:
       # see tests/t99bott for an example that triggers it:
       cannotEval(n)
-      #InternalError(n.info, s.name.s & " " & $s.position)
 
-proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
-  let a = c.genx(n.sons[0])
-  let b = c.genx(n.sons[1])
+proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
+               flags: TGenFlags) =
+  let a = c.genx(n.sons[0], flags)
+  let b = c.genx(n.sons[1], {})
   if dest < 0: dest = c.getTemp(n.typ)
-  c.gABC(n, opc, dest, a, b)
+  c.gABC(n, (if gfAddrOf in flags: succ(opc) else: opc), dest, a, b)
   c.freeTemp(a)
   c.freeTemp(b)
 
-proc genObjAccess(c: PCtx; n: PNode; dest: var TDest) =
-  genAccess(c, n, dest, opcLdObj)
+proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
+  genAccess(c, n, dest, opcLdObj, flags)
 
-proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest) =
+proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
   # XXX implement field checks!
-  genAccess(c, n.sons[0], dest, opcLdObj)
+  genAccess(c, n.sons[0], dest, opcLdObj, flags)
 
-proc genArrAccess(c: PCtx; n: PNode; dest: var TDest) =
-  if n.sons[0].typ.skipTypes(abstractVarRange).kind in {tyString, tyCString}:
-    genAccess(c, n, dest, opcLdStrIdx)
+proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
+  if n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
+      tyString, tyCString}:
+    genAccess(c, n, dest, opcLdStrIdx, {})
   else:
-    genAccess(c, n, dest, opcLdArr)
+    genAccess(c, n, dest, opcLdArr, flags)
 
 proc getNullValue*(typ: PType, info: TLineInfo): PNode
 proc getNullValueAux(obj: PNode, result: PNode) = 
@@ -1100,14 +1132,6 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
     result = newNodeIT(nkCurly, info, t)
   else: internalError("getNullValue: " & $t.kind)
 
-proc setSlot(c: PCtx; v: PSym) =
-  # XXX generate type initialization here?
-  if v.position == 0:
-    v.position = c.prc.maxSlots
-    c.prc.slots[v.position] = (inUse: true,
-        kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
-    inc c.prc.maxSlots
-
 proc genVarSection(c: PCtx; n: PNode) =
   for a in n:
     if a.kind == nkCommentStmt: continue
@@ -1187,7 +1211,7 @@ proc genSetConstr(c: PCtx, n: PNode, dest: var TDest) =
 
 proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
   if dest < 0: dest = c.getTemp(n.typ)
-  let t = n.typ.skipTypes(abstractRange)
+  let t = n.typ.skipTypes(abstractRange-{tyTypeDesc})
   if t.kind == tyRef:
     c.gABx(n, opcNew, dest, c.genType(t.sons[0]))
   else:
@@ -1222,7 +1246,7 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
 
 proc genProc*(c: PCtx; s: PSym): int
 
-proc gen(c: PCtx; n: PNode; dest: var TDest) =
+proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
   case n.kind
   of nkSym:
     let s = n.sym
@@ -1271,11 +1295,11 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
   of nkAsgn, nkFastAsgn: 
     unused(n, dest)
     genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
-  of nkDotExpr: genObjAccess(c, n, dest)
-  of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest)
-  of nkBracketExpr: genArrAccess(c, n, dest)
-  of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcDeref)
-  of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddr)
+  of nkDotExpr: genObjAccess(c, n, dest, flags)
+  of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
+  of nkBracketExpr: genArrAccess(c, n, dest, flags)
+  of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcDeref, flags)
+  of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddr, flags)
   of nkWhenStmt, nkIfStmt, nkIfExpr: genIf(c, n, dest)
   of nkCaseStmt: genCase(c, n, dest)
   of nkWhileStmt:
@@ -1298,7 +1322,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
   of nkStmtListExpr:
     let L = n.len-1
     for i in 0 .. <L: gen(c, n.sons[i])
-    gen(c, n.sons[L], dest)
+    gen(c, n.sons[L], dest, flags)
   of nkDiscardStmt:
     unused(n, dest)
     gen(c, n.sons[0])
@@ -1460,9 +1484,9 @@ proc genProc(c: PCtx; s: PSym): int =
     c.gABC(body, opcEof, eofInstr.regA)
     c.optimizeJumps(result)
     s.offset = c.prc.maxSlots
-    #if s.name.s == "rawGet":
+    #if s.name.s == "concatStyleInterpolation":
     #  c.echoCode(result)
-    #  echo renderTree(body)
+    # echo renderTree(body)
     c.prc = oldPrc
   else:
     c.prc.maxSlots = s.offset
diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg
index d47dccb63..63a3c30c4 100644
--- a/config/nimdoc.cfg
+++ b/config/nimdoc.cfg
@@ -76,7 +76,7 @@ span.LongStringLit {color: blue}
 span.CharLit {color: blue}
 span.EscapeSequence {color: black}
 span.Operator {color: black}
-span.Punctation {color: black}
+span.Punctuation {color: black}
 span.Comment, span.LongComment {font-style:italic; color: green}
 span.RegularExpression  {color: DarkViolet}
 span.TagStart {color: DarkViolet}
diff --git a/config/nimdoc.tex.cfg b/config/nimdoc.tex.cfg
index 8b59f2ee9..599ede345 100644
--- a/config/nimdoc.tex.cfg
+++ b/config/nimdoc.tex.cfg
@@ -98,7 +98,7 @@ doc.file = """
 \newcommand{\spanCharLit}[1]{#1}
 \newcommand{\spanEscapeSequence}[1]{#1}
 \newcommand{\spanOperator}[1]{#1}
-\newcommand{\spanPunctation}[1]{#1}
+\newcommand{\spanPunctuation}[1]{#1}
 \newcommand{\spanComment}[1]{\emph{#1}}
 \newcommand{\spanLongComment}[1]{\emph{#1}}
 \newcommand{\spanRegularExpression}[1]{#1}
diff --git a/copying.txt b/copying.txt
index 0ff6b7d87..4041ca027 100644
--- a/copying.txt
+++ b/copying.txt
@@ -1,7 +1,7 @@
 ===============================================================================
 Nimrod -- a Compiler for Nimrod. http://nimrod-code.org/
  
-Copyright (C) 2004-2013 Andreas Rumpf. All rights reserved.
+Copyright (C) 2004-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/devel/logging.nim b/devel/logging.nim
deleted file mode 100644
index a10478dab..000000000
--- a/devel/logging.nim
+++ /dev/null
@@ -1,210 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module implements a simple logger. It is based on the following design:
-## * Runtime log formating is a bug: Sooner or later every log file is parsed.
-## * Keep it simple: If this library does not fullfill your needs, write your 
-##   own. Trying to support every logging feature just leads to bloat.
-## 
-## Format is:: 
-##
-##   DEBUG|INFO|... (2009-11-02 00:00:00)? (Component: )? Message
-##
-## 
-
-import strutils, os, times
-
-type
-  TLevel* = enum  ## logging level
-    lvlAll,       ## all levels active
-    lvlDebug,     ## debug level (and any above) active
-    lvlInfo,      ## info level (and any above) active
-    lvlWarn,      ## warn level (and any above) active
-    lvlError,     ## error level (and any above) active
-    lvlFatal,     ## fatal level (and any above) active
-    lvlNone
-
-const
-  LevelNames*: array [TLevel, string] = [
-    "DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE"
-  ]
-
-  defaultFmtStr = "" ## default string between log level and message per logger
-  verboseFmtStr = "$date $time "
-
-type
-  TLogger* = object of TObject ## abstract logger; the base type of all loggers
-    levelThreshold*: TLevel    ## only messages of level >= levelThreshold 
-                               ## should be processed
-    fmtStr: string ## = defaultFmtStr by default, see substituteLog for $date etc.
-    
-  TConsoleLogger* = object of TLogger ## logger that writes the messages to the
-                                      ## console
-  
-  TFileLogger* = object of TLogger ## logger that writes the messages to a file
-    f: TFile
-  
-  # TODO: implement rolling log, will produce filename.1, filename.2 etc.
-  TRollingFileLogger* = object of TFileLogger ## logger that writes the 
-                                              ## message to a file
-    maxLines: int # maximum number of lines    
-    curLine : int
-    baseName: string # initial filename
-    logFiles: int # how many log files already created, e.g. basename.1, basename.2...
-    
-    
-
-
-proc substituteLog*(frmt: string): string = 
-  ## converts $date to the current date
-  ## converts $time to the current time
-  ## converts $app to getAppFilename()
-  ## converts 
-  result = newStringOfCap(frmt.len + 20)
-  var i = 0
-  while i < frmt.len: 
-    if frmt[i] != '$': 
-      result.add(frmt[i])
-      inc(i)
-    else:
-      inc(i)
-      var v = ""
-      var app = getAppFilename()
-      while frmt[i] in IdentChars: 
-        v.add(toLower(frmt[i]))
-        inc(i)
-      case v
-      of "date": result.add(getDateStr())
-      of "time": result.add(getClockStr())
-      of "app":  result.add(app)
-      of "appdir": result.add(app.splitFile.dir)
-      of "appname": result.add(app.splitFile.name)
-
-
-
-method log*(L: ref TLogger, level: TLevel,
-            frmt: string, args: varargs[string, `$`]) =
-  ## override this method in custom loggers. Default implementation does
-  ## nothing.
-  nil
-  
-method log*(L: ref TConsoleLogger, level: TLevel,
-            frmt: string, args: varargs[string, `$`]) = 
-    Writeln(stdout, LevelNames[level], " ", substituteLog(L.fmtStr), frmt % args)
-
-method log*(L: ref TFileLogger, level: TLevel, 
-            frmt: string, args: varargs[string, `$`]) = 
-    Writeln(L.f, LevelNames[level], " ", substituteLog(L.fmtStr), frmt % args)
-
-proc defaultFilename*(): string = 
-  ## returns the default filename for a logger
-  var (path, name, ext) = splitFile(getAppFilename())
-  result = changeFileExt(path / name & "_" & getDateStr(), "log")
-
-      
-
-
-proc newConsoleLogger*(levelThreshold = lvlAll) : ref TConsoleLogger =
-  new result
-  result.fmtStr = defaultFmtStr
-  result.levelThreshold = levelThreshold
-
-proc newFileLogger*(filename = defaultFilename(), 
-                    mode: TFileMode = fmAppend,
-                    levelThreshold = lvlAll): ref TFileLogger = 
-  new(result)
-  result.levelThreshold = levelThreshold
-  result.f = open(filename, mode)
-  result.fmtStr = defaultFmtStr
-
-# ------
-
-proc readLogLines(logger : ref TRollingFileLogger) = nil
-  #f.readLine # TODO read all lines, update curLine
-
-
-proc newRollingFileLogger*(filename = defaultFilename(), 
-                           mode: TFileMode = fmReadWrite,
-                           levelThreshold = lvlAll,
-                           maxLines = 1000): ref TRollingFileLogger = 
-  new(result)
-  result.levelThreshold = levelThreshold
-  result.fmtStr = defaultFmtStr
-  result.maxLines = maxLines
-  result.f = open(filename, mode)
-  result.curLine = 0
-  
-  # TODO count all number files
-  # count lines in existing filename file
-  # if >= maxLines then rename to next numbered file and create new file
-  
-  #if mode in {fmReadWrite, fmReadWriteExisting}:
-  #  readLogLines(result)
-
-
-
-method log*(L: ref TRollingFileLogger, level: TLevel, 
-            frmt: string, args: varargs[string, `$`]) = 
-  # TODO 
-  # if more than maxlines, then set cursor to zero
-  
-  Writeln(L.f, LevelNames[level], " ", frmt % args)
-
-# --------
-
-var
-  level* = lvlAll  ## global log filter
-  handlers*: seq[ref TLogger] = @[] ## handlers with their own log levels
-
-proc logLoop(level: TLevel, frmt: string, args: varargs[string, `$`]) =
-  for logger in items(handlers): 
-    if level >= logger.levelThreshold:
-      log(logger, level, frmt, args)
-
-template log*(level: TLevel, frmt: string, args: varargs[string, `$`]) =
-  ## logs a message of the given level
-  bind logLoop
-  bind `%`
-  bind logging.Level
-  
-  if level >= logging.Level:
-    logLoop(level, frmt, args)
-
-template debug*(frmt: string, args: varargs[string, `$`]) =
-  ## logs a debug message
-  log(lvlDebug, frmt, args)
-
-template info*(frmt: string, args: varargs[string, `$`]) = 
-  ## logs an info message
-  log(lvlInfo, frmt, args)
-
-template warn*(frmt: string, args: varargs[string, `$`]) = 
-  ## logs a warning message
-  log(lvlWarn, frmt, args)
-
-template error*(frmt: string, args: varargs[string, `$`]) = 
-  ## logs an error message
-  log(lvlError, frmt, args)
-  
-template fatal*(frmt: string, args: varargs[string, `$`]) =  
-  ## logs a fatal error message
-  log(lvlFatal, frmt, args)
-
-
-# --------------
-
-when isMainModule:
-  var L = newConsoleLogger()
-  var fL = newFileLogger("test.log")
-  fL.fmtStr = verboseFmtStr
-  handlers.add(L)
-  handlers.add(fL)
-  info("hello", [])
-  
-
diff --git a/doc/gc.txt b/doc/gc.txt
index 13498afaa..18fb03b6d 100644
--- a/doc/gc.txt
+++ b/doc/gc.txt
@@ -107,3 +107,20 @@ that up to 100 objects are traversed and freed before it checks again. Thus
 ``workPackage`` affects the timing granularity and may need to be tweaked in
 highly specialized environments or for older hardware.
 
+
+Keeping track of memory
+-----------------------
+
+If you need to pass around memory allocated by Nimrod to C, you can use the
+procs ``GC_ref`` and ``GC_unref`` to mark objects as referenced to avoid them
+being freed by the GC. Other useful procs from `system <system.html>`_ you can
+use to keep track of memory are:
+
+* getTotalMem(): returns the amount of total memory managed by the GC.
+* getOccupiedMem(): bytes reserved by the GC and used by objects.
+* getFreeMem(): bytes reserved by the GC and not in use.
+
+In addition to ``GC_ref`` and ``GC_unref`` you can avoid the GC by manually
+allocating memory with procs like ``alloc``, ``allocShared``, or
+``allocCStringArray``. The GC won't try to free them, you need to call their
+respective *dealloc* pairs when you are done with them or they will leak.
diff --git a/doc/grammar.txt b/doc/grammar.txt
index 54c2217d8..63e898e11 100644
--- a/doc/grammar.txt
+++ b/doc/grammar.txt
@@ -59,8 +59,7 @@ primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
               | '.' optInd ('type' | 'addr' | symbol) generalizedLit?
               | '[' optInd indexExprList optPar ']'
               | '{' optInd indexExprList optPar '}'
-              | &( '`'|IDENT|literal|'cast') expr ^+ ',' # command syntax
-                     (doBlock | macroColon)?
+              | &( '`'|IDENT|literal|'cast') expr # command syntax
 condExpr = expr colcom expr optInd
         ('elif' expr colcom expr optInd)*
          'else' colcom expr
diff --git a/doc/lib.txt b/doc/lib.txt
index ba0cb0a90..3214cdae2 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -341,6 +341,9 @@ Miscellaneous
 * `endians <endians.html>`_
   This module contains helpers that deal with different byte orders.
 
+* `logging <logging.html>`_
+  This module implements a simple logger.
+
 
 Database support
 ----------------
diff --git a/doc/manual.txt b/doc/manual.txt
index faf62dcee..16e025ee0 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -12,6 +12,8 @@ Nimrod Manual
   user to one/some of the other players, but the total amount seems to remain
   pretty much constant for a given task. -- Ran
 
+
+
 About this document
 ===================
 
@@ -1313,12 +1315,9 @@ Examples:
 
 .. code-block:: nimrod
 
-  type
-    TCallback = proc (x: int) {.cdecl.}
-
-  proc printItem(x: Int) = ...
+  proc printItem(x: int) = ...
 
-  proc forEach(c: TCallback) =
+  proc forEach(c: proc (x: int) {.cdecl.}) =
     ...
 
   forEach(printItem)  # this will NOT work because calling conventions differ
@@ -1479,7 +1478,7 @@ But it seems all this boilerplate code needs to be repeated for the ``TEuro``
 currency. This can be solved with templates_.
 
 .. code-block:: nimrod
-  template Additive(typ: typedesc): stmt =
+  template additive(typ: typedesc): stmt =
     proc `+` *(x, y: typ): typ {.borrow.}
     proc `-` *(x, y: typ): typ {.borrow.}
     
@@ -1487,26 +1486,26 @@ currency. This can be solved with templates_.
     proc `+` *(x: typ): typ {.borrow.}
     proc `-` *(x: typ): typ {.borrow.}
 
-  template Multiplicative(typ, base: typedesc): stmt =
+  template multiplicative(typ, base: typedesc): stmt =
     proc `*` *(x: typ, y: base): typ {.borrow.}
     proc `*` *(x: base, y: typ): typ {.borrow.}
     proc `div` *(x: typ, y: base): typ {.borrow.}
     proc `mod` *(x: typ, y: base): typ {.borrow.}
 
-  template Comparable(typ: typedesc): stmt =
+  template comparable(typ: typedesc): stmt =
     proc `<` * (x, y: typ): bool {.borrow.}
     proc `<=` * (x, y: typ): bool {.borrow.}
     proc `==` * (x, y: typ): bool {.borrow.}
 
-  template DefineCurrency(typ, base: expr): stmt =
+  template defineCurrency(typ, base: expr): stmt =
     type
       typ* = distinct base
-    Additive(typ)
-    Multiplicative(typ, base)
-    Comparable(typ)
+    additive(typ)
+    multiplicative(typ, base)
+    comparable(typ)
     
-  DefineCurrency(TDollar, int)
-  DefineCurrency(TEuro, int)
+  defineCurrency(TDollar, int)
+  defineCurrency(TEuro, int)
 
 
 Void type
@@ -2232,6 +2231,8 @@ Instead of:
 Using statement
 ---------------
 
+**Warning**: The ``using`` statement is highly experimental!
+
 The `using statement`:idx: provides syntactic convenience for procs that
 heavily use a single contextual parameter. When applied to a variable or a
 constant, it will instruct Nimrod to automatically consider the used symbol as
@@ -2457,6 +2458,83 @@ notation. (Thus an operator can have more than two parameters):
 
   assert `*+`(3, 4, 6) == `*`(a, `+`(b, c))
 
+
+Method call syntax
+------------------
+
+For object oriented programming, the syntax ``obj.method(args)`` can be used 
+instead of ``method(obj, args)``. The parentheses can be omitted if there are no
+remaining arguments: ``obj.len`` (instead of ``len(obj)``).
+
+This `method call syntax`:idx: is not restricted to objects, it can be used
+to supply any type of first argument for procedures:
+
+.. code-block:: nimrod
+  
+  echo("abc".len) # is the same as echo(len("abc"))
+  echo("abc".toUpper())
+  echo({'a', 'b', 'c'}.card)
+  stdout.writeln("Hallo") # the same as writeln(stdout, "Hallo")
+
+Another way to look at the method call syntax is that it provides the missing
+postfix notation.
+
+
+Properties
+----------
+Nimrod has no need for *get-properties*: Ordinary get-procedures that are called
+with the *method call syntax* achieve the same. But setting a value is 
+different; for this a special setter syntax is needed:
+
+.. code-block:: nimrod
+  
+  type
+    TSocket* = object of TObject
+      FHost: int # cannot be accessed from the outside of the module
+                 # the `F` prefix is a convention to avoid clashes since
+                 # the accessors are named `host`
+
+  proc `host=`*(s: var TSocket, value: int) {.inline.} =
+    ## setter of hostAddr
+    s.FHost = value
+  
+  proc host*(s: TSocket): int {.inline.} =
+    ## getter of hostAddr
+    return s.FHost
+
+  var
+    s: TSocket
+  s.host = 34  # same as `host=`(s, 34)
+
+
+Command invocation syntax
+-------------------------
+
+Routines can be invoked without the ``()`` if the call is syntatically
+a statement. This `command invocation syntax`:idx: also works for
+expressions, but then only a single argument may follow. This restriction
+means ``echo f 1, f 2`` is parsed as ``echo(f(1), f(2))`` and not as
+``echo(f(1, f(2)))``. The method call syntax may be used to provide one
+more argument in this case:
+
+.. code-block:: nimrod
+  proc optarg(x:int, y:int = 0):int = x + y
+  proc singlearg(x:int):int = 20*x
+  
+  echo optarg 1, " ", singlearg 2  # prints "1 40"
+  
+  let fail = optarg 1, optarg 8   # Wrong. Too many arguments for a command call
+  let x = optarg(1, optarg 8)  # traditional procedure call with 2 arguments
+  let y = 1.optarg optarg 8    # same thing as above, w/o the parenthesis
+  assert x == y
+
+The command invocation syntax also can't have complex expressions as arguments. 
+For example: (`anonymous procs`_), ``if``, ``case`` or ``try``. The (`do 
+notation`_) is limited, but usable for a single proc (see the example in the 
+corresponding section). Function calls with no arguments still needs () to 
+distinguish between a call and the function itself as a first class value.
+
+
 Closures
 --------
 
@@ -2469,6 +2547,7 @@ the closure and its enclosing scope (i.e. any modifications made to them are
 visible in both places). The closure environment may be allocated on the heap
 or on the stack if the compiler determines that this would be safe.
 
+
 Anonymous Procs
 ---------------
 
@@ -2495,6 +2574,9 @@ calls can use the ``do`` keyword:
 .. code-block:: nimrod
   sort(cities) do (x,y: string) -> int:
     cmp(x.len, y.len)
+  # Less parenthesis using the method plus command syntax:
+  cities = cities.map do (x:string) -> string:  
+    "City of " & x
 
 ``do`` is written after the parentheses enclosing the regular proc params. 
 The proc expression represented by the do block is appended to them.
@@ -2849,7 +2931,7 @@ parameters of an outer factory proc:
         yield x
         inc x
 
-  let foo = mycount 1, 4
+  let foo = mycount(1, 4)
 
   for f in foo():
     echo f
@@ -3440,13 +3522,41 @@ A symbol can be forced to be open by a `mixin`:idx: declaration:
 
 .. code-block:: nimrod
   proc create*[T](): ref T =
-    # there is no overloaded 'mixin' here, so we need to state that it's an
+    # there is no overloaded 'init' here, so we need to state that it's an
     # open symbol explicitly:
     mixin init
     new result
     init result
 
 
+Bind statement
+--------------
+
+The `bind`:idx: statement is the counterpart to the ``mixin`` statement. It 
+can be used to explicitly declare identifiers that should be bound early (i.e.
+the identifiers should be looked up in the scope of the template/generic
+definition):
+
+.. code-block:: nimrod
+  # Module A
+  var 
+    lastId = 0
+  
+  template genId*: expr =
+    bind lastId
+    inc(lastId)
+    lastId
+
+.. code-block:: nimrod
+  # Module B
+  import A
+  
+  echo genId()
+
+But a ``bind`` is rarely useful because symbol binding from the definition
+scope is the default.
+
+
 Templates
 =========
 
@@ -3506,28 +3616,6 @@ receive undeclared identifiers:
   declareInt(x) # valid
 
 
-Scoping in templates
---------------------
-
-The template body does not open a new scope. To open a new scope a ``block``
-statement can be used:
-
-.. code-block:: nimrod
-  template declareInScope(x: expr, t: typedesc): stmt {.immediate.} = 
-    var x: t
-    
-  template declareInNewScope(x: expr, t: typedesc): stmt {.immediate.} = 
-    # open a new scope:
-    block: 
-      var x: t
-
-  declareInScope(a, int)
-  a = 42  # works, `a` is known here
-  
-  declareInNewScope(b, int)
-  b = 42  # does not work, `b` is unknown
-
-
 Passing a code block to a template
 ----------------------------------
 
@@ -3538,50 +3626,28 @@ special ``:`` syntax:
 .. code-block:: nimrod
 
   template withFile(f, fn, mode: expr, actions: stmt): stmt {.immediate.} =
-    block:
-      var f: TFile
-      if open(f, fn, mode):
-        try:
-          actions
-        finally:
-          close(f)
-      else:
-        quit("cannot open: " & fn)
+    var f: TFile
+    if open(f, fn, mode):
+      try:
+        actions
+      finally:
+        close(f)
+    else:
+      quit("cannot open: " & fn)
       
   withFile(txt, "ttempl3.txt", fmWrite):
     txt.writeln("line 1")
     txt.writeln("line 2")
   
 In the example the two ``writeln`` statements are bound to the ``actions``
-parameter. 
-
-**Note:** The symbol binding rules for templates might change!
+parameter.
 
-Symbol binding within templates happens after template instantiation: 
 
-.. code-block:: nimrod
-  # Module A
-  var 
-    lastId = 0
-  
-  template genId*: expr =
-    inc(lastId)
-    lastId
-
-.. code-block:: nimrod
-  # Module B
-  import A
-  
-  echo genId() # Error: undeclared identifier: 'lastId'
-
-
-Bind statement
---------------
+Symbol binding in templates
+---------------------------
 
-Exporting a template is a often a leaky abstraction as it can depend on 
-symbols that are not visible from a client module. However, to compensate for
-this case, a `bind`:idx: statement can be used: It declares all identifiers
-that should be bound early (i.e. when the template is parsed):
+A template is a `hygienic`:idx: macro and so opens a new scope. Most symbols are
+bound from the definition scope of the template:
 
 .. code-block:: nimrod
   # Module A
@@ -3589,7 +3655,6 @@ that should be bound early (i.e. when the template is parsed):
     lastId = 0
   
   template genId*: expr =
-    bind lastId
     inc(lastId)
     lastId
 
@@ -3597,9 +3662,11 @@ that should be bound early (i.e. when the template is parsed):
   # Module B
   import A
   
-  echo genId() # Works
+  echo genId() # Works as 'lastId' has been bound in 'genId's defining scope
+
+As in generics symbol binding can be influenced via ``mixin`` or ``bind`` 
+statements.
 
-A ``bind`` statement can also be used in generics for the same purpose.
 
 
 Identifier construction
@@ -3942,13 +4009,13 @@ Static params can also appear in the signatures of generic types:
 
   type
     Matrix[M,N: static[int]; T: Number] = array[0..(M*N - 1), T]
-      # Please, note how `Number` is just a type constraint here, while
+      # Note how `Number` is just a type constraint here, while
       # `static[int]` requires us to supply a compile-time int value
 
     AffineTransform2D[T] = Matrix[3, 3, T]
     AffineTransform3D[T] = Matrix[4, 4, T]
 
-  AffineTransform3D[float] # OK
+  AffineTransform3D[float]  # OK
   AffineTransform2D[string] # Error, `string` is not a `Number`
 
 
@@ -4685,6 +4752,10 @@ 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``.
+
 
 delegator pragma
 ----------------
@@ -5173,9 +5244,9 @@ the same feature under the same name.
 Exportc pragma
 --------------
 The `exportc`:idx: pragma provides a means to export a type, a variable, or a
-procedure to C. The optional argument is a string containing the C identifier.
-If the argument is missing, the C name is the Nimrod
-identifier *exactly as spelled*:
+procedure to C. Enums and constants can't be exported. The optional argument
+is a string containing the C identifier.  If the argument is missing, the C
+name is the Nimrod identifier *exactly as spelled*:
 
 .. code-block:: Nimrod
   proc callme(formatstr: cstring) {.exportc: "callMe", varargs.}
diff --git a/doc/tut1.txt b/doc/tut1.txt
index 1ba3253c8..b70f40f4a 100644
--- a/doc/tut1.txt
+++ b/doc/tut1.txt
@@ -1321,6 +1321,30 @@ In this example ``$`` is applied to any argument that is passed to the
 parameter ``a``. Note that ``$`` applied to strings is a nop.
 
 
+Slices
+------
+
+Slices look similar to subranges types in syntax but are used in a different
+context. A slice is just an object of type TSlice which contains two bounds,
+`a` and `b`. By itself a slice is not very useful, but other collection types
+define operators which accept TSlice objects to define ranges.
+
+.. code-block:: nimrod
+
+  var
+    a = "Nimrod is a progamming language"
+    b = "Slices are useless."
+
+  echo a[10..15] # --> 'a prog'
+  b[11.. -2] = "useful"
+  echo b # --> 'Slices are useful.'
+
+In the previous example slices are used to modify a part of a string, and even
+a negative index is used. The slice's bounds can hold any value supported by
+their type, but it is the proc using the slice object which defines what values
+are accepted.
+
+
 Tuples
 ------
 
diff --git a/doc/tut2.txt b/doc/tut2.txt
index 581239cc7..6738c5551 100644
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -528,7 +528,7 @@ containers:
   proc newNode*[T](data: T): PBinaryTree[T] =
     # constructor for a node
     new(result)
-    result.dat = data
+    result.data = data
 
   proc add*[T](root: var PBinaryTree[T], n: PBinaryTree[T]) =
     # insert a node into the tree
@@ -569,7 +569,7 @@ containers:
       
   var
     root: PBinaryTree[string] # instantiate a PBinaryTree with ``string``
-  add(root, newNode("hallo")) # instantiates ``newNode`` and ``add``
+  add(root, newNode("hello")) # instantiates ``newNode`` and ``add``
   add(root, "world")          # instantiates the second ``add`` proc
   for str in preorder(root):
     stdout.writeln(str)
diff --git a/koch.nim b/koch.nim
index 35a86a597..4d2b3bfb7 100644
--- a/koch.nim
+++ b/koch.nim
@@ -266,8 +266,9 @@ proc tests(args: string) =
   # we compile the tester with taintMode:on to have a basic
   # taint mode test :-)
   exec "nimrod cc --taintMode:on tests/testament/tester"
-  exec quoteShell(getCurrentDir() / "tests/testament/tester".exe) & " " &
-      (args|"all")
+  let tester = quoteShell(getCurrentDir() / "tests/testament/tester".exe)
+  exec tester & " " & (args|"all")
+  exec tester & " html"
 
 proc temp(args: string) =
   var output = "compiler" / "nimrod".exe
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 3b36e31e0..585ccf869 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -294,19 +294,6 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst".}
   ##       if not `ex`:
   ##         echo `info` & ": Check failed: " & `expString`
   
-when not defined(booting):
-  template emit*(e: static[string]): stmt =
-    ## accepts a single string argument and treats it as nimrod code
-    ## that should be inserted verbatim in the program
-    ## Example:
-    ##
-    ## .. code-block:: nimrod
-    ##   emit("echo " & '"' & "hello world".toUpper & '"')
-    ##
-    macro payload: stmt {.gensym.} =
-      result = e.parseStmt
-    payload()
-
 proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
   ## checks that `n` is of kind `k`. If this is not the case,
   ## compilation aborts with an error message. This is useful for writing
@@ -421,7 +408,8 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
   of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
   of nnkStrLit..nnkTripleStrLit: add(result, $n.strVal)
   of nnkIdent: add(result, "!\"" & $n.ident & '"')
-  of nnkSym, nnkNone: assert false
+  of nnkSym: add(result, $n.symbol)
+  of nnkNone: assert false
   else:
     add(result, lispRepr(n[0]))
     for j in 1..n.len-1:
@@ -745,3 +733,15 @@ proc addIdentIfAbsent*(dest: PNimrodNode, ident: string) {.compiletime.} =
     else: discard
   dest.add(ident(ident))
 
+when not defined(booting):
+  template emit*(e: static[string]): stmt =
+    ## accepts a single string argument and treats it as nimrod code
+    ## that should be inserted verbatim in the program
+    ## Example:
+    ##
+    ## .. code-block:: nimrod
+    ##   emit("echo " & '"' & "hello world".toUpper & '"')
+    ##
+    macro payload: stmt {.gensym.} =
+      result = parseStmt(e)
+    payload()
diff --git a/lib/impure/db_mongo.nim b/lib/impure/db_mongo.nim
index d012f677f..dc8a808f2 100644
--- a/lib/impure/db_mongo.nim
+++ b/lib/impure/db_mongo.nim
@@ -58,7 +58,7 @@ proc open*(host: string = defaultHost, port: int = defaultPort): TDbConn {.
   ## be established.
   init(result)
   
-  let x = connect(result, host, port.cint)
+  let x = client(result, host, port.cint)
   if x != 0'i32:
     dbError(result, "cannot open: " & host)
 
@@ -119,7 +119,7 @@ proc insertId*(db: var TDbConn, namespace: string, data: PJsonNode): TOid {.
   ## the generated OID for the ``_id`` field.
   result = genOid()
   var x = jsonToBSon(data, result)
-  insert(db, namespace, x)
+  insert(db, namespace, x, nil)
   destroy(x)
 
 proc insert*(db: var TDbConn, namespace: string, data: PJsonNode) {.
diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim
index a3499a6df..809ee7039 100644
--- a/lib/impure/db_sqlite.nim
+++ b/lib/impure/db_sqlite.nim
@@ -148,7 +148,8 @@ proc getValue*(db: TDbConn, query: TSqlQuery,
   if finalize(stmt) != SQLITE_OK: dbError(db)
   
 proc tryInsertID*(db: TDbConn, query: TSqlQuery, 
-                  args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
+                  args: varargs[string, `$`]): int64
+                  {.tags: [FWriteDb], raises: [].} =
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row or -1 in case of an error. 
   var q = dbFormat(query, args)
@@ -157,7 +158,8 @@ proc tryInsertID*(db: TDbConn, query: TSqlQuery,
   if prepare_v2(db, q, q.len.cint, stmt, nil) == SQLITE_OK:
     if step(stmt) == SQLITE_DONE:
       result = last_insert_rowid(db)
-  if finalize(stmt) != SQLITE_OK: dbError(db)
+    if finalize(stmt) != SQLITE_OK:
+      result = -1
 
 proc insertID*(db: TDbConn, query: TSqlQuery, 
                args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = 
diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim
index db7a63928..4ca0c79e0 100644
--- a/lib/packages/docutils/highlite.nim
+++ b/lib/packages/docutils/highlite.nim
@@ -19,7 +19,7 @@ type
     gtEof, gtNone, gtWhitespace, gtDecNumber, gtBinNumber, gtHexNumber, 
     gtOctNumber, gtFloatNumber, gtIdentifier, gtKeyword, gtStringLit, 
     gtLongStringLit, gtCharLit, gtEscapeSequence, # escape sequence like \xff
-    gtOperator, gtPunctation, gtComment, gtLongComment, gtRegularExpression, 
+    gtOperator, gtPunctuation, gtComment, gtLongComment, gtRegularExpression, 
     gtTagStart, gtTagEnd, gtKey, gtValue, gtRawData, gtAssembler, 
     gtPreprocessor, gtDirective, gtCommand, gtRule, gtHyperlink, gtLabel, 
     gtReference, gtOther
@@ -39,7 +39,7 @@ const
   tokenClassToStr*: array[TTokenClass, string] = ["Eof", "None", "Whitespace", 
     "DecNumber", "BinNumber", "HexNumber", "OctNumber", "FloatNumber", 
     "Identifier", "Keyword", "StringLit", "LongStringLit", "CharLit", 
-    "EscapeSequence", "Operator", "Punctation", "Comment", "LongComment", 
+    "EscapeSequence", "Operator", "Punctuation", "Comment", "LongComment", 
     "RegularExpression", "TagStart", "TagEnd", "Key", "Value", "RawData", 
     "Assembler", "Preprocessor", "Directive", "Command", "Rule", "Hyperlink", 
     "Label", "Reference", "Other"]
@@ -258,7 +258,7 @@ proc nimNextToken(g: var TGeneralTokenizer) =
           else: inc(pos)
     of '(', ')', '[', ']', '{', '}', '`', ':', ',', ';': 
       inc(pos)
-      g.kind = gtPunctation
+      g.kind = gtPunctuation
     of '\0': 
       g.kind = gtEof
     else: 
@@ -473,7 +473,7 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openArray[string],
         else: inc(pos)
     of '(', ')', '[', ']', '{', '}', ':', ',', ';', '.': 
       inc(pos)
-      g.kind = gtPunctation
+      g.kind = gtPunctuation
     of '\0': 
       g.kind = gtEof
     else: 
diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim
new file mode 100644
index 000000000..d50394f60
--- /dev/null
+++ b/lib/posix/epoll.nim
@@ -0,0 +1,88 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2013 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+const
+  EPOLLIN* = 0x00000001
+  EPOLLPRI* = 0x00000002
+  EPOLLOUT* = 0x00000004
+  EPOLLERR* = 0x00000008
+  EPOLLHUP* = 0x00000010
+  EPOLLRDNORM* = 0x00000040
+  EPOLLRDBAND* = 0x00000080
+  EPOLLWRNORM* = 0x00000100
+  EPOLLWRBAND* = 0x00000200
+  EPOLLMSG* = 0x00000400
+  EPOLLRDHUP* = 0x00002000
+  EPOLLWAKEUP* = 1 shl 29
+  EPOLLONESHOT* = 1 shl 30
+  EPOLLET* = 1 shl 31
+
+# Valid opcodes ( "op" parameter ) to issue to epoll_ctl().
+
+const 
+  EPOLL_CTL_ADD* = 1          # Add a file descriptor to the interface.  
+  EPOLL_CTL_DEL* = 2          # Remove a file descriptor from the interface.  
+  EPOLL_CTL_MOD* = 3          # Change file descriptor epoll_event structure.  
+
+type 
+  epoll_data* {.importc: "union epoll_data", 
+      header: "<sys/epoll.h>", pure, final.} = object # TODO: This is actually a union.
+    thePtr* {.importc: "ptr".}: pointer # \
+    #fd*: cint
+    #u32*: uint32
+    #u64*: uint64
+
+  epoll_event* {.importc: "struct epoll_event", header: "<sys/epoll.h>", pure, final.} = object 
+    events*: uint32 # Epoll events 
+    data*: epoll_data # User data variable 
+
+proc epoll_create*(size: cint): cint {.importc: "epoll_create", 
+    header: "<sys/epoll.h>".}
+  ## Creates an epoll instance.  Returns an fd for the new instance.
+  ##   The "size" parameter is a hint specifying the number of file
+  ##   descriptors to be associated with the new instance.  The fd
+  ##   returned by epoll_create() should be closed with close().  
+
+proc epoll_create1*(flags: cint): cint {.importc: "epoll_create1", 
+    header: "<sys/epoll.h>".}
+  ## Same as epoll_create but with an FLAGS parameter.  The unused SIZE
+  ##   parameter has been dropped.  
+
+proc epoll_ctl*(epfd: cint; op: cint; fd: cint; event: ptr epoll_event): cint {.
+    importc: "epoll_ctl", header: "<sys/epoll.h>".}
+  ## Manipulate an epoll instance "epfd". Returns 0 in case of success,
+  ##   -1 in case of error ( the "errno" variable will contain the
+  ##   specific error code ) The "op" parameter is one of the EPOLL_CTL_*
+  ##   constants defined above. The "fd" parameter is the target of the
+  ##   operation. The "event" parameter describes which events the caller
+  ##   is interested in and any associated user data.  
+
+proc epoll_wait*(epfd: cint; events: ptr epoll_event; maxevents: cint; 
+                 timeout: cint): cint {.importc: "epoll_wait", 
+    header: "<sys/epoll.h>".}
+  ## Wait for events on an epoll instance "epfd". Returns the number of
+  ##   triggered events returned in "events" buffer. Or -1 in case of
+  ##   error with the "errno" variable set to the specific error code. The
+  ##   "events" parameter is a buffer that will contain triggered
+  ##   events. The "maxevents" is the maximum number of events to be
+  ##   returned ( usually size of "events" ). The "timeout" parameter
+  ##   specifies the maximum wait time in milliseconds (-1 == infinite).
+  ##
+  ##   This function is a cancellation point and therefore not marked with
+  ##   __THROW.
+
+
+#proc epoll_pwait*(epfd: cint; events: ptr epoll_event; maxevents: cint; 
+#                  timeout: cint; ss: ptr sigset_t): cint {.
+#    importc: "epoll_pwait", header: "<sys/epoll.h>".}
+# Same as epoll_wait, but the thread's signal mask is temporarily
+#   and atomically replaced with the one provided as parameter.
+#
+#   This function is a cancellation point and therefore not marked with
+#   __THROW.  
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index 685a1dafc..41260b36f 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -14,7 +14,7 @@
 
 ## This is a raw POSIX interface module. It does not not provide any
 ## convenience: cstrings are used instead of proper Nimrod strings and
-## return codes indicate errors. If you want exceptions 
+## return codes indicate errors. If you want exceptions
 ## and a proper Nimrod-like interface, use the OS module or write a wrapper.
 
 ## Coding conventions:
@@ -63,74 +63,74 @@ const
   MM_NULLTXT* = nil
   MM_NULLACT* = nil
   MM_NULLTAG* = nil
-  
+
   STDERR_FILENO* = 2 ## File number of stderr;
   STDIN_FILENO* = 0  ## File number of stdin;
-  STDOUT_FILENO* = 1 ## File number of stdout; 
+  STDOUT_FILENO* = 1 ## File number of stdout;
 
 when defined(endb):
   # to not break bootstrapping again ...
   type
-    TDIR* {.importc: "DIR", header: "<dirent.h>", 
+    TDIR* {.importc: "DIR", header: "<dirent.h>",
             final, pure, incompleteStruct.} = object
-      ## A type representing a directory stream. 
+      ## A type representing a directory stream.
 else:
   type
-    TDIR* {.importc: "DIR", header: "<dirent.h>", 
+    TDIR* {.importc: "DIR", header: "<dirent.h>",
             final, pure.} = object
-      ## A type representing a directory stream.   
-  
+      ## A type representing a directory stream.
+
 type
   TSocketHandle* = distinct cint # The type used to represent socket descriptors
 
-  Tdirent* {.importc: "struct dirent", 
+  Tdirent* {.importc: "struct dirent",
              header: "<dirent.h>", final, pure.} = object ## dirent_t struct
     d_ino*: Tino  ## File serial number.
     d_name*: array [0..255, char] ## Name of entry.
 
   Tflock* {.importc: "flock", final, pure,
             header: "<fcntl.h>".} = object ## flock type
-    l_type*: cshort   ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. 
-    l_whence*: cshort ## Flag for starting offset. 
-    l_start*: TOff    ## Relative offset in bytes. 
-    l_len*: TOff      ## Size; if 0 then until EOF. 
-    l_pid*: TPid      ## Process ID of the process holding the lock; 
-                      ## returned with F_GETLK. 
-  
-  Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final, pure.} = 
+    l_type*: cshort   ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK.
+    l_whence*: cshort ## Flag for starting offset.
+    l_start*: TOff    ## Relative offset in bytes.
+    l_len*: TOff      ## Size; if 0 then until EOF.
+    l_pid*: TPid      ## Process ID of the process holding the lock;
+                      ## returned with F_GETLK.
+
+  Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final, pure.} =
     object ## Represents the entire floating-point environment. The
            ## floating-point environment refers collectively to any
            ## floating-point status flags and control modes supported
            ## by the implementation.
-  Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final, pure.} = 
-    object ## Represents the floating-point status flags collectively, 
-           ## including any status the implementation associates with the 
-           ## flags. A floating-point status flag is a system variable 
+  Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final, pure.} =
+    object ## Represents the floating-point status flags collectively,
+           ## including any status the implementation associates with the
+           ## flags. A floating-point status flag is a system variable
            ## whose value is set (but never cleared) when a floating-point
            ## exception is raised, which occurs as a side effect of
            ## exceptional floating-point arithmetic to provide auxiliary
            ## information. A floating-point control mode is a system variable
-           ## whose value may be set by the user to affect the subsequent 
+           ## whose value may be set by the user to affect the subsequent
            ## behavior of floating-point arithmetic.
 
   TFTW* {.importc: "struct FTW", header: "<ftw.h>", final, pure.} = object
     base*: cint
     level*: cint
-    
-  TGlob* {.importc: "glob_t", header: "<glob.h>", 
+
+  TGlob* {.importc: "glob_t", header: "<glob.h>",
            final, pure.} = object ## glob_t
-    gl_pathc*: int          ## Count of paths matched by pattern. 
-    gl_pathv*: cstringArray ## Pointer to a list of matched pathnames. 
-    gl_offs*: int           ## Slots to reserve at the beginning of gl_pathv. 
-  
-  TGroup* {.importc: "struct group", header: "<grp.h>", 
+    gl_pathc*: int          ## Count of paths matched by pattern.
+    gl_pathv*: cstringArray ## Pointer to a list of matched pathnames.
+    gl_offs*: int           ## Slots to reserve at the beginning of gl_pathv.
+
+  TGroup* {.importc: "struct group", header: "<grp.h>",
             final, pure.} = object ## struct group
-    gr_name*: cstring     ## The name of the group. 
-    gr_gid*: TGid         ## Numerical group ID. 
-    gr_mem*: cstringArray ## Pointer to a null-terminated array of character 
-                          ## pointers to member names. 
+    gr_name*: cstring     ## The name of the group.
+    gr_gid*: TGid         ## Numerical group ID.
+    gr_mem*: cstringArray ## Pointer to a null-terminated array of character
+                          ## pointers to member names.
 
-  Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final, pure.} = 
+  Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final, pure.} =
     object ## Identifies the conversion from one codeset to another.
 
   Tlconv* {.importc: "struct lconv", header: "<locale.h>", final,
@@ -161,21 +161,21 @@ type
     thousands_sep*: cstring
 
   TMqd* {.importc: "mqd_t", header: "<mqueue.h>", final, pure.} = object
-  TMqAttr* {.importc: "struct mq_attr", 
-             header: "<mqueue.h>", 
+  TMqAttr* {.importc: "struct mq_attr",
+             header: "<mqueue.h>",
              final, pure.} = object ## message queue attribute
-    mq_flags*: int   ## Message queue flags. 
-    mq_maxmsg*: int  ## Maximum number of messages. 
-    mq_msgsize*: int ## Maximum message size. 
-    mq_curmsgs*: int ## Number of messages currently queued. 
+    mq_flags*: int   ## Message queue flags.
+    mq_maxmsg*: int  ## Maximum number of messages.
+    mq_msgsize*: int ## Maximum message size.
+    mq_curmsgs*: int ## Number of messages currently queued.
 
-  TPasswd* {.importc: "struct passwd", header: "<pwd.h>", 
+  TPasswd* {.importc: "struct passwd", header: "<pwd.h>",
              final, pure.} = object ## struct passwd
-    pw_name*: cstring   ## User's login name. 
-    pw_uid*: Tuid       ## Numerical user ID. 
-    pw_gid*: TGid       ## Numerical group ID. 
-    pw_dir*: cstring    ## Initial working directory. 
-    pw_shell*: cstring  ## Program to use as shell. 
+    pw_name*: cstring   ## User's login name.
+    pw_uid*: Tuid       ## Numerical user ID.
+    pw_gid*: TGid       ## Numerical group ID.
+    pw_dir*: cstring    ## Initial working directory.
+    pw_shell*: cstring  ## Program to use as shell.
 
   Tblkcnt* {.importc: "blkcnt_t", header: "<sys/types.h>".} = int
     ## used for file block counts
@@ -195,289 +195,289 @@ type
   TOff* {.importc: "off_t", header: "<sys/types.h>".} = int64
   TPid* {.importc: "pid_t", header: "<sys/types.h>".} = int
   Tpthread_attr* {.importc: "pthread_attr_t", header: "<sys/types.h>".} = int
-  Tpthread_barrier* {.importc: "pthread_barrier_t", 
+  Tpthread_barrier* {.importc: "pthread_barrier_t",
                       header: "<sys/types.h>".} = int
-  Tpthread_barrierattr* {.importc: "pthread_barrierattr_t", 
+  Tpthread_barrierattr* {.importc: "pthread_barrierattr_t",
                           header: "<sys/types.h>".} = int
   Tpthread_cond* {.importc: "pthread_cond_t", header: "<sys/types.h>".} = int
-  Tpthread_condattr* {.importc: "pthread_condattr_t", 
+  Tpthread_condattr* {.importc: "pthread_condattr_t",
                        header: "<sys/types.h>".} = int
   Tpthread_key* {.importc: "pthread_key_t", header: "<sys/types.h>".} = int
   Tpthread_mutex* {.importc: "pthread_mutex_t", header: "<sys/types.h>".} = int
-  Tpthread_mutexattr* {.importc: "pthread_mutexattr_t", 
+  Tpthread_mutexattr* {.importc: "pthread_mutexattr_t",
                         header: "<sys/types.h>".} = int
   Tpthread_once* {.importc: "pthread_once_t", header: "<sys/types.h>".} = int
-  Tpthread_rwlock* {.importc: "pthread_rwlock_t", 
+  Tpthread_rwlock* {.importc: "pthread_rwlock_t",
                      header: "<sys/types.h>".} = int
-  Tpthread_rwlockattr* {.importc: "pthread_rwlockattr_t", 
+  Tpthread_rwlockattr* {.importc: "pthread_rwlockattr_t",
                          header: "<sys/types.h>".} = int
-  Tpthread_spinlock* {.importc: "pthread_spinlock_t", 
+  Tpthread_spinlock* {.importc: "pthread_spinlock_t",
                        header: "<sys/types.h>".} = int
   Tpthread* {.importc: "pthread_t", header: "<sys/types.h>".} = int
   Tsuseconds* {.importc: "suseconds_t", header: "<sys/types.h>".} = int
   #Ttime* {.importc: "time_t", header: "<sys/types.h>".} = int
   Ttimer* {.importc: "timer_t", header: "<sys/types.h>".} = int
   Ttrace_attr* {.importc: "trace_attr_t", header: "<sys/types.h>".} = int
-  Ttrace_event_id* {.importc: "trace_event_id_t", 
+  Ttrace_event_id* {.importc: "trace_event_id_t",
                      header: "<sys/types.h>".} = int
-  Ttrace_event_set* {.importc: "trace_event_set_t", 
+  Ttrace_event_set* {.importc: "trace_event_set_t",
                       header: "<sys/types.h>".} = int
   Ttrace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int
   Tuid* {.importc: "uid_t", header: "<sys/types.h>".} = int
   Tuseconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
-  
-  Tutsname* {.importc: "struct utsname", 
-              header: "<sys/utsname.h>", 
+
+  Tutsname* {.importc: "struct utsname",
+              header: "<sys/utsname.h>",
               final, pure.} = object ## struct utsname
-    sysname*,      ## Name of this implementation of the operating system. 
-      nodename*,   ## Name of this node within the communications 
-                   ## network to which this node is attached, if any. 
-      release*,    ## Current release level of this implementation. 
-      version*,    ## Current version level of this release. 
+    sysname*,      ## Name of this implementation of the operating system.
+      nodename*,   ## Name of this node within the communications
+                   ## network to which this node is attached, if any.
+      release*,    ## Current release level of this implementation.
+      version*,    ## Current version level of this release.
       machine*: array [0..255, char] ## Name of the hardware type on which the
-                                     ## system is running. 
+                                     ## system is running.
 
   TSem* {.importc: "sem_t", header: "<semaphore.h>", final, pure.} = object
-  Tipc_perm* {.importc: "struct ipc_perm", 
+  Tipc_perm* {.importc: "struct ipc_perm",
                header: "<sys/ipc.h>", final, pure.} = object ## struct ipc_perm
-    uid*: Tuid    ## Owner's user ID. 
-    gid*: TGid    ## Owner's group ID. 
-    cuid*: Tuid   ## Creator's user ID. 
-    cgid*: TGid   ## Creator's group ID. 
-    mode*: TMode  ## Read/write permission. 
-  
-  TStat* {.importc: "struct stat", 
+    uid*: Tuid    ## Owner's user ID.
+    gid*: TGid    ## Owner's group ID.
+    cuid*: Tuid   ## Creator's user ID.
+    cgid*: TGid   ## Creator's group ID.
+    mode*: TMode  ## Read/write permission.
+
+  TStat* {.importc: "struct stat",
            header: "<sys/stat.h>", final, pure.} = object ## struct stat
-    st_dev*: TDev          ## Device ID of device containing file. 
-    st_ino*: Tino          ## File serial number. 
-    st_mode*: TMode        ## Mode of file (see below). 
-    st_nlink*: TNlink      ## Number of hard links to the file. 
-    st_uid*: Tuid          ## User ID of file. 
-    st_gid*: TGid          ## Group ID of file. 
-    st_rdev*: TDev         ## Device ID (if file is character or block special). 
-    st_size*: TOff         ## For regular files, the file size in bytes. 
-                           ## For symbolic links, the length in bytes of the 
-                           ## pathname contained in the symbolic link. 
-                           ## For a shared memory object, the length in bytes. 
-                           ## For a typed memory object, the length in bytes. 
-                           ## For other file types, the use of this field is 
-                           ## unspecified. 
-    st_atime*: TTime       ## Time of last access. 
-    st_mtime*: TTime       ## Time of last data modification. 
-    st_ctime*: TTime       ## Time of last status change. 
-    st_blksize*: Tblksize  ## A file system-specific preferred I/O block size  
-                           ## for this object. In some file system types, this 
-                           ## may vary from file to file. 
-    st_blocks*: Tblkcnt    ## Number of blocks allocated for this object. 
-
-  
-  TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>", 
+    st_dev*: TDev          ## Device ID of device containing file.
+    st_ino*: Tino          ## File serial number.
+    st_mode*: TMode        ## Mode of file (see below).
+    st_nlink*: TNlink      ## Number of hard links to the file.
+    st_uid*: Tuid          ## User ID of file.
+    st_gid*: TGid          ## Group ID of file.
+    st_rdev*: TDev         ## Device ID (if file is character or block special).
+    st_size*: TOff         ## For regular files, the file size in bytes.
+                           ## For symbolic links, the length in bytes of the
+                           ## pathname contained in the symbolic link.
+                           ## For a shared memory object, the length in bytes.
+                           ## For a typed memory object, the length in bytes.
+                           ## For other file types, the use of this field is
+                           ## unspecified.
+    st_atime*: TTime       ## Time of last access.
+    st_mtime*: TTime       ## Time of last data modification.
+    st_ctime*: TTime       ## Time of last status change.
+    st_blksize*: Tblksize  ## A file system-specific preferred I/O block size
+                           ## for this object. In some file system types, this
+                           ## may vary from file to file.
+    st_blocks*: Tblkcnt    ## Number of blocks allocated for this object.
+
+
+  TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>",
               final, pure.} = object ## struct statvfs
-    f_bsize*: int        ## File system block size. 
-    f_frsize*: int       ## Fundamental file system block size. 
+    f_bsize*: int        ## File system block size.
+    f_frsize*: int       ## Fundamental file system block size.
     f_blocks*: Tfsblkcnt ## Total number of blocks on file system
-                         ## in units of f_frsize. 
-    f_bfree*: Tfsblkcnt  ## Total number of free blocks. 
-    f_bavail*: Tfsblkcnt ## Number of free blocks available to 
-                         ## non-privileged process. 
-    f_files*: Tfsfilcnt  ## Total number of file serial numbers. 
-    f_ffree*: Tfsfilcnt  ## Total number of free file serial numbers. 
-    f_favail*: Tfsfilcnt ## Number of file serial numbers available to 
-                         ## non-privileged process. 
-    f_fsid*: int         ## File system ID. 
-    f_flag*: int         ## Bit mask of f_flag values. 
-    f_namemax*: int      ## Maximum filename length. 
-
-  Tposix_typed_mem_info* {.importc: "struct posix_typed_mem_info", 
+                         ## in units of f_frsize.
+    f_bfree*: Tfsblkcnt  ## Total number of free blocks.
+    f_bavail*: Tfsblkcnt ## Number of free blocks available to
+                         ## non-privileged process.
+    f_files*: Tfsfilcnt  ## Total number of file serial numbers.
+    f_ffree*: Tfsfilcnt  ## Total number of free file serial numbers.
+    f_favail*: Tfsfilcnt ## Number of file serial numbers available to
+                         ## non-privileged process.
+    f_fsid*: int         ## File system ID.
+    f_flag*: int         ## Bit mask of f_flag values.
+    f_namemax*: int      ## Maximum filename length.
+
+  Tposix_typed_mem_info* {.importc: "struct posix_typed_mem_info",
                            header: "<sys/mman.h>", final, pure.} = object
     posix_tmi_length*: int
-  
-  Ttm* {.importc: "struct tm", header: "<time.h>", 
+
+  Ttm* {.importc: "struct tm", header: "<time.h>",
          final, pure.} = object ## struct tm
-    tm_sec*: cint   ## Seconds [0,60]. 
-    tm_min*: cint   ## Minutes [0,59]. 
-    tm_hour*: cint  ## Hour [0,23]. 
-    tm_mday*: cint  ## Day of month [1,31]. 
-    tm_mon*: cint   ## Month of year [0,11]. 
-    tm_year*: cint  ## Years since 1900. 
-    tm_wday*: cint  ## Day of week [0,6] (Sunday =0). 
-    tm_yday*: cint  ## Day of year [0,365]. 
-    tm_isdst*: cint ## Daylight Savings flag. 
-  Ttimespec* {.importc: "struct timespec", 
+    tm_sec*: cint   ## Seconds [0,60].
+    tm_min*: cint   ## Minutes [0,59].
+    tm_hour*: cint  ## Hour [0,23].
+    tm_mday*: cint  ## Day of month [1,31].
+    tm_mon*: cint   ## Month of year [0,11].
+    tm_year*: cint  ## Years since 1900.
+    tm_wday*: cint  ## Day of week [0,6] (Sunday =0).
+    tm_yday*: cint  ## Day of year [0,365].
+    tm_isdst*: cint ## Daylight Savings flag.
+  Ttimespec* {.importc: "struct timespec",
                header: "<time.h>", final, pure.} = object ## struct timespec
-    tv_sec*: TTime ## Seconds. 
-    tv_nsec*: int  ## Nanoseconds. 
-  titimerspec* {.importc: "struct itimerspec", header: "<time.h>", 
+    tv_sec*: TTime ## Seconds.
+    tv_nsec*: int  ## Nanoseconds.
+  titimerspec* {.importc: "struct itimerspec", header: "<time.h>",
                  final, pure.} = object ## struct itimerspec
-    it_interval*: Ttimespec ## Timer period. 
-    it_value*: Ttimespec    ## Timer expiration. 
-  
+    it_interval*: Ttimespec ## Timer period.
+    it_value*: Ttimespec    ## Timer expiration.
+
   Tsig_atomic* {.importc: "sig_atomic_t", header: "<signal.h>".} = cint
-    ## Possibly volatile-qualified integer type of an object that can be 
+    ## Possibly volatile-qualified integer type of an object that can be
     ## accessed as an atomic entity, even in the presence of asynchronous
     ## interrupts.
   Tsigset* {.importc: "sigset_t", header: "<signal.h>", final, pure.} = object
-  
-  TsigEvent* {.importc: "struct sigevent", 
+
+  TsigEvent* {.importc: "struct sigevent",
                header: "<signal.h>", final, pure.} = object ## struct sigevent
-    sigev_notify*: cint           ## Notification type. 
-    sigev_signo*: cint            ## Signal number. 
-    sigev_value*: TsigVal         ## Signal value. 
-    sigev_notify_function*: proc (x: TsigVal) {.noconv.} ## Notification func. 
+    sigev_notify*: cint           ## Notification type.
+    sigev_signo*: cint            ## Signal number.
+    sigev_value*: TsigVal         ## Signal value.
+    sigev_notify_function*: proc (x: TsigVal) {.noconv.} ## Notification func.
     sigev_notify_attributes*: ptr Tpthread_attr ## Notification attributes.
 
-  TsigVal* {.importc: "union sigval", 
+  TsigVal* {.importc: "union sigval",
              header: "<signal.h>", final, pure.} = object ## struct sigval
-    sival_ptr*: pointer ## pointer signal value; 
+    sival_ptr*: pointer ## pointer signal value;
                         ## integer signal value not defined!
-  TSigaction* {.importc: "struct sigaction", 
+  TSigaction* {.importc: "struct sigaction",
                 header: "<signal.h>", final, pure.} = object ## struct sigaction
     sa_handler*: proc (x: cint) {.noconv.}  ## Pointer to a signal-catching
-                                            ## function or one of the macros 
-                                            ## SIG_IGN or SIG_DFL. 
-    sa_mask*: Tsigset ## Set of signals to be blocked during execution of 
-                      ## the signal handling function. 
-    sa_flags*: cint   ## Special flags. 
+                                            ## function or one of the macros
+                                            ## SIG_IGN or SIG_DFL.
+    sa_mask*: Tsigset ## Set of signals to be blocked during execution of
+                      ## the signal handling function.
+    sa_flags*: cint   ## Special flags.
     sa_sigaction*: proc (x: cint, y: var TsigInfo, z: pointer) {.noconv.}
 
   TStack* {.importc: "stack_t",
             header: "<signal.h>", final, pure.} = object ## stack_t
-    ss_sp*: pointer  ## Stack base or pointer. 
-    ss_size*: int    ## Stack size. 
-    ss_flags*: cint  ## Flags. 
+    ss_sp*: pointer  ## Stack base or pointer.
+    ss_size*: int    ## Stack size.
+    ss_flags*: cint  ## Flags.
 
-  TSigStack* {.importc: "struct sigstack", 
+  TSigStack* {.importc: "struct sigstack",
                header: "<signal.h>", final, pure.} = object ## struct sigstack
-    ss_onstack*: cint ## Non-zero when signal stack is in use. 
-    ss_sp*: pointer   ## Signal stack pointer. 
+    ss_onstack*: cint ## Non-zero when signal stack is in use.
+    ss_sp*: pointer   ## Signal stack pointer.
 
-  TsigInfo* {.importc: "siginfo_t", 
+  TsigInfo* {.importc: "siginfo_t",
               header: "<signal.h>", final, pure.} = object ## siginfo_t
-    si_signo*: cint    ## Signal number. 
-    si_code*: cint     ## Signal code. 
-    si_errno*: cint    ## If non-zero, an errno value associated with 
-                       ## this signal, as defined in <errno.h>. 
-    si_pid*: TPid      ## Sending process ID. 
-    si_uid*: Tuid      ## Real user ID of sending process. 
-    si_addr*: pointer  ## Address of faulting instruction. 
-    si_status*: cint   ## Exit value or signal. 
-    si_band*: int      ## Band event for SIGPOLL. 
-    si_value*: TsigVal ## Signal value. 
-  
+    si_signo*: cint    ## Signal number.
+    si_code*: cint     ## Signal code.
+    si_errno*: cint    ## If non-zero, an errno value associated with
+                       ## this signal, as defined in <errno.h>.
+    si_pid*: TPid      ## Sending process ID.
+    si_uid*: Tuid      ## Real user ID of sending process.
+    si_addr*: pointer  ## Address of faulting instruction.
+    si_status*: cint   ## Exit value or signal.
+    si_band*: int      ## Band event for SIGPOLL.
+    si_value*: TsigVal ## Signal value.
+
   Tnl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint
   Tnl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = cint
 
-  Tsched_param* {.importc: "struct sched_param", 
-                  header: "<sched.h>", 
+  Tsched_param* {.importc: "struct sched_param",
+                  header: "<sched.h>",
                   final, pure.} = object ## struct sched_param
     sched_priority*: cint
-    sched_ss_low_priority*: cint     ## Low scheduling priority for 
-                                     ## sporadic server. 
-    sched_ss_repl_period*: Ttimespec ## Replenishment period for 
-                                     ## sporadic server. 
-    sched_ss_init_budget*: Ttimespec ## Initial budget for sporadic server. 
-    sched_ss_max_repl*: cint         ## Maximum pending replenishments for 
-                                     ## sporadic server. 
-
-  Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>", 
+    sched_ss_low_priority*: cint     ## Low scheduling priority for
+                                     ## sporadic server.
+    sched_ss_repl_period*: Ttimespec ## Replenishment period for
+                                     ## sporadic server.
+    sched_ss_init_budget*: Ttimespec ## Initial budget for sporadic server.
+    sched_ss_max_repl*: cint         ## Maximum pending replenishments for
+                                     ## sporadic server.
+
+  Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>",
               final, pure.} = object ## struct timeval
-    tv_sec*: int       ## Seconds. 
-    tv_usec*: int ## Microseconds. 
-  TFdSet* {.importc: "fd_set", header: "<sys/select.h>", 
+    tv_sec*: int       ## Seconds.
+    tv_usec*: int ## Microseconds.
+  TFdSet* {.importc: "fd_set", header: "<sys/select.h>",
             final, pure.} = object
-  Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", 
+  Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>",
                final, pure.} = object
-  Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>", 
+  Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>",
                final, pure.} = object ## ucontext_t
-    uc_link*: ptr Tucontext ## Pointer to the context that is resumed 
-                            ## when this context returns. 
-    uc_sigmask*: Tsigset    ## The set of signals that are blocked when this 
-                            ## context is active. 
-    uc_stack*: TStack       ## The stack used by this context. 
-    uc_mcontext*: Tmcontext ## A machine-specific representation of the saved 
-                            ## context. 
+    uc_link*: ptr Tucontext ## Pointer to the context that is resumed
+                            ## when this context returns.
+    uc_sigmask*: Tsigset    ## The set of signals that are blocked when this
+                            ## context is active.
+    uc_stack*: TStack       ## The stack used by this context.
+    uc_mcontext*: Tmcontext ## A machine-specific representation of the saved
+                            ## context.
 
 when hasAioH:
   type
-    Taiocb* {.importc: "struct aiocb", header: "<aio.h>", 
+    Taiocb* {.importc: "struct aiocb", header: "<aio.h>",
               final, pure.} = object ## struct aiocb
-      aio_fildes*: cint         ## File descriptor. 
-      aio_offset*: TOff         ## File offset. 
-      aio_buf*: pointer         ## Location of buffer. 
-      aio_nbytes*: int          ## Length of transfer. 
-      aio_reqprio*: cint        ## Request priority offset. 
-      aio_sigevent*: TsigEvent  ## Signal number and value. 
-      aio_lio_opcode: cint      ## Operation to be performed. 
- 
+      aio_fildes*: cint         ## File descriptor.
+      aio_offset*: TOff         ## File offset.
+      aio_buf*: pointer         ## Location of buffer.
+      aio_nbytes*: int          ## Length of transfer.
+      aio_reqprio*: cint        ## Request priority offset.
+      aio_sigevent*: TsigEvent  ## Signal number and value.
+      aio_lio_opcode: cint      ## Operation to be performed.
+
 when hasSpawnH:
   type
-    Tposix_spawnattr* {.importc: "posix_spawnattr_t", 
+    Tposix_spawnattr* {.importc: "posix_spawnattr_t",
                         header: "<spawn.h>", final, pure.} = object
-    Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", 
+    Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t",
                                  header: "<spawn.h>", final, pure.} = object
 
 type
   TSocklen* {.importc: "socklen_t", header: "<sys/socket.h>".} = cuint
   TSa_Family* {.importc: "sa_family_t", header: "<sys/socket.h>".} = cint
-  
-  TSockAddr* {.importc: "struct sockaddr", header: "<sys/socket.h>", 
+
+  TSockAddr* {.importc: "struct sockaddr", header: "<sys/socket.h>",
                pure, final.} = object ## struct sockaddr
-    sa_family*: TSa_Family         ## Address family. 
-    sa_data*: array [0..255, char] ## Socket address (variable-length data). 
-  
+    sa_family*: TSa_Family         ## Address family.
+    sa_data*: array [0..255, char] ## Socket address (variable-length data).
+
   Tsockaddr_storage* {.importc: "struct sockaddr_storage",
-                       header: "<sys/socket.h>", 
+                       header: "<sys/socket.h>",
                        pure, final.} = object ## struct sockaddr_storage
-    ss_family*: TSa_Family ## Address family. 
+    ss_family*: TSa_Family ## Address family.
 
-  Tif_nameindex* {.importc: "struct if_nameindex", final, 
+  Tif_nameindex* {.importc: "struct if_nameindex", final,
                    pure, header: "<net/if.h>".} = object ## struct if_nameindex
-    if_index*: cint   ## Numeric index of the interface. 
-    if_name*: cstring ## Null-terminated name of the interface. 
+    if_index*: cint   ## Numeric index of the interface.
+    if_name*: cstring ## Null-terminated name of the interface.
 
 
   TIOVec* {.importc: "struct iovec", pure, final,
             header: "<sys/uio.h>".} = object ## struct iovec
-    iov_base*: pointer ## Base address of a memory region for input or output. 
-    iov_len*: int    ## The size of the memory pointed to by iov_base. 
-    
+    iov_base*: pointer ## Base address of a memory region for input or output.
+    iov_len*: int    ## The size of the memory pointed to by iov_base.
+
   Tmsghdr* {.importc: "struct msghdr", pure, final,
              header: "<sys/socket.h>".} = object  ## struct msghdr
-    msg_name*: pointer  ## Optional address. 
-    msg_namelen*: TSocklen  ## Size of address. 
-    msg_iov*: ptr TIOVec    ## Scatter/gather array. 
-    msg_iovlen*: cint   ## Members in msg_iov. 
-    msg_control*: pointer  ## Ancillary data; see below. 
-    msg_controllen*: TSocklen ## Ancillary data buffer len. 
-    msg_flags*: cint ## Flags on received message. 
+    msg_name*: pointer  ## Optional address.
+    msg_namelen*: TSocklen  ## Size of address.
+    msg_iov*: ptr TIOVec    ## Scatter/gather array.
+    msg_iovlen*: cint   ## Members in msg_iov.
+    msg_control*: pointer  ## Ancillary data; see below.
+    msg_controllen*: TSocklen ## Ancillary data buffer len.
+    msg_flags*: cint ## Flags on received message.
 
 
-  Tcmsghdr* {.importc: "struct cmsghdr", pure, final, 
+  Tcmsghdr* {.importc: "struct cmsghdr", pure, final,
               header: "<sys/socket.h>".} = object ## struct cmsghdr
-    cmsg_len*: TSocklen ## Data byte count, including the cmsghdr. 
-    cmsg_level*: cint   ## Originating protocol. 
-    cmsg_type*: cint    ## Protocol-specific type. 
+    cmsg_len*: TSocklen ## Data byte count, including the cmsghdr.
+    cmsg_level*: cint   ## Originating protocol.
+    cmsg_type*: cint    ## Protocol-specific type.
 
-  TLinger* {.importc: "struct linger", pure, final, 
+  TLinger* {.importc: "struct linger", pure, final,
              header: "<sys/socket.h>".} = object ## struct linger
-    l_onoff*: cint  ## Indicates whether linger option is enabled. 
-    l_linger*: cint ## Linger time, in seconds. 
-  
+    l_onoff*: cint  ## Indicates whether linger option is enabled.
+    l_linger*: cint ## Linger time, in seconds.
+
   TInPort* = int16 ## unsigned!
   TInAddrScalar* = int32 ## unsigned!
 
   TInAddrT* {.importc: "in_addr_t", pure, final,
              header: "<netinet/in.h>".} = int32 ## unsigned!
 
-  TInAddr* {.importc: "struct in_addr", pure, final, 
+  TInAddr* {.importc: "struct in_addr", pure, final,
              header: "<netinet/in.h>".} = object ## struct in_addr
     s_addr*: TInAddrScalar
 
-  Tsockaddr_in* {.importc: "struct sockaddr_in", pure, final, 
+  Tsockaddr_in* {.importc: "struct sockaddr_in", pure, final,
                   header: "<netinet/in.h>".} = object ## struct sockaddr_in
-    sin_family*: TSa_Family ## AF_INET. 
-    sin_port*: TInPort      ## Port number. 
-    sin_addr*: TInAddr      ## IP address. 
+    sin_family*: TSa_Family ## AF_INET.
+    sin_port*: TInPort      ## Port number.
+    sin_addr*: TInAddr      ## IP address.
 
   TIn6Addr* {.importc: "struct in6_addr", pure, final,
               header: "<netinet/in.h>".} = object ## struct in6_addr
@@ -485,75 +485,75 @@ type
 
   Tsockaddr_in6* {.importc: "struct sockaddr_in6", pure, final,
                    header: "<netinet/in.h>".} = object ## struct sockaddr_in6
-    sin6_family*: TSa_Family ## AF_INET6. 
-    sin6_port*: TInPort      ## Port number. 
-    sin6_flowinfo*: int32    ## IPv6 traffic class and flow information. 
-    sin6_addr*: TIn6Addr     ## IPv6 address. 
-    sin6_scope_id*: int32    ## Set of interfaces for a scope. 
-  
-  Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final, 
+    sin6_family*: TSa_Family ## AF_INET6.
+    sin6_port*: TInPort      ## Port number.
+    sin6_flowinfo*: int32    ## IPv6 traffic class and flow information.
+    sin6_addr*: TIn6Addr     ## IPv6 address.
+    sin6_scope_id*: int32    ## Set of interfaces for a scope.
+
+  Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final,
                 header: "<netinet/in.h>".} = object ## struct ipv6_mreq
-    ipv6mr_multiaddr*: TIn6Addr ## IPv6 multicast address. 
-    ipv6mr_interface*: cint     ## Interface index. 
+    ipv6mr_multiaddr*: TIn6Addr ## IPv6 multicast address.
+    ipv6mr_interface*: cint     ## Interface index.
 
-  Thostent* {.importc: "struct hostent", pure, final, 
+  Thostent* {.importc: "struct hostent", pure, final,
               header: "<netdb.h>".} = object ## struct hostent
-    h_name*: cstring           ## Official name of the host. 
-    h_aliases*: cstringArray   ## A pointer to an array of pointers to 
-                               ## alternative host names, terminated by a 
-                               ## null pointer. 
-    h_addrtype*: cint          ## Address type. 
-    h_length*: cint            ## The length, in bytes, of the address. 
-    h_addr_list*: cstringArray ## A pointer to an array of pointers to network 
+    h_name*: cstring           ## Official name of the host.
+    h_aliases*: cstringArray   ## A pointer to an array of pointers to
+                               ## alternative host names, terminated by a
+                               ## null pointer.
+    h_addrtype*: cint          ## Address type.
+    h_length*: cint            ## The length, in bytes, of the address.
+    h_addr_list*: cstringArray ## A pointer to an array of pointers to network
                                ## addresses (in network byte order) for the
-                               ## host, terminated by a null pointer. 
+                               ## host, terminated by a null pointer.
 
-  Tnetent* {.importc: "struct netent", pure, final, 
+  Tnetent* {.importc: "struct netent", pure, final,
               header: "<netdb.h>".} = object ## struct netent
-    n_name*: cstring         ## Official, fully-qualified (including the 
-                             ## domain) name of the host. 
-    n_aliases*: cstringArray ## A pointer to an array of pointers to 
-                             ## alternative network names, terminated by a 
-                             ## null pointer. 
-    n_addrtype*: cint        ## The address type of the network. 
-    n_net*: int32            ## The network number, in host byte order. 
-
-  TProtoent* {.importc: "struct protoent", pure, final, 
+    n_name*: cstring         ## Official, fully-qualified (including the
+                             ## domain) name of the host.
+    n_aliases*: cstringArray ## A pointer to an array of pointers to
+                             ## alternative network names, terminated by a
+                             ## null pointer.
+    n_addrtype*: cint        ## The address type of the network.
+    n_net*: int32            ## The network number, in host byte order.
+
+  TProtoent* {.importc: "struct protoent", pure, final,
               header: "<netdb.h>".} = object ## struct protoent
-    p_name*: cstring         ## Official name of the protocol. 
-    p_aliases*: cstringArray ## A pointer to an array of pointers to 
-                             ## alternative protocol names, terminated by 
-                             ## a null pointer. 
-    p_proto*: cint           ## The protocol number. 
+    p_name*: cstring         ## Official name of the protocol.
+    p_aliases*: cstringArray ## A pointer to an array of pointers to
+                             ## alternative protocol names, terminated by
+                             ## a null pointer.
+    p_proto*: cint           ## The protocol number.
 
-  TServent* {.importc: "struct servent", pure, final, 
+  TServent* {.importc: "struct servent", pure, final,
               header: "<netdb.h>".} = object ## struct servent
-    s_name*: cstring         ## Official name of the service. 
-    s_aliases*: cstringArray ## A pointer to an array of pointers to 
-                             ## alternative service names, terminated by 
-                             ## a null pointer. 
-    s_port*: cint            ## The port number at which the service 
-                             ## resides, in network byte order. 
-    s_proto*: cstring        ## The name of the protocol to use when 
-                             ## contacting the service. 
-
-  Taddrinfo* {.importc: "struct addrinfo", pure, final, 
+    s_name*: cstring         ## Official name of the service.
+    s_aliases*: cstringArray ## A pointer to an array of pointers to
+                             ## alternative service names, terminated by
+                             ## a null pointer.
+    s_port*: cint            ## The port number at which the service
+                             ## resides, in network byte order.
+    s_proto*: cstring        ## The name of the protocol to use when
+                             ## contacting the service.
+
+  Taddrinfo* {.importc: "struct addrinfo", pure, final,
               header: "<netdb.h>".} = object ## struct addrinfo
-    ai_flags*: cint         ## Input flags. 
-    ai_family*: cint        ## Address family of socket. 
-    ai_socktype*: cint      ## Socket type. 
-    ai_protocol*: cint      ## Protocol of socket. 
-    ai_addrlen*: TSocklen   ## Length of socket address. 
-    ai_addr*: ptr TSockAddr ## Socket address of socket. 
-    ai_canonname*: cstring  ## Canonical name of service location. 
-    ai_next*: ptr Taddrinfo ## Pointer to next in list. 
-  
-  TPollfd* {.importc: "struct pollfd", pure, final, 
+    ai_flags*: cint         ## Input flags.
+    ai_family*: cint        ## Address family of socket.
+    ai_socktype*: cint      ## Socket type.
+    ai_protocol*: cint      ## Protocol of socket.
+    ai_addrlen*: TSocklen   ## Length of socket address.
+    ai_addr*: ptr TSockAddr ## Socket address of socket.
+    ai_canonname*: cstring  ## Canonical name of service location.
+    ai_next*: ptr Taddrinfo ## Pointer to next in list.
+
+  TPollfd* {.importc: "struct pollfd", pure, final,
              header: "<poll.h>".} = object ## struct pollfd
-    fd*: cint        ## The following descriptor being polled. 
-    events*: cshort  ## The input event flags (see below). 
-    revents*: cshort ## The output event flags (see below).  
-  
+    fd*: cint        ## The following descriptor being polled.
+    events*: cshort  ## The input event flags (see below).
+    revents*: cshort ## The output event flags (see below).
+
   Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
 
 var
@@ -561,31 +561,31 @@ var
   h_errno* {.importc, header: "<netdb.h>".}: cint
   daylight* {.importc, header: "<time.h>".}: cint
   timezone* {.importc, header: "<time.h>".}: int
-  
+
 # Constants as variables:
 when hasAioH:
   var
     AIO_ALLDONE* {.importc, header: "<aio.h>".}: cint
-      ## A return value indicating that none of the requested operations 
+      ## A return value indicating that none of the requested operations
       ## could be canceled since they are already complete.
     AIO_CANCELED* {.importc, header: "<aio.h>".}: cint
       ## A return value indicating that all requested operations have
       ## been canceled.
     AIO_NOTCANCELED* {.importc, header: "<aio.h>".}: cint
-      ## A return value indicating that some of the requested operations could 
+      ## A return value indicating that some of the requested operations could
       ## not be canceled since they are in progress.
     LIO_NOP* {.importc, header: "<aio.h>".}: cint
       ## A lio_listio() element operation option indicating that no transfer is
       ## requested.
     LIO_NOWAIT* {.importc, header: "<aio.h>".}: cint
-      ## A lio_listio() synchronization operation indicating that the calling 
-      ## thread is to continue execution while the lio_listio() operation is 
+      ## A lio_listio() synchronization operation indicating that the calling
+      ## thread is to continue execution while the lio_listio() operation is
       ## being performed, and no notification is given when the operation is
       ## complete.
     LIO_READ* {.importc, header: "<aio.h>".}: cint
       ## A lio_listio() element operation option requesting a read.
     LIO_WAIT* {.importc, header: "<aio.h>".}: cint
-      ## A lio_listio() synchronization operation indicating that the calling 
+      ## A lio_listio() synchronization operation indicating that the calling
       ## thread is to suspend until the lio_listio() operation is complete.
     LIO_WRITE* {.importc, header: "<aio.h>".}: cint
       ## A lio_listio() element operation option requesting a write.
@@ -598,9 +598,9 @@ var
   RTLD_GLOBAL* {.importc, header: "<dlfcn.h>".}: cint
     ## All symbols are available for relocation processing of other modules.
   RTLD_LOCAL* {.importc, header: "<dlfcn.h>".}: cint
-    ## All symbols are not made available for relocation processing by 
-    ## other modules. 
-    
+    ## All symbols are not made available for relocation processing by
+    ## other modules.
+
   E2BIG* {.importc, header: "<errno.h>".}: cint
       ## Argument list too long.
   EACCES* {.importc, header: "<errno.h>".}: cint
@@ -758,7 +758,7 @@ var
   EWOULDBLOCK* {.importc, header: "<errno.h>".}: cint
       ## Operation would block (may be the same value as [EAGAIN]).
   EXDEV* {.importc, header: "<errno.h>".}: cint
-      ## Cross-device link.   
+      ## Cross-device link.
 
   F_DUPFD* {.importc, header: "<fcntl.h>".}: cint
     ## Duplicate file descriptor.
@@ -779,15 +779,15 @@ var
   F_GETOWN* {.importc, header: "<fcntl.h>".}: cint
     ## Get process or process group ID to receive SIGURG signals.
   F_SETOWN* {.importc, header: "<fcntl.h>".}: cint
-    ## Set process or process group ID to receive SIGURG signals. 
+    ## Set process or process group ID to receive SIGURG signals.
   FD_CLOEXEC* {.importc, header: "<fcntl.h>".}: cint
-    ## Close the file descriptor upon execution of an exec family function. 
+    ## Close the file descriptor upon execution of an exec family function.
   F_RDLCK* {.importc, header: "<fcntl.h>".}: cint
     ## Shared or read lock.
   F_UNLCK* {.importc, header: "<fcntl.h>".}: cint
     ## Unlock.
   F_WRLCK* {.importc, header: "<fcntl.h>".}: cint
-    ## Exclusive or write lock. 
+    ## Exclusive or write lock.
   O_CREAT* {.importc, header: "<fcntl.h>".}: cint
     ## Create file if it does not exist.
   O_EXCL* {.importc, header: "<fcntl.h>".}: cint
@@ -795,7 +795,7 @@ var
   O_NOCTTY* {.importc, header: "<fcntl.h>".}: cint
     ## Do not assign controlling terminal.
   O_TRUNC* {.importc, header: "<fcntl.h>".}: cint
-    ## Truncate flag. 
+    ## Truncate flag.
   O_APPEND* {.importc, header: "<fcntl.h>".}: cint
     ## Set append mode.
   O_DSYNC* {.importc, header: "<fcntl.h>".}: cint
@@ -805,21 +805,21 @@ var
   O_RSYNC* {.importc, header: "<fcntl.h>".}: cint
     ## Synchronized read I/O operations.
   O_SYNC* {.importc, header: "<fcntl.h>".}: cint
-    ## Write according to synchronized I/O file integrity completion. 
+    ## Write according to synchronized I/O file integrity completion.
   O_ACCMODE* {.importc, header: "<fcntl.h>".}: cint
-    ## Mask for file access modes.      
+    ## Mask for file access modes.
   O_RDONLY* {.importc, header: "<fcntl.h>".}: cint
     ## Open for reading only.
   O_RDWR* {.importc, header: "<fcntl.h>".}: cint
     ## Open for reading and writing.
   O_WRONLY* {.importc, header: "<fcntl.h>".}: cint
-    ## Open for writing only. 
+    ## Open for writing only.
   POSIX_FADV_NORMAL* {.importc, header: "<fcntl.h>".}: cint
     ## The application has no advice to give on its behavior with
     ## respect to the specified data. It is the default characteristic
     ## if no advice is given for an open file.
   POSIX_FADV_SEQUENTIAL* {.importc, header: "<fcntl.h>".}: cint
-    ## The application expects to access the specified data 
+    ## The application expects to access the specified data
     # sequentially from lower offsets to higher offsets.
   POSIX_FADV_RANDOM* {.importc, header: "<fcntl.h>".}: cint
     ## The application expects to access the specified data in a random order.
@@ -829,8 +829,8 @@ var
     ## The application expects that it will not access the specified data
     ## in the near future.
   POSIX_FADV_NOREUSE* {.importc, header: "<fcntl.h>".}: cint
-    ## The application expects to access the specified data once and 
-    ## then not reuse it thereafter. 
+    ## The application expects to access the specified data once and
+    ## then not reuse it thereafter.
 
   FE_DIVBYZERO* {.importc, header: "<fenv.h>".}: cint
   FE_INEXACT* {.importc, header: "<fenv.h>".}: cint
@@ -875,20 +875,20 @@ when not defined(haiku):
     MM_PRINT* {.importc, header: "<fmtmsg.h>".}: cint
       ## Display message on standard error.
     MM_CONSOLE* {.importc, header: "<fmtmsg.h>".}: cint
-      ## Display message on system console. 
+      ## Display message on system console.
 
     MM_OK* {.importc, header: "<fmtmsg.h>".}: cint
       ## The function succeeded.
     MM_NOTOK* {.importc, header: "<fmtmsg.h>".}: cint
       ## The function failed completely.
     MM_NOMSG* {.importc, header: "<fmtmsg.h>".}: cint
-      ## The function was unable to generate a message on standard error, 
+      ## The function was unable to generate a message on standard error,
       ## but otherwise succeeded.
     MM_NOCON* {.importc, header: "<fmtmsg.h>".}: cint
-      ## The function was unable to generate a console message, but 
-      ## otherwise succeeded. 
+      ## The function was unable to generate a console message, but
+      ## otherwise succeeded.
 
-var    
+var
   FNM_NOMATCH* {.importc, header: "<fnmatch.h>".}: cint
     ## The string does not match the specified pattern.
   FNM_PATHNAME* {.importc, header: "<fnmatch.h>".}: cint
@@ -916,14 +916,14 @@ var
     ## Symbolic link that names a nonexistent file.
 
   FTW_PHYS* {.importc, header: "<ftw.h>".}: cint
-    ## Physical walk, does not follow symbolic links. Otherwise, nftw() 
+    ## Physical walk, does not follow symbolic links. Otherwise, nftw()
     ## follows links but does not walk down any path that crosses itself.
   FTW_MOUNT* {.importc, header: "<ftw.h>".}: cint
     ## The walk does not cross a mount point.
   FTW_DEPTH* {.importc, header: "<ftw.h>".}: cint
     ## All subdirectories are visited before the directory itself.
   FTW_CHDIR* {.importc, header: "<ftw.h>".}: cint
-    ## The walk changes to each directory before reading it. 
+    ## The walk changes to each directory before reading it.
 
   GLOB_APPEND* {.importc, header: "<glob.h>".}: cint
     ## Append generated pathnames to those previously obtained.
@@ -932,7 +932,7 @@ var
   GLOB_ERR* {.importc, header: "<glob.h>".}: cint
     ## Cause glob() to return on error.
   GLOB_MARK* {.importc, header: "<glob.h>".}: cint
-    ## Each pathname that is a directory that matches pattern has a 
+    ## Each pathname that is a directory that matches pattern has a
     ## slash appended.
   GLOB_NOCHECK* {.importc, header: "<glob.h>".}: cint
     ## If pattern does not match any pathname, then return a list
@@ -942,10 +942,10 @@ var
   GLOB_NOSORT* {.importc, header: "<glob.h>".}: cint
     ## Do not sort the pathnames returned.
   GLOB_ABORTED* {.importc, header: "<glob.h>".}: cint
-    ## The scan was stopped because GLOB_ERR was set or errfunc() 
+    ## The scan was stopped because GLOB_ERR was set or errfunc()
     ## returned non-zero.
   GLOB_NOMATCH* {.importc, header: "<glob.h>".}: cint
-    ## The pattern does not match any existing pathname, and GLOB_NOCHECK 
+    ## The pattern does not match any existing pathname, and GLOB_NOCHECK
     ## was not set in flags.
   GLOB_NOSPACE* {.importc, header: "<glob.h>".}: cint
     ## An attempt to allocate memory failed.
@@ -1033,10 +1033,10 @@ var
   NOEXPR* {.importc, header: "<langinfo.h>".}: cint
     ## Negative response expression.
   CRNCYSTR* {.importc, header: "<langinfo.h>".}: cint
-    ## Local currency symbol, preceded by '-' if the symbol 
-    ## should appear before the value, '+' if the symbol should appear 
+    ## Local currency symbol, preceded by '-' if the symbol
+    ## should appear before the value, '+' if the symbol should appear
     ## after the value, or '.' if the symbol should replace the radix
-    ## character. If the local currency symbol is the empty string, 
+    ## character. If the local currency symbol is the empty string,
     ## implementations may return the empty string ( "" ).
 
   LC_ALL* {.importc, header: "<locale.h>".}: cint
@@ -1046,7 +1046,7 @@ var
   LC_MONETARY* {.importc, header: "<locale.h>".}: cint
   LC_NUMERIC* {.importc, header: "<locale.h>".}: cint
   LC_TIME* {.importc, header: "<locale.h>".}: cint
-  
+
   PTHREAD_BARRIER_SERIAL_THREAD* {.importc, header: "<pthread.h>".}: cint
   PTHREAD_CANCEL_ASYNCHRONOUS* {.importc, header: "<pthread.h>".}: cint
   PTHREAD_CANCEL_ENABLE* {.importc, header: "<pthread.h>".}: cint
@@ -1115,7 +1115,7 @@ var
   PC_ALLOC_SIZE_MIN* {.importc: "_PC_ALLOC_SIZE_MIN",
     header: "<unistd.h>".}: cint
   PC_ASYNC_IO* {.importc: "_PC_ASYNC_IO", header: "<unistd.h>".}: cint
-  PC_CHOWN_RESTRICTED* {.importc: "_PC_CHOWN_RESTRICTED", 
+  PC_CHOWN_RESTRICTED* {.importc: "_PC_CHOWN_RESTRICTED",
     header: "<unistd.h>".}: cint
   PC_FILESIZEBITS* {.importc: "_PC_FILESIZEBITS", header: "<unistd.h>".}: cint
   PC_LINK_MAX* {.importc: "_PC_LINK_MAX", header: "<unistd.h>".}: cint
@@ -1127,9 +1127,9 @@ var
   PC_PATH_MAX*{.importc: "_PC_PATH_MAX", header: "<unistd.h>".}: cint
   PC_PIPE_BUF*{.importc: "_PC_PIPE_BUF", header: "<unistd.h>".}: cint
   PC_PRIO_IO*{.importc: "_PC_PRIO_IO", header: "<unistd.h>".}: cint
-  PC_REC_INCR_XFER_SIZE*{.importc: "_PC_REC_INCR_XFER_SIZE", 
+  PC_REC_INCR_XFER_SIZE*{.importc: "_PC_REC_INCR_XFER_SIZE",
     header: "<unistd.h>".}: cint
-  PC_REC_MIN_XFER_SIZE*{.importc: "_PC_REC_MIN_XFER_SIZE", 
+  PC_REC_MIN_XFER_SIZE*{.importc: "_PC_REC_MIN_XFER_SIZE",
     header: "<unistd.h>".}: cint
   PC_REC_XFER_ALIGN*{.importc: "_PC_REC_XFER_ALIGN", header: "<unistd.h>".}: cint
   PC_SYMLINK_MAX*{.importc: "_PC_SYMLINK_MAX", header: "<unistd.h>".}: cint
@@ -1142,9 +1142,9 @@ var
   SC_2_FORT_RUN*{.importc: "_SC_2_FORT_RUN", header: "<unistd.h>".}: cint
   SC_2_LOCALEDEF*{.importc: "_SC_2_LOCALEDEF", header: "<unistd.h>".}: cint
   SC_2_PBS*{.importc: "_SC_2_PBS", header: "<unistd.h>".}: cint
-  SC_2_PBS_ACCOUNTING*{.importc: "_SC_2_PBS_ACCOUNTING", 
+  SC_2_PBS_ACCOUNTING*{.importc: "_SC_2_PBS_ACCOUNTING",
     header: "<unistd.h>".}: cint
-  SC_2_PBS_CHECKPOINT*{.importc: "_SC_2_PBS_CHECKPOINT", 
+  SC_2_PBS_CHECKPOINT*{.importc: "_SC_2_PBS_CHECKPOINT",
     header: "<unistd.h>".}: cint
   SC_2_PBS_LOCATE*{.importc: "_SC_2_PBS_LOCATE", header: "<unistd.h>".}: cint
   SC_2_PBS_MESSAGE*{.importc: "_SC_2_PBS_MESSAGE", header: "<unistd.h>".}: cint
@@ -1155,10 +1155,10 @@ var
   SC_ADVISORY_INFO*{.importc: "_SC_ADVISORY_INFO", header: "<unistd.h>".}: cint
   SC_AIO_LISTIO_MAX*{.importc: "_SC_AIO_LISTIO_MAX", header: "<unistd.h>".}: cint
   SC_AIO_MAX*{.importc: "_SC_AIO_MAX", header: "<unistd.h>".}: cint
-  SC_AIO_PRIO_DELTA_MAX*{.importc: "_SC_AIO_PRIO_DELTA_MAX", 
+  SC_AIO_PRIO_DELTA_MAX*{.importc: "_SC_AIO_PRIO_DELTA_MAX",
     header: "<unistd.h>".}: cint
   SC_ARG_MAX*{.importc: "_SC_ARG_MAX", header: "<unistd.h>".}: cint
-  SC_ASYNCHRONOUS_IO*{.importc: "_SC_ASYNCHRONOUS_IO", 
+  SC_ASYNCHRONOUS_IO*{.importc: "_SC_ASYNCHRONOUS_IO",
     header: "<unistd.h>".}: cint
   SC_ATEXIT_MAX*{.importc: "_SC_ATEXIT_MAX", header: "<unistd.h>".}: cint
   SC_BARRIERS*{.importc: "_SC_BARRIERS", header: "<unistd.h>".}: cint
@@ -1168,17 +1168,17 @@ var
   SC_BC_STRING_MAX*{.importc: "_SC_BC_STRING_MAX", header: "<unistd.h>".}: cint
   SC_CHILD_MAX*{.importc: "_SC_CHILD_MAX", header: "<unistd.h>".}: cint
   SC_CLK_TCK*{.importc: "_SC_CLK_TCK", header: "<unistd.h>".}: cint
-  SC_CLOCK_SELECTION*{.importc: "_SC_CLOCK_SELECTION", 
+  SC_CLOCK_SELECTION*{.importc: "_SC_CLOCK_SELECTION",
     header: "<unistd.h>".}: cint
-  SC_COLL_WEIGHTS_MAX*{.importc: "_SC_COLL_WEIGHTS_MAX", 
+  SC_COLL_WEIGHTS_MAX*{.importc: "_SC_COLL_WEIGHTS_MAX",
     header: "<unistd.h>".}: cint
   SC_CPUTIME*{.importc: "_SC_CPUTIME", header: "<unistd.h>".}: cint
   SC_DELAYTIMER_MAX*{.importc: "_SC_DELAYTIMER_MAX", header: "<unistd.h>".}: cint
   SC_EXPR_NEST_MAX*{.importc: "_SC_EXPR_NEST_MAX", header: "<unistd.h>".}: cint
   SC_FSYNC*{.importc: "_SC_FSYNC", header: "<unistd.h>".}: cint
-  SC_GETGR_R_SIZE_MAX*{.importc: "_SC_GETGR_R_SIZE_MAX", 
+  SC_GETGR_R_SIZE_MAX*{.importc: "_SC_GETGR_R_SIZE_MAX",
     header: "<unistd.h>".}: cint
-  SC_GETPW_R_SIZE_MAX*{.importc: "_SC_GETPW_R_SIZE_MAX", 
+  SC_GETPW_R_SIZE_MAX*{.importc: "_SC_GETPW_R_SIZE_MAX",
     header: "<unistd.h>".}: cint
   SC_HOST_NAME_MAX*{.importc: "_SC_HOST_NAME_MAX", header: "<unistd.h>".}: cint
   SC_IOV_MAX*{.importc: "_SC_IOV_MAX", header: "<unistd.h>".}: cint
@@ -1189,11 +1189,11 @@ var
   SC_MAPPED_FILES*{.importc: "_SC_MAPPED_FILES", header: "<unistd.h>".}: cint
   SC_MEMLOCK*{.importc: "_SC_MEMLOCK", header: "<unistd.h>".}: cint
   SC_MEMLOCK_RANGE*{.importc: "_SC_MEMLOCK_RANGE", header: "<unistd.h>".}: cint
-  SC_MEMORY_PROTECTION*{.importc: "_SC_MEMORY_PROTECTION", 
+  SC_MEMORY_PROTECTION*{.importc: "_SC_MEMORY_PROTECTION",
     header: "<unistd.h>".}: cint
-  SC_MESSAGE_PASSING*{.importc: "_SC_MESSAGE_PASSING", 
+  SC_MESSAGE_PASSING*{.importc: "_SC_MESSAGE_PASSING",
     header: "<unistd.h>".}: cint
-  SC_MONOTONIC_CLOCK*{.importc: "_SC_MONOTONIC_CLOCK", 
+  SC_MONOTONIC_CLOCK*{.importc: "_SC_MONOTONIC_CLOCK",
     header: "<unistd.h>".}: cint
   SC_MQ_OPEN_MAX*{.importc: "_SC_MQ_OPEN_MAX", header: "<unistd.h>".}: cint
   SC_MQ_PRIO_MAX*{.importc: "_SC_MQ_PRIO_MAX", header: "<unistd.h>".}: cint
@@ -1201,13 +1201,13 @@ var
   SC_OPEN_MAX*{.importc: "_SC_OPEN_MAX", header: "<unistd.h>".}: cint
   SC_PAGE_SIZE*{.importc: "_SC_PAGE_SIZE", header: "<unistd.h>".}: cint
   SC_PRIORITIZED_IO*{.importc: "_SC_PRIORITIZED_IO", header: "<unistd.h>".}: cint
-  SC_PRIORITY_SCHEDULING*{.importc: "_SC_PRIORITY_SCHEDULING", 
+  SC_PRIORITY_SCHEDULING*{.importc: "_SC_PRIORITY_SCHEDULING",
     header: "<unistd.h>".}: cint
   SC_RAW_SOCKETS*{.importc: "_SC_RAW_SOCKETS", header: "<unistd.h>".}: cint
   SC_RE_DUP_MAX*{.importc: "_SC_RE_DUP_MAX", header: "<unistd.h>".}: cint
-  SC_READER_WRITER_LOCKS*{.importc: "_SC_READER_WRITER_LOCKS", 
+  SC_READER_WRITER_LOCKS*{.importc: "_SC_READER_WRITER_LOCKS",
     header: "<unistd.h>".}: cint
-  SC_REALTIME_SIGNALS*{.importc: "_SC_REALTIME_SIGNALS", 
+  SC_REALTIME_SIGNALS*{.importc: "_SC_REALTIME_SIGNALS",
     header: "<unistd.h>".}: cint
   SC_REGEXP*{.importc: "_SC_REGEXP", header: "<unistd.h>".}: cint
   SC_RTSIG_MAX*{.importc: "_SC_RTSIG_MAX", header: "<unistd.h>".}: cint
@@ -1215,43 +1215,43 @@ var
   SC_SEM_NSEMS_MAX*{.importc: "_SC_SEM_NSEMS_MAX", header: "<unistd.h>".}: cint
   SC_SEM_VALUE_MAX*{.importc: "_SC_SEM_VALUE_MAX", header: "<unistd.h>".}: cint
   SC_SEMAPHORES*{.importc: "_SC_SEMAPHORES", header: "<unistd.h>".}: cint
-  SC_SHARED_MEMORY_OBJECTS*{.importc: "_SC_SHARED_MEMORY_OBJECTS", 
+  SC_SHARED_MEMORY_OBJECTS*{.importc: "_SC_SHARED_MEMORY_OBJECTS",
     header: "<unistd.h>".}: cint
   SC_SHELL*{.importc: "_SC_SHELL", header: "<unistd.h>".}: cint
   SC_SIGQUEUE_MAX*{.importc: "_SC_SIGQUEUE_MAX", header: "<unistd.h>".}: cint
   SC_SPAWN*{.importc: "_SC_SPAWN", header: "<unistd.h>".}: cint
   SC_SPIN_LOCKS*{.importc: "_SC_SPIN_LOCKS", header: "<unistd.h>".}: cint
-  SC_SPORADIC_SERVER*{.importc: "_SC_SPORADIC_SERVER", 
+  SC_SPORADIC_SERVER*{.importc: "_SC_SPORADIC_SERVER",
     header: "<unistd.h>".}: cint
   SC_SS_REPL_MAX*{.importc: "_SC_SS_REPL_MAX", header: "<unistd.h>".}: cint
   SC_STREAM_MAX*{.importc: "_SC_STREAM_MAX", header: "<unistd.h>".}: cint
   SC_SYMLOOP_MAX*{.importc: "_SC_SYMLOOP_MAX", header: "<unistd.h>".}: cint
-  SC_SYNCHRONIZED_IO*{.importc: "_SC_SYNCHRONIZED_IO", 
+  SC_SYNCHRONIZED_IO*{.importc: "_SC_SYNCHRONIZED_IO",
     header: "<unistd.h>".}: cint
-  SC_THREAD_ATTR_STACKADDR*{.importc: "_SC_THREAD_ATTR_STACKADDR", 
+  SC_THREAD_ATTR_STACKADDR*{.importc: "_SC_THREAD_ATTR_STACKADDR",
     header: "<unistd.h>".}: cint
-  SC_THREAD_ATTR_STACKSIZE*{.importc: "_SC_THREAD_ATTR_STACKSIZE", 
+  SC_THREAD_ATTR_STACKSIZE*{.importc: "_SC_THREAD_ATTR_STACKSIZE",
     header: "<unistd.h>".}: cint
   SC_THREAD_CPUTIME*{.importc: "_SC_THREAD_CPUTIME", header: "<unistd.h>".}: cint
   SC_THREAD_DESTRUCTOR_ITERATIONS*{.importc: "_SC_THREAD_DESTRUCTOR_ITERATIONS",
     header: "<unistd.h>".}: cint
-  SC_THREAD_KEYS_MAX*{.importc: "_SC_THREAD_KEYS_MAX", 
+  SC_THREAD_KEYS_MAX*{.importc: "_SC_THREAD_KEYS_MAX",
     header: "<unistd.h>".}: cint
-  SC_THREAD_PRIO_INHERIT*{.importc: "_SC_THREAD_PRIO_INHERIT", 
+  SC_THREAD_PRIO_INHERIT*{.importc: "_SC_THREAD_PRIO_INHERIT",
     header: "<unistd.h>".}: cint
-  SC_THREAD_PRIO_PROTECT*{.importc: "_SC_THREAD_PRIO_PROTECT", 
+  SC_THREAD_PRIO_PROTECT*{.importc: "_SC_THREAD_PRIO_PROTECT",
     header: "<unistd.h>".}: cint
   SC_THREAD_PRIORITY_SCHEDULING*{.importc: "_SC_THREAD_PRIORITY_SCHEDULING",
     header: "<unistd.h>".}: cint
-  SC_THREAD_PROCESS_SHARED*{.importc: "_SC_THREAD_PROCESS_SHARED", 
+  SC_THREAD_PROCESS_SHARED*{.importc: "_SC_THREAD_PROCESS_SHARED",
     header: "<unistd.h>".}: cint
-  SC_THREAD_SAFE_FUNCTIONS*{.importc: "_SC_THREAD_SAFE_FUNCTIONS", 
+  SC_THREAD_SAFE_FUNCTIONS*{.importc: "_SC_THREAD_SAFE_FUNCTIONS",
     header: "<unistd.h>".}: cint
-  SC_THREAD_SPORADIC_SERVER*{.importc: "_SC_THREAD_SPORADIC_SERVER", 
+  SC_THREAD_SPORADIC_SERVER*{.importc: "_SC_THREAD_SPORADIC_SERVER",
     header: "<unistd.h>".}: cint
-  SC_THREAD_STACK_MIN*{.importc: "_SC_THREAD_STACK_MIN", 
+  SC_THREAD_STACK_MIN*{.importc: "_SC_THREAD_STACK_MIN",
     header: "<unistd.h>".}: cint
-  SC_THREAD_THREADS_MAX*{.importc: "_SC_THREAD_THREADS_MAX", 
+  SC_THREAD_THREADS_MAX*{.importc: "_SC_THREAD_THREADS_MAX",
     header: "<unistd.h>".}: cint
   SC_THREADS*{.importc: "_SC_THREADS", header: "<unistd.h>".}: cint
   SC_TIMEOUTS*{.importc: "_SC_TIMEOUTS", header: "<unistd.h>".}: cint
@@ -1276,21 +1276,21 @@ var
   SC_XBS5_ILP32_OFF32*{.importc: "_SC_XBS5_ILP32_OFF32", header: "<unistd.h>".}: cint
   SC_XBS5_ILP32_OFFBIG*{.importc: "_SC_XBS5_ILP32_OFFBIG", header: "<unistd.h>".}: cint
   SC_XBS5_LP64_OFF64*{.importc: "_SC_XBS5_LP64_OFF64", header: "<unistd.h>".}: cint
-  SC_XBS5_LPBIG_OFFBIG*{.importc: "_SC_XBS5_LPBIG_OFFBIG", 
+  SC_XBS5_LPBIG_OFFBIG*{.importc: "_SC_XBS5_LPBIG_OFFBIG",
                          header: "<unistd.h>".}: cint
   SC_XOPEN_CRYPT*{.importc: "_SC_XOPEN_CRYPT", header: "<unistd.h>".}: cint
   SC_XOPEN_ENH_I18N*{.importc: "_SC_XOPEN_ENH_I18N", header: "<unistd.h>".}: cint
   SC_XOPEN_LEGACY*{.importc: "_SC_XOPEN_LEGACY", header: "<unistd.h>".}: cint
   SC_XOPEN_REALTIME*{.importc: "_SC_XOPEN_REALTIME", header: "<unistd.h>".}: cint
-  SC_XOPEN_REALTIME_THREADS*{.importc: "_SC_XOPEN_REALTIME_THREADS", 
+  SC_XOPEN_REALTIME_THREADS*{.importc: "_SC_XOPEN_REALTIME_THREADS",
                               header: "<unistd.h>".}: cint
   SC_XOPEN_SHM*{.importc: "_SC_XOPEN_SHM", header: "<unistd.h>".}: cint
   SC_XOPEN_STREAMS*{.importc: "_SC_XOPEN_STREAMS", header: "<unistd.h>".}: cint
   SC_XOPEN_UNIX*{.importc: "_SC_XOPEN_UNIX", header: "<unistd.h>".}: cint
   SC_XOPEN_VERSION*{.importc: "_SC_XOPEN_VERSION", header: "<unistd.h>".}: cint
-  SC_NPROCESSORS_ONLN*{.importc: "_SC_NPROCESSORS_ONLN", 
+  SC_NPROCESSORS_ONLN*{.importc: "_SC_NPROCESSORS_ONLN",
                         header: "<unistd.h>".}: cint
-  
+
   SEM_FAILED* {.importc, header: "<semaphore.h>".}: pointer
   IPC_CREAT* {.importc, header: "<sys/ipc.h>".}: cint
     ## Create entry if key does not exist.
@@ -1307,7 +1307,7 @@ var
   IPC_SET* {.importc, header: "<sys/ipc.h>".}: cint
     ## Set options.
   IPC_STAT* {.importc, header: "<sys/ipc.h>".}: cint
-    ## Get options. 
+    ## Get options.
 
   S_IFMT* {.importc, header: "<sys/stat.h>".}: cint
     ## Type of file.
@@ -1355,12 +1355,12 @@ var
     ## Set-group-ID on execution.
   S_ISVTX* {.importc, header: "<sys/stat.h>".}: cint
     ## On directories, restricted deletion flag.
-  
+
   ST_RDONLY* {.importc, header: "<sys/statvfs.h>".}: cint
     ## Read-only file system.
   ST_NOSUID* {.importc, header: "<sys/statvfs.h>".}: cint
     ## Does not support the semantics of the ST_ISUID and ST_ISGID file mode bits.
-       
+
   PROT_READ* {.importc, header: "<sys/mman.h>".}: cint
     ## Page can be read.
   PROT_WRITE* {.importc, header: "<sys/mman.h>".}: cint
@@ -1387,8 +1387,8 @@ var
     ## Lock pages that become mapped.
   MAP_FAILED* {.importc, header: "<sys/mman.h>".}: cint
   POSIX_MADV_NORMAL* {.importc, header: "<sys/mman.h>".}: cint
-    ## The application has no advice to give on its behavior with 
-    ## respect to the specified range. It is the default characteristic 
+    ## The application has no advice to give on its behavior with
+    ## respect to the specified range. It is the default characteristic
     ## if no advice is given for a range of memory.
   POSIX_MADV_SEQUENTIAL* {.importc, header: "<sys/mman.h>".}: cint
     ## The application expects to access the specified range sequentially
@@ -1407,13 +1407,13 @@ var
     ## A number used to convert the value returned by the clock() function
     ## into seconds.
   CLOCK_PROCESS_CPUTIME_ID* {.importc, header: "<time.h>".}: cint
-    ## The identifier of the CPU-time clock associated with the process 
+    ## The identifier of the CPU-time clock associated with the process
     ## making a clock() or timer*() function call.
   CLOCK_THREAD_CPUTIME_ID* {.importc, header: "<time.h>".}: cint
   CLOCK_REALTIME* {.importc, header: "<time.h>".}: cint
     ## The identifier of the system-wide realtime clock.
   TIMER_ABSTIME* {.importc, header: "<time.h>".}: cint
-    ## Flag indicating time is absolute. For functions taking timer 
+    ## Flag indicating time is absolute. For functions taking timer
     ## objects, this refers to the clock associated with the timer.
   CLOCK_MONOTONIC* {.importc, header: "<time.h>".}: cint
 
@@ -1438,25 +1438,25 @@ var
   WEXITED* {.importc, header: "<sys/wait.h>".}: cint
     ## Wait for processes that have exited.
   WSTOPPED* {.importc, header: "<sys/wait.h>".}: cint
-    ## Status is returned for any child that has stopped upon receipt 
+    ## Status is returned for any child that has stopped upon receipt
     ## of a signal.
   WCONTINUED* {.importc, header: "<sys/wait.h>".}: cint
     ## Status is returned for any child that was stopped and has been continued.
   WNOWAIT* {.importc, header: "<sys/wait.h>".}: cint
-    ## Keep the process whose status is returned in infop in a waitable state. 
-  P_ALL* {.importc, header: "<sys/wait.h>".}: cint 
-  P_PID* {.importc, header: "<sys/wait.h>".}: cint 
+    ## Keep the process whose status is returned in infop in a waitable state.
+  P_ALL* {.importc, header: "<sys/wait.h>".}: cint
+  P_PID* {.importc, header: "<sys/wait.h>".}: cint
   P_PGID* {.importc, header: "<sys/wait.h>".}: cint
-       
+
   SIG_DFL* {.importc, header: "<signal.h>".}: proc (x: cint) {.noconv.}
     ## Request for default signal handling.
   SIG_ERR* {.importc, header: "<signal.h>".}: proc (x: cint) {.noconv.}
     ## Return value from signal() in case of error.
-  cSIG_HOLD* {.importc: "SIG_HOLD", 
+  cSIG_HOLD* {.importc: "SIG_HOLD",
     header: "<signal.h>".}: proc (x: cint) {.noconv.}
     ## Request that signal be held.
   SIG_IGN* {.importc, header: "<signal.h>".}: proc (x: cint) {.noconv.}
-    ## Request that signal be ignored. 
+    ## Request that signal be ignored.
 
   SIGEV_NONE* {.importc, header: "<signal.h>".}: cint
   SIGEV_SIGNAL* {.importc, header: "<signal.h>".}: cint
@@ -1518,8 +1518,8 @@ var
   SEEK_END* {.importc, header: "<unistd.h>".}: cint
 
   SCM_RIGHTS* {.importc, header: "<sys/socket.h>".}: cint
-    ## Indicates that the data array contains the access rights 
-    ## to be sent or received. 
+    ## Indicates that the data array contains the access rights
+    ## to be sent or received.
 
   SOCK_DGRAM* {.importc, header: "<sys/socket.h>".}: cint ## Datagram socket.
   SOCK_RAW* {.importc, header: "<sys/socket.h>".}: cint
@@ -1527,11 +1527,11 @@ var
   SOCK_SEQPACKET* {.importc, header: "<sys/socket.h>".}: cint
     ## Sequenced-packet socket.
   SOCK_STREAM* {.importc, header: "<sys/socket.h>".}: cint
-    ## Byte-stream socket. 
-    
+    ## Byte-stream socket.
+
   SOL_SOCKET* {.importc, header: "<sys/socket.h>".}: cint
-    ## Options to be accessed at socket level, not protocol level. 
-    
+    ## Options to be accessed at socket level, not protocol level.
+
   SO_ACCEPTCONN* {.importc, header: "<sys/socket.h>".}: cint
     ## Socket is accepting connections.
   SO_BROADCAST* {.importc, header: "<sys/socket.h>".}: cint
@@ -1563,11 +1563,11 @@ var
   SO_SNDTIMEO* {.importc, header: "<sys/socket.h>".}: cint
     ## Send timeout.
   SO_TYPE* {.importc, header: "<sys/socket.h>".}: cint
-    ## Socket type. 
-      
+    ## Socket type.
+
   SOMAXCONN* {.importc, header: "<sys/socket.h>".}: cint
-    ## The maximum backlog queue length. 
-    
+    ## The maximum backlog queue length.
+
   MSG_CTRUNC* {.importc, header: "<sys/socket.h>".}: cint
     ## Control data truncated.
   MSG_DONTROUTE* {.importc, header: "<sys/socket.h>".}: cint
@@ -1583,7 +1583,7 @@ var
   MSG_TRUNC* {.importc, header: "<sys/socket.h>".}: cint
     ## Normal data truncated.
   MSG_WAITALL* {.importc, header: "<sys/socket.h>".}: cint
-    ## Attempt to fill the read buffer. 
+    ## Attempt to fill the read buffer.
 
   AF_INET* {.importc, header: "<sys/socket.h>".}: cint
     ## Internet domain sockets for use with IPv4 addresses.
@@ -1592,17 +1592,17 @@ var
   AF_UNIX* {.importc, header: "<sys/socket.h>".}: cint
     ## UNIX domain sockets.
   AF_UNSPEC* {.importc, header: "<sys/socket.h>".}: cint
-    ## Unspecified. 
+    ## Unspecified.
 
   SHUT_RD* {.importc, header: "<sys/socket.h>".}: cint
     ## Disables further receive operations.
   SHUT_RDWR* {.importc, header: "<sys/socket.h>".}: cint
     ## Disables further send and receive operations.
   SHUT_WR* {.importc, header: "<sys/socket.h>".}: cint
-    ## Disables further send operations. 
+    ## Disables further send operations.
 
   IF_NAMESIZE* {.importc, header: "<net/if.h>".}: cint
-    
+
   IPPROTO_IP* {.importc, header: "<netinet/in.h>".}: cint
     ## Internet protocol.
   IPPROTO_IPV6* {.importc, header: "<netinet/in.h>".}: cint
@@ -1610,7 +1610,7 @@ var
   IPPROTO_ICMP* {.importc, header: "<netinet/in.h>".}: cint
     ## Control message protocol.
   IPPROTO_RAW* {.importc, header: "<netinet/in.h>".}: cint
-    ## Raw IP Packets Protocol. 
+    ## Raw IP Packets Protocol.
   IPPROTO_TCP* {.importc, header: "<netinet/in.h>".}: cint
     ## Transmission control protocol.
   IPPROTO_UDP* {.importc, header: "<netinet/in.h>".}: cint
@@ -1622,7 +1622,7 @@ var
     ## IPv4 broadcast address.
 
   INET_ADDRSTRLEN* {.importc, header: "<netinet/in.h>".}: cint
-    ## 16. Length of the string form for IP. 
+    ## 16. Length of the string form for IP.
 
   IPV6_JOIN_GROUP* {.importc, header: "<netinet/in.h>".}: cint
     ## Join a multicast group.
@@ -1640,68 +1640,68 @@ var
     ## Restrict AF_INET6 socket to IPv6 communications only.
 
   TCP_NODELAY* {.importc, header: "<netinet/tcp.h>".}: cint
-    ## Avoid coalescing of small segments. 
+    ## Avoid coalescing of small segments.
 
-  IPPORT_RESERVED* {.importc, header: "<netdb.h>".}: cint 
+  IPPORT_RESERVED* {.importc, header: "<netdb.h>".}: cint
 
-  HOST_NOT_FOUND* {.importc, header: "<netdb.h>".}: cint 
-  NO_DATA* {.importc, header: "<netdb.h>".}: cint 
-  NO_RECOVERY* {.importc, header: "<netdb.h>".}: cint 
-  TRY_AGAIN* {.importc, header: "<netdb.h>".}: cint 
+  HOST_NOT_FOUND* {.importc, header: "<netdb.h>".}: cint
+  NO_DATA* {.importc, header: "<netdb.h>".}: cint
+  NO_RECOVERY* {.importc, header: "<netdb.h>".}: cint
+  TRY_AGAIN* {.importc, header: "<netdb.h>".}: cint
 
-  AI_PASSIVE* {.importc, header: "<netdb.h>".}: cint 
+  AI_PASSIVE* {.importc, header: "<netdb.h>".}: cint
     ## Socket address is intended for bind().
-  AI_CANONNAME* {.importc, header: "<netdb.h>".}: cint 
+  AI_CANONNAME* {.importc, header: "<netdb.h>".}: cint
     ## Request for canonical name.
-  AI_NUMERICHOST* {.importc, header: "<netdb.h>".}: cint 
+  AI_NUMERICHOST* {.importc, header: "<netdb.h>".}: cint
     ## Return numeric host address as name.
-  AI_NUMERICSERV* {.importc, header: "<netdb.h>".}: cint 
+  AI_NUMERICSERV* {.importc, header: "<netdb.h>".}: cint
     ## Inhibit service name resolution.
-  AI_V4MAPPED* {.importc, header: "<netdb.h>".}: cint 
+  AI_V4MAPPED* {.importc, header: "<netdb.h>".}: cint
      ## If no IPv6 addresses are found, query for IPv4 addresses and
      ## return them to the caller as IPv4-mapped IPv6 addresses.
-  AI_ALL* {.importc, header: "<netdb.h>".}: cint 
+  AI_ALL* {.importc, header: "<netdb.h>".}: cint
     ## Query for both IPv4 and IPv6 addresses.
-  AI_ADDRCONFIG* {.importc, header: "<netdb.h>".}: cint 
-    ## Query for IPv4 addresses only when an IPv4 address is configured; 
+  AI_ADDRCONFIG* {.importc, header: "<netdb.h>".}: cint
+    ## Query for IPv4 addresses only when an IPv4 address is configured;
     ## query for IPv6 addresses only when an IPv6 address is configured.
 
-  NI_NOFQDN* {.importc, header: "<netdb.h>".}: cint 
+  NI_NOFQDN* {.importc, header: "<netdb.h>".}: cint
     ## Only the nodename portion of the FQDN is returned for local hosts.
-  NI_NUMERICHOST* {.importc, header: "<netdb.h>".}: cint 
+  NI_NUMERICHOST* {.importc, header: "<netdb.h>".}: cint
     ## The numeric form of the node's address is returned instead of its name.
-  NI_NAMEREQD* {.importc, header: "<netdb.h>".}: cint 
+  NI_NAMEREQD* {.importc, header: "<netdb.h>".}: cint
     ## Return an error if the node's name cannot be located in the database.
-  NI_NUMERICSERV* {.importc, header: "<netdb.h>".}: cint 
+  NI_NUMERICSERV* {.importc, header: "<netdb.h>".}: cint
     ## The numeric form of the service address is returned instead of its name.
-  NI_NUMERICSCOPE* {.importc, header: "<netdb.h>".}: cint 
+  NI_NUMERICSCOPE* {.importc, header: "<netdb.h>".}: cint
     ## For IPv6 addresses, the numeric form of the scope identifier is
     ## returned instead of its name.
-  NI_DGRAM* {.importc, header: "<netdb.h>".}: cint 
-    ## Indicates that the service is a datagram service (SOCK_DGRAM). 
+  NI_DGRAM* {.importc, header: "<netdb.h>".}: cint
+    ## Indicates that the service is a datagram service (SOCK_DGRAM).
 
-  EAI_AGAIN* {.importc, header: "<netdb.h>".}: cint 
+  EAI_AGAIN* {.importc, header: "<netdb.h>".}: cint
     ## The name could not be resolved at this time. Future attempts may succeed.
-  EAI_BADFLAGS* {.importc, header: "<netdb.h>".}: cint 
+  EAI_BADFLAGS* {.importc, header: "<netdb.h>".}: cint
     ## The flags had an invalid value.
-  EAI_FAIL* {.importc, header: "<netdb.h>".}: cint 
+  EAI_FAIL* {.importc, header: "<netdb.h>".}: cint
     ## A non-recoverable error occurred.
-  EAI_FAMILY* {.importc, header: "<netdb.h>".}: cint 
-    ## The address family was not recognized or the address length 
+  EAI_FAMILY* {.importc, header: "<netdb.h>".}: cint
+    ## The address family was not recognized or the address length
     ## was invalid for the specified family.
-  EAI_MEMORY* {.importc, header: "<netdb.h>".}: cint 
+  EAI_MEMORY* {.importc, header: "<netdb.h>".}: cint
     ## There was a memory allocation failure.
-  EAI_NONAME* {.importc, header: "<netdb.h>".}: cint 
+  EAI_NONAME* {.importc, header: "<netdb.h>".}: cint
     ## The name does not resolve for the supplied parameters.
-    ## NI_NAMEREQD is set and the host's name cannot be located, 
+    ## NI_NAMEREQD is set and the host's name cannot be located,
     ## or both nodename and servname were null.
-  EAI_SERVICE* {.importc, header: "<netdb.h>".}: cint 
+  EAI_SERVICE* {.importc, header: "<netdb.h>".}: cint
     ## The service passed was not recognized for the specified socket type.
-  EAI_SOCKTYPE* {.importc, header: "<netdb.h>".}: cint 
+  EAI_SOCKTYPE* {.importc, header: "<netdb.h>".}: cint
     ## The intended socket type was not recognized.
-  EAI_SYSTEM* {.importc, header: "<netdb.h>".}: cint 
+  EAI_SYSTEM* {.importc, header: "<netdb.h>".}: cint
     ## A system error occurred. The error code can be found in errno.
-  EAI_OVERFLOW* {.importc, header: "<netdb.h>".}: cint 
+  EAI_OVERFLOW* {.importc, header: "<netdb.h>".}: cint
     ## An argument buffer overflowed.
 
   POLLIN* {.importc, header: "<poll.h>".}: cshort
@@ -1723,7 +1723,7 @@ var
   POLLHUP* {.importc, header: "<poll.h>".}: cshort
     ## Device has been disconnected (revents only).
   POLLNVAL* {.importc, header: "<poll.h>".}: cshort
-    ## Invalid fd member (revents only). 
+    ## Invalid fd member (revents only).
 
 
 when hasSpawnH:
@@ -1743,7 +1743,7 @@ when hasSpawnH:
     # macosx lacks this, so we define the constant to be 0 to not affect
     # OR'ing of flags:
     const POSIX_SPAWN_USEVFORK* = cint(0)
-    
+
 when hasAioH:
   proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
   proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
@@ -1817,13 +1817,13 @@ proc feupdateenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
 when not defined(haiku):
   proc fmtmsg*(a1: int, a2: cstring, a3: cint,
               a4, a5, a6: cstring): cint {.importc, header: "<fmtmsg.h>".}
-            
+
 proc fnmatch*(a1, a2: cstring, a3: cint): cint {.importc, header: "<fnmatch.h>".}
-proc ftw*(a1: cstring, 
+proc ftw*(a1: cstring,
          a2: proc (x1: cstring, x2: ptr TStat, x3: cint): cint {.noconv.},
          a3: cint): cint {.importc, header: "<ftw.h>".}
-proc nftw*(a1: cstring, 
-          a2: proc (x1: cstring, x2: ptr TStat, 
+proc nftw*(a1: cstring,
+          a2: proc (x1: cstring, x2: ptr TStat,
                     x3: cint, x4: ptr TFTW): cint {.noconv.},
           a3: cint,
           a4: cint): cint {.importc, header: "<ftw.h>".}
@@ -1837,7 +1837,7 @@ proc getgrgid*(a1: TGid): ptr TGroup {.importc, header: "<grp.h>".}
 proc getgrnam*(a1: cstring): ptr TGroup {.importc, header: "<grp.h>".}
 proc getgrgid_r*(a1: TGid, a2: ptr TGroup, a3: cstring, a4: int,
                  a5: ptr ptr TGroup): cint {.importc, header: "<grp.h>".}
-proc getgrnam_r*(a1: cstring, a2: ptr TGroup, a3: cstring, 
+proc getgrnam_r*(a1: cstring, a2: ptr TGroup, a3: cstring,
                   a4: int, a5: ptr ptr TGroup): cint {.
                  importc, header: "<grp.h>".}
 proc getgrent*(): ptr TGroup {.importc, header: "<grp.h>".}
@@ -1876,9 +1876,9 @@ proc mq_send*(a1: TMqd, a2: cstring, a3: int, a4: int): cint {.
 proc mq_setattr*(a1: TMqd, a2, a3: ptr TMqAttr): cint {.
   importc, header: "<mqueue.h>".}
 
-proc mq_timedreceive*(a1: TMqd, a2: cstring, a3: int, a4: int, 
+proc mq_timedreceive*(a1: TMqd, a2: cstring, a3: int, a4: int,
                       a5: ptr Ttimespec): int {.importc, header: "<mqueue.h>".}
-proc mq_timedsend*(a1: TMqd, a2: cstring, a3: int, a4: int, 
+proc mq_timedsend*(a1: TMqd, a2: cstring, a3: int, a4: int,
                    a5: ptr Ttimespec): cint {.importc, header: "<mqueue.h>".}
 proc mq_unlink*(a1: cstring): cint {.importc, header: "<mqueue.h>".}
 
@@ -1951,7 +1951,7 @@ proc pthread_barrierattr_getpshared*(
           importc, header: "<pthread.h>".}
 proc pthread_barrierattr_init*(a1: ptr Tpthread_barrierattr): cint {.
   importc, header: "<pthread.h>".}
-proc pthread_barrierattr_setpshared*(a1: ptr Tpthread_barrierattr, 
+proc pthread_barrierattr_setpshared*(a1: ptr Tpthread_barrierattr,
   a2: cint): cint {.importc, header: "<pthread.h>".}
 proc pthread_cancel*(a1: Tpthread): cint {.importc, header: "<pthread.h>".}
 proc pthread_cleanup_push*(a1: proc (x: pointer) {.noconv.}, a2: pointer) {.
@@ -1973,7 +1973,7 @@ proc pthread_condattr_getclock*(a1: ptr Tpthread_condattr,
           a2: var TClockId): cint {.importc, header: "<pthread.h>".}
 proc pthread_condattr_getpshared*(a1: ptr Tpthread_condattr,
           a2: var cint): cint {.importc, header: "<pthread.h>".}
-          
+
 proc pthread_condattr_init*(a1: ptr Tpthread_condattr): cint {.importc, header: "<pthread.h>".}
 proc pthread_condattr_setclock*(a1: ptr Tpthread_condattr,a2: TClockId): cint {.importc, header: "<pthread.h>".}
 proc pthread_condattr_setpshared*(a1: ptr Tpthread_condattr, a2: cint): cint {.importc, header: "<pthread.h>".}
@@ -2085,6 +2085,7 @@ proc execv*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>"
 proc execve*(a1: cstring, a2, a3: cstringArray): cint {.
   importc, header: "<unistd.h>".}
 proc execvp*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>".}
+proc execvpe*(a1: cstring, a2: cstringArray, a3: cstringArray): cint {.importc, header: "<unistd.h>".}
 proc fchown*(a1: cint, a2: Tuid, a3: TGid): cint {.importc, header: "<unistd.h>".}
 proc fchdir*(a1: cint): cint {.importc, header: "<unistd.h>".}
 proc fdatasync*(a1: cint): cint {.importc, header: "<unistd.h>".}
@@ -2205,18 +2206,18 @@ proc S_ISREG*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
 proc S_ISLNK*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
   ## Test for a symbolic link.
 proc S_ISSOCK*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
-  ## Test for a socket. 
-    
+  ## Test for a socket.
+
 proc S_TYPEISMQ*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".}
   ## Test for a message queue.
 proc S_TYPEISSEM*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".}
   ## Test for a semaphore.
 proc S_TYPEISSHM*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".}
-  ## Test for a shared memory object. 
-    
+  ## Test for a shared memory object.
+
 proc S_TYPEISTMO*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".}
-  ## Test macro for a typed memory object. 
-  
+  ## Test macro for a typed memory object.
+
 proc mlock*(a1: pointer, a2: int): cint {.importc, header: "<sys/mman.h>".}
 proc mlockall*(a1: cint): cint {.importc, header: "<sys/mman.h>".}
 proc mmap*(a1: pointer, a2: int, a3, a4, a5: cint, a6: TOff): pointer {.
@@ -2231,7 +2232,7 @@ proc posix_madvise*(a1: pointer, a2: int, a3: cint): cint {.
   importc, header: "<sys/mman.h>".}
 proc posix_mem_offset*(a1: pointer, a2: int, a3: var TOff,
            a4: var int, a5: var cint): cint {.importc, header: "<sys/mman.h>".}
-proc posix_typed_mem_get_info*(a1: cint, 
+proc posix_typed_mem_get_info*(a1: cint,
   a2: var Tposix_typed_mem_info): cint {.importc, header: "<sys/mman.h>".}
 proc posix_typed_mem_open*(a1: cstring, a2, a3: cint): cint {.
   importc, header: "<sys/mman.h>".}
@@ -2317,7 +2318,7 @@ proc sigrelse*(a1: cint): cint {.importc, header: "<signal.h>".}
 proc sigset*(a1: int, a2: proc (x: cint) {.noconv.}) {.
   importc, header: "<signal.h>".}
 proc sigsuspend*(a1: var Tsigset): cint {.importc, header: "<signal.h>".}
-proc sigtimedwait*(a1: var Tsigset, a2: var TsigInfo, 
+proc sigtimedwait*(a1: var Tsigset, a2: var TsigInfo,
                    a3: var Ttimespec): cint {.importc, header: "<signal.h>".}
 proc sigwait*(a1: var Tsigset, a2: var cint): cint {.
   importc, header: "<signal.h>".}
@@ -2361,7 +2362,7 @@ proc select*(a1: cint, a2, a3, a4: ptr TFdSet, a5: ptr Ttimeval): cint {.
 when hasSpawnH:
   proc posix_spawn*(a1: var TPid, a2: cstring,
             a3: var Tposix_spawn_file_actions,
-            a4: var Tposix_spawnattr, 
+            a4: var Tposix_spawnattr,
             a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".}
   proc posix_spawn_file_actions_addclose*(a1: var Tposix_spawn_file_actions,
             a2: cint): cint {.importc, header: "<spawn.h>".}
@@ -2388,7 +2389,7 @@ when hasSpawnH:
             a2: var cint): cint {.importc, header: "<spawn.h>".}
   proc posix_spawnattr_getsigmask*(a1: var Tposix_spawnattr,
             a2: var Tsigset): cint {.importc, header: "<spawn.h>".}
-  
+
   proc posix_spawnattr_init*(a1: var Tposix_spawnattr): cint {.
     importc, header: "<spawn.h>".}
   proc posix_spawnattr_setsigdefault*(a1: var Tposix_spawnattr,
@@ -2397,10 +2398,10 @@ when hasSpawnH:
     importc, header: "<spawn.h>".}
   proc posix_spawnattr_setpgroup*(a1: var Tposix_spawnattr, a2: TPid): cint {.
     importc, header: "<spawn.h>".}
-  
+
   proc posix_spawnattr_setschedparam*(a1: var Tposix_spawnattr,
             a2: var Tsched_param): cint {.importc, header: "<spawn.h>".}
-  proc posix_spawnattr_setschedpolicy*(a1: var Tposix_spawnattr, 
+  proc posix_spawnattr_setschedpolicy*(a1: var Tposix_spawnattr,
                                        a2: cint): cint {.
                                        importc, header: "<spawn.h>".}
   proc posix_spawnattr_setsigmask*(a1: var Tposix_spawnattr,
@@ -2441,7 +2442,7 @@ proc accept*(a1: TSocketHandle, a2: ptr TSockAddr, a3: ptr TSocklen): TSocketHan
 proc bindSocket*(a1: TSocketHandle, a2: ptr TSockAddr, a3: TSocklen): cint {.
   importc: "bind", header: "<sys/socket.h>".}
   ## is Posix's ``bind``, because ``bind`` is a reserved word
-  
+
 proc connect*(a1: TSocketHandle, a2: ptr TSockAddr, a3: TSocklen): cint {.
   importc, header: "<sys/socket.h>".}
 proc getpeername*(a1: TSocketHandle, a2: ptr TSockAddr, a3: ptr TSocklen): cint {.
@@ -2530,9 +2531,9 @@ proc freeaddrinfo*(a1: ptr Taddrinfo) {.importc, header: "<netdb.h>".}
 
 proc gai_strerror*(a1: cint): cstring {.importc, header: "<netdb.h>".}
 
-proc getaddrinfo*(a1, a2: cstring, a3: ptr Taddrinfo, 
+proc getaddrinfo*(a1, a2: cstring, a3: ptr Taddrinfo,
                   a4: var ptr Taddrinfo): cint {.importc, header: "<netdb.h>".}
-                  
+
 proc gethostbyaddr*(a1: pointer, a2: TSocklen, a3: cint): ptr Thostent {.
                     importc, header: "<netdb.h>".}
 proc gethostbyname*(a1: cstring): ptr Thostent {.importc, header: "<netdb.h>".}
@@ -2566,4 +2567,14 @@ proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {.
 proc realpath*(name, resolved: cstring): cstring {.
   importc: "realpath", header: "<stdlib.h>".}
 
-
+proc utimes*(path: cstring, times: ptr array [2, Ttimeval]): int {.
+  importc: "utimes", header: "<sys/time.h>".}
+  ## Sets file access and modification times.
+  ##
+  ## Pass the filename and an array of times to set the access and modification
+  ## times respectively. If you pass nil as the array both attributes will be
+  ## set to the current time.
+  ##
+  ## Returns zero on success.
+  ##
+  ## For more information read http://www.unix.com/man-page/posix/3/utimes/.
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index df7ae6d17..921c659de 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -131,3 +131,36 @@ proc sort*[T](a: var openArray[T],
       dec(m, s*2)
     s = s*2
 
+proc product*[T](x: openarray[seq[T]]): seq[seq[T]] =
+  ## produces the Cartesian product of the array. Warning: complexity
+  ## may explode.
+  result = @[]
+  if x.len == 0:
+    return
+  if x.len == 1:
+    result = @x
+    return
+  var
+    indexes = newSeq[int](x.len)
+    initial = newSeq[int](x.len)
+    index = 0
+  # replace with newSeq as soon as #853 is fixed
+  var next: seq[T] = @[]
+  next.setLen(x.len)
+  for i in 0..(x.len-1):
+    if len(x[i]) == 0: return
+    initial[i] = len(x[i])-1
+  indexes = initial
+  while true:
+    while indexes[index] == -1:
+      indexes[index] = initial[index]
+      index +=1
+      if index == x.len: return
+      indexes[index] -=1
+    for ni, i in indexes:
+      next[ni] = x[ni][i]
+    var res: seq[T]
+    shallowCopy(res, next)
+    result.add(res)
+    index = 0
+    indexes[index] -=1
diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim
index f13cadaa2..96afc6f4f 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/pure/asyncio.nim
@@ -689,5 +689,5 @@ when isMainModule:
   server.listen()
   d.register(server)
   
-  while d.poll(-1): nil
+  while d.poll(-1): discard
     
diff --git a/lib/pure/asyncio2.nim b/lib/pure/asyncio2.nim
new file mode 100644
index 000000000..cdb4a6f49
--- /dev/null
+++ b/lib/pure/asyncio2.nim
@@ -0,0 +1,485 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+import os, oids, tables, strutils
+
+import winlean
+
+import sockets2, net
+
+## Asyncio2 
+## --------
+##
+## This module implements a brand new asyncio module based on Futures.
+## IOCP is used under the hood on Windows and the selectors module is used for
+## other operating systems.
+
+# -- Futures
+
+type
+  PFutureVoid* = ref object of PObject
+    cbVoid: proc () {.closure.}
+    finished: bool
+
+  PFuture*[T] = ref object of PFutureVoid
+    value: T
+    error: ref EBase
+    cb: proc (future: PFuture[T]) {.closure.}
+
+proc newFuture*[T](): PFuture[T] =
+  ## Creates a new future.
+  new(result)
+  result.finished = false
+
+proc complete*[T](future: PFuture[T], val: T) =
+  ## Completes ``future`` with value ``val``.
+  assert(not future.finished)
+  assert(future.error == nil)
+  future.value = val
+  future.finished = true
+  if future.cb != nil:
+    future.cb(future)
+  if future.cbVoid != nil:
+    future.cbVoid()
+
+proc fail*[T](future: PFuture[T], error: ref EBase) =
+  ## Completes ``future`` with ``error``.
+  assert(not future.finished)
+  future.finished = true
+  future.error = error
+  if future.cb != nil:
+    future.cb(future)
+
+proc `callback=`*[T](future: PFuture[T],
+    cb: proc (future: PFuture[T]) {.closure.}) =
+  ## Sets the callback proc to be called when the future completes.
+  ##
+  ## If future has already completed then ``cb`` will be called immediately.
+  future.cb = cb
+  if future.finished:
+    future.cb(future)
+
+proc `callbackVoid=`*(future: PFutureVoid, cb: proc () {.closure.}) =
+  ## Sets the **void** callback proc to be called when the future completes.
+  ##
+  ## If future has already completed then ``cb`` will be called immediately.
+  ##
+  ## **Note**: This is used for the ``await`` functionality, you most likely
+  ## want to use ``callback``.
+  future.cbVoid = cb
+  if future.finished:
+    future.cbVoid()
+
+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
+    return future.value
+  else:
+    # TODO: Make a custom exception type for this?
+    raise newException(EInvalidValue, "Future still in progress.")
+
+proc finished*[T](future: PFuture[T]): bool =
+  ## Determines whether ``future`` has completed.
+  ##
+  ## ``True`` may indicate an error or a value. Use ``hasError`` to distinguish.
+  future.finished
+
+proc failed*[T](future: PFuture[T]): bool =
+  ## Determines whether ``future`` completed with an error.
+  future.error != nil
+
+when defined(windows):
+  type
+    TCompletionKey = dword
+
+    TCompletionData* = object
+      sock: TSocketHandle
+      cb: proc (sock: TSocketHandle, errcode: TOSErrorCode) {.closure.}
+
+    PDispatcher* = ref object
+      ioPort: THandle
+
+    TCustomOverlapped = object
+      Internal*: DWORD
+      InternalHigh*: DWORD
+      Offset*: DWORD
+      OffsetHigh*: DWORD
+      hEvent*: THANDLE
+      data*: TCompletionData
+
+    PCustomOverlapped = ptr TCustomOverlapped
+
+  proc newDispatcher*(): PDispatcher =
+    ## Creates a new Dispatcher instance.
+    new result
+    result.ioPort = CreateIOCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1)
+
+  proc register*(p: PDispatcher, sock: TSocketHandle) =
+    ## Registers ``sock`` with the dispatcher ``p``.
+    if CreateIOCompletionPort(sock.THandle, p.ioPort,
+                              cast[TCompletionKey](sock), 1) == 0:
+      OSError(OSLastError())
+
+  proc poll*(p: PDispatcher, timeout = 500) =
+    ## Waits for completion events and processes them.
+    let llTimeout =
+      if timeout ==  -1: winlean.INFINITE
+      else: timeout.int32
+    var lpNumberOfBytesTransferred: DWORD
+    var lpCompletionKey: ULONG
+    var lpOverlapped: POverlapped
+    let res = GetQueuedCompletionStatus(p.ioPort, addr lpNumberOfBytesTransferred,
+        addr lpCompletionKey, addr lpOverlapped, llTimeout).bool
+
+    # http://stackoverflow.com/a/12277264/492186
+    # TODO: http://www.serverframework.com/handling-multiple-pending-socket-read-and-write-operations.html
+    var customOverlapped = cast[PCustomOverlapped](lpOverlapped)
+    if res:
+      assert customOverlapped.data.sock == lpCompletionKey.TSocketHandle
+
+      customOverlapped.data.cb(customOverlapped.data.sock, TOSErrorCode(-1))
+      dealloc(customOverlapped)
+    else:
+      let errCode = OSLastError()
+      if lpOverlapped != nil:
+        assert customOverlapped.data.sock == lpCompletionKey.TSocketHandle
+        dealloc(customOverlapped)
+        customOverlapped.data.cb(customOverlapped.data.sock, errCode)
+      else:
+        if errCode.int32 == WAIT_TIMEOUT:
+          # Timed out
+          discard
+        else: OSError(errCode)
+
+  var connectExPtr: pointer = nil
+  var acceptExPtr: pointer = nil
+  var getAcceptExSockAddrsPtr: pointer = nil
+
+  proc initPointer(s: TSocketHandle, func: var pointer, guid: var TGUID): bool =
+    # Ref: https://github.com/powdahound/twisted/blob/master/twisted/internet/iocpreactor/iocpsupport/winsock_pointers.c
+    var bytesRet: DWord
+    func = nil
+    result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, addr guid,
+                      sizeof(TGUID).dword, addr func, sizeof(pointer).DWORD,
+                      addr bytesRet, nil, nil) == 0
+
+  proc initAll() =
+    let dummySock = socket()
+    if not initPointer(dummySock, connectExPtr, WSAID_CONNECTEX):
+      OSError(OSLastError())
+    if not initPointer(dummySock, acceptExPtr, WSAID_ACCEPTEX):
+      OSError(OSLastError())
+    if not initPointer(dummySock, getAcceptExSockAddrsPtr, WSAID_GETACCEPTEXSOCKADDRS):
+      OSError(OSLastError())
+
+  proc connectEx(s: TSocketHandle, name: ptr TSockAddr, namelen: cint, 
+                  lpSendBuffer: pointer, dwSendDataLength: dword,
+                  lpdwBytesSent: PDWORD, lpOverlapped: POverlapped): bool =
+    if connectExPtr.isNil: raise newException(EInvalidValue, "Need to initialise ConnectEx().")
+    let func =
+      cast[proc (s: TSocketHandle, name: ptr TSockAddr, namelen: cint, 
+         lpSendBuffer: pointer, dwSendDataLength: dword,
+         lpdwBytesSent: PDWORD, lpOverlapped: POverlapped): bool {.stdcall.}](connectExPtr)
+
+    result = func(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent,
+         lpOverlapped)
+
+  proc acceptEx(listenSock, acceptSock: TSocketHandle, lpOutputBuffer: pointer,
+                 dwReceiveDataLength, dwLocalAddressLength,
+                 dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD,
+                 lpOverlapped: POverlapped): bool =
+    if acceptExPtr.isNil: raise newException(EInvalidValue, "Need to initialise AcceptEx().")
+    let func =
+      cast[proc (listenSock, acceptSock: TSocketHandle, lpOutputBuffer: pointer,
+                 dwReceiveDataLength, dwLocalAddressLength,
+                 dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD,
+                 lpOverlapped: POverlapped): bool {.stdcall.}](acceptExPtr)
+    result = func(listenSock, acceptSock, lpOutputBuffer, dwReceiveDataLength,
+        dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived,
+        lpOverlapped)
+
+  proc getAcceptExSockaddrs(lpOutputBuffer: pointer,
+      dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength: DWORD,
+      LocalSockaddr: ptr ptr TSockAddr, LocalSockaddrLength: lpint,
+      RemoteSockaddr: ptr ptr TSockAddr, RemoteSockaddrLength: lpint) =
+    if getAcceptExSockAddrsPtr.isNil:
+      raise newException(EInvalidValue, "Need to initialise getAcceptExSockAddrs().")
+
+    let func =
+      cast[proc (lpOutputBuffer: pointer,
+                 dwReceiveDataLength, dwLocalAddressLength,
+                 dwRemoteAddressLength: DWORD, LocalSockaddr: ptr ptr TSockAddr,
+                 LocalSockaddrLength: lpint, RemoteSockaddr: ptr ptr TSockAddr,
+                RemoteSockaddrLength: lpint) {.stdcall.}](getAcceptExSockAddrsPtr)
+    
+    func(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
+                  dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength,
+                  RemoteSockaddr, RemoteSockaddrLength)
+
+  proc connect*(p: PDispatcher, socket: TSocketHandle, address: string, port: TPort,
+    af = AF_INET): PFuture[int] =
+    ## Connects ``socket`` to server at ``address:port``.
+    ##
+    ## Returns a ``PFuture`` which will complete when the connection succeeds
+    ## or an error occurs.
+
+    var retFuture = newFuture[int]()# TODO: Change to void when that regression is fixed.
+    # Apparently ``ConnectEx`` expects the socket to be initially bound:
+    var saddr: Tsockaddr_in
+    saddr.sin_family = int16(toInt(af))
+    saddr.sin_port = 0
+    saddr.sin_addr.s_addr = INADDR_ANY
+    if bindAddr(socket, cast[ptr TSockAddr](addr(saddr)),
+                  sizeof(saddr).TSockLen) < 0'i32:
+      OSError(OSLastError())
+
+    var aiList = getAddrInfo(address, port, af)
+    var success = false
+    var lastError: TOSErrorCode
+    var it = aiList
+    while it != nil:
+      # "the OVERLAPPED structure must remain valid until the I/O completes"
+      # http://blogs.msdn.com/b/oldnewthing/archive/2011/02/02/10123392.aspx
+      var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped)))
+      ol.data = TCompletionData(sock: socket, cb:
+        proc (sock: TSocketHandle, errcode: TOSErrorCode) =
+          if errcode == TOSErrorCode(-1):
+            retFuture.complete(0)
+          else:
+            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+      )
+      
+      var ret = connectEx(socket, it.ai_addr, sizeof(TSockAddrIn).cint,
+                          nil, 0, nil, cast[POverlapped](ol))
+      if ret:
+        # Request to connect completed immediately.
+        success = true
+        retFuture.complete(0)
+        dealloc(ol)
+        break
+      else:
+        lastError = OSLastError()
+        if lastError.int32 == ERROR_IO_PENDING:
+          # In this case ``ol`` will be deallocated in ``poll``.
+          success = true
+          break
+        else:
+          dealloc(ol)
+          success = false
+      it = it.ai_next
+
+    dealloc(aiList)
+    if not success:
+      retFuture.fail(newException(EOS, osErrorMsg(lastError)))
+    return retFuture
+
+  proc recv*(p: PDispatcher, socket: TSocketHandle, size: int): PFuture[string] =
+    ## Reads ``size`` bytes from ``socket``. Returned future will complete once
+    ## all of the requested data is read.
+
+    var retFuture = newFuture[string]()
+    
+    var dataBuf: TWSABuf
+    dataBuf.buf = newString(size)
+    dataBuf.len = size
+    
+    var bytesReceived, flags: DWord
+    var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped)))
+    ol.data = TCompletionData(sock: socket, cb:
+      proc (sock: TSocketHandle, errcode: TOSErrorCode) =
+        if errcode == TOSErrorCode(-1):
+          var data = newString(size)
+          copyMem(addr data[0], addr dataBuf.buf[0], size)
+          retFuture.complete($data)
+        else:
+          retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+    )
+    
+    let ret = WSARecv(socket, addr dataBuf, 1, addr bytesReceived,
+                      addr flags, cast[POverlapped](ol), nil)
+    if ret == -1:
+      let err = OSLastError()
+      if err.int32 != ERROR_IO_PENDING:
+        retFuture.fail(newException(EOS, osErrorMsg(err)))
+        dealloc(ol)
+    else:
+      # Request to read completed immediately.
+      var data = newString(size)
+      copyMem(addr data[0], addr dataBuf.buf[0], size)
+      retFuture.complete($data)
+      dealloc(ol)
+    return retFuture
+
+  proc send*(p: PDispatcher, socket: TSocketHandle, data: string): PFuture[int] =
+    ## Sends ``data`` to ``socket``. The returned future will complete once all
+    ## data has been sent.
+    var retFuture = newFuture[int]()
+
+    var dataBuf: TWSABuf
+    dataBuf.buf = data
+    dataBuf.len = data.len
+
+    var bytesReceived, flags: DWord
+    var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped)))
+    ol.data = TCompletionData(sock: socket, cb:
+      proc (sock: TSocketHandle, errcode: TOSErrorCode) =
+        if errcode == TOSErrorCode(-1):
+          retFuture.complete(0)
+        else:
+          retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+    )
+
+    let ret = WSASend(socket, addr dataBuf, 1, addr bytesReceived,
+                      flags, cast[POverlapped](ol), nil)
+    if ret == -1:
+      let err = osLastError()
+      if err.int32 != ERROR_IO_PENDING:
+        retFuture.fail(newException(EOS, osErrorMsg(err)))
+        dealloc(ol)
+    else:
+      retFuture.complete(0)
+      dealloc(ol)
+    return retFuture
+
+  proc acceptAddr*(p: PDispatcher, socket: TSocketHandle): 
+      PFuture[tuple[address: string, client: TSocketHandle]] =
+    ## 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: TSocketHandle]]()
+
+    var clientSock = socket()
+    if clientSock == OSInvalidSocket: osError(osLastError())
+
+    const lpOutputLen = 1024
+    var lpOutputBuf = newString(lpOutputLen)
+    var dwBytesReceived: DWORD
+    let dwReceiveDataLength = 0.DWORD # We don't want any data to be read.
+    let dwLocalAddressLength = DWORD(sizeof (TSockaddr_in) + 16)
+    let dwRemoteAddressLength = DWORD(sizeof(TSockaddr_in) + 16)
+
+    template completeAccept(): stmt {.immediate, dirty.} =
+      var listenSock = socket
+      let setoptRet = setsockopt(clientSock, SOL_SOCKET,
+          SO_UPDATE_ACCEPT_CONTEXT, addr listenSock,
+          sizeof(listenSock).TSockLen)
+      if setoptRet != 0: osError(osLastError())
+
+      var LocalSockaddr, RemoteSockaddr: ptr TSockAddr
+      var localLen, remoteLen: int32
+      getAcceptExSockaddrs(addr lpOutputBuf[0], dwReceiveDataLength,
+                           dwLocalAddressLength, dwRemoteAddressLength,
+                           addr LocalSockaddr, addr localLen,
+                           addr RemoteSockaddr, addr remoteLen)
+      # TODO: IPv6. Check ``sa_family``. http://stackoverflow.com/a/9212542/492186
+      retFuture.complete(
+        (address: $inet_ntoa(cast[ptr Tsockaddr_in](remoteSockAddr).sin_addr),
+         client: clientSock)
+      )
+
+    var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped)))
+    ol.data = TCompletionData(sock: socket, cb:
+      proc (sock: TSocketHandle, errcode: TOSErrorCode) =
+        if errcode == TOSErrorCode(-1):
+          completeAccept()
+        else:
+          retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+    )
+
+    # http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
+    let ret = acceptEx(socket, clientSock, addr lpOutputBuf[0],
+                       dwReceiveDataLength, 
+                       dwLocalAddressLength,
+                       dwRemoteAddressLength,
+                       addr dwBytesReceived, cast[POverlapped](ol))
+
+    if not ret:
+      let err = osLastError()
+      if err.int32 != ERROR_IO_PENDING:
+        retFuture.fail(newException(EOS, osErrorMsg(err)))
+        dealloc(ol)
+    else:
+      completeAccept()
+      dealloc(ol)
+
+    return retFuture
+
+  proc accept*(p: PDispatcher, socket: TSocketHandle): PFuture[TSocketHandle] =
+    ## 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[TSocketHandle]()
+    var fut = p.acceptAddr(socket)
+    fut.callback =
+      proc (future: PFuture[tuple[address: string, client: TSocketHandle]]) =
+        assert future.finished
+        if future.failed:
+          retFut.fail(future.error)
+        else:
+          retFut.complete(future.read.client)
+    return retFut
+
+  initAll()
+else:
+  # TODO: Selectors.
+
+
+when isMainModule:
+  
+  var p = newDispatcher()
+  var sock = socket()
+  #sock.setBlocking false
+  p.register(sock)
+
+  when true:
+
+    var f = p.connect(sock, "irc.freenode.org", TPort(6667))
+    f.callback =
+      proc (future: PFuture[int]) =
+        echo("Connected in future!")
+        echo(future.read)
+        for i in 0 .. 50:
+          var recvF = p.recv(sock, 10)
+          recvF.callback =
+            proc (future: PFuture[string]) =
+              echo("Read: ", future.read)
+
+  else:
+
+    sock.bindAddr(TPort(6667))
+    sock.listen()
+    proc onAccept(future: PFuture[TSocketHandle]) =
+      echo "Accepted"
+      var t = p.send(future.read, "test\c\L")
+      t.callback =
+        proc (future: PFuture[int]) =
+          echo(future.read)
+      
+      var f = p.accept(sock)
+      f.callback = onAccept
+      
+    var f = p.accept(sock)
+    f.callback = onAccept
+  
+  while true:
+    p.poll()
+    echo "polled"
+
+
+
+
+
+  
+
+  
\ No newline at end of file
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index 3993f1ccc..b2f72ee14 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -276,6 +276,38 @@ template foldr*(sequence, operation: expr): expr =
     result = operation
   result
 
+template mapIt*(seq1, typ, pred: expr): expr =
+  ## Convenience template around the ``map`` proc to reduce typing.
+  ##
+  ## The template injects the ``it`` variable which you can use directly in an
+  ## expression. You also need to pass as `typ` the type of the expression,
+  ## since the new returned sequence can have a different type than the
+  ## original.  Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let
+  ##     nums = @[1, 2, 3, 4]
+  ##     strings = nums.mapIt(string, $(4 * it))
+  var result {.gensym.}: seq[typ] = @[]
+  for it {.inject.} in items(seq1):
+    result.add(pred)
+  result
+
+template mapIt*(varSeq, pred: expr) =
+  ## Convenience template around the mutable ``map`` proc to reduce typing.
+  ##
+  ## The template injects the ``it`` variable which you can use directly in an
+  ## expression. The expression has to return the same type as the sequence you
+  ## are mutating. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var nums = @[1, 2, 3, 4]
+  ##   nums.mapIt(it * 3)
+  ##   assert nums[0] + nums[3] == 15
+  for i in 0 .. <len(varSeq):
+    let it {.inject.} = varSeq[i]
+    varSeq[i] = pred
+
 when isMainModule:
   import strutils
   block: # concat test
@@ -381,4 +413,11 @@ when isMainModule:
     Inserting [2,2,2,2,2,2] into [1,1,1,1,1,1,1,1]
     at 3 is [1,1,1,2,2,2,2,2,2,1,1,1,1,1]"""
 
+  block: # mapIt tests
+    var
+      nums = @[1, 2, 3, 4]
+      strings = nums.mapIt(string, $(4 * it))
+    nums.mapIt(it * 3)
+    assert nums[0] + nums[3] == 15
+
   echo "Finished doc tests"
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index 7259772aa..e6ab617e5 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -224,3 +224,20 @@ proc toOrderedSet*[A](keys: openArray[A]): TOrderedSet[A] =
 proc `$`*[A](s: TOrderedSet[A]): string =
   ## The `$` operator for ordered hash sets.
   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: 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
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index 73da274b9..40ae57b5a 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -189,6 +189,16 @@ template dollarImpl(): stmt {.dirty.} =
 proc `$`*[A, B](t: TTable[A, B]): string =
   ## The `$` operator for hash tables.
   dollarImpl()
+  
+proc `==`*[A, B](s, t: TTable[A, B]): bool =
+  s.counter == t.counter and s.data == t.data
+  
+proc indexBy*[A, B, C](collection: A, index: proc(x: B): C): TTable[C, B] =
+  ## Index the collection with the proc provided.
+  # TODO: As soon as supported, change collection: A to collection: A[B]
+  result = initTable[C, B]()
+  for item in collection:
+    result[index(item)] = item
 
 # ------------------------------ ordered table ------------------------------
 
diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim
index a64b7f138..3ed00fdb2 100644
--- a/lib/pure/dynlib.nim
+++ b/lib/pure/dynlib.nim
@@ -14,15 +14,15 @@
 type
   TLibHandle* = pointer ## a handle to a dynamically loaded library
 
-proc LoadLib*(path: string): TLibHandle
+proc loadLib*(path: string): TLibHandle
   ## loads a library from `path`. Returns nil if the library could not 
   ## be loaded.
 
-proc LoadLib*(): TLibHandle
+proc loadLib*(): TLibHandle
   ## gets the handle from the current executable. Returns nil if the 
   ## library could not be loaded.
 
-proc UnloadLib*(lib: TLibHandle)
+proc unloadLib*(lib: TLibHandle)
   ## unloads the library `lib`
 
 proc raiseInvalidLibrary*(name: cstring) {.noinline, noreturn.} =
@@ -60,9 +60,9 @@ when defined(posix):
   proc dlsym(lib: TLibHandle, name: cstring): pointer {.
       importc, header: "<dlfcn.h>".}
 
-  proc LoadLib(path: string): TLibHandle = return dlopen(path, RTLD_NOW)
-  proc LoadLib(): TLibHandle = return dlopen(nil, RTLD_NOW)
-  proc UnloadLib(lib: TLibHandle) = dlclose(lib)
+  proc loadLib(path: string): TLibHandle = return dlopen(path, RTLD_NOW)
+  proc loadLib(): TLibHandle = return dlopen(nil, RTLD_NOW)
+  proc unloadLib(lib: TLibHandle) = dlclose(lib)
   proc symAddr(lib: TLibHandle, name: cstring): pointer = 
     return dlsym(lib, name)
 
@@ -78,14 +78,14 @@ elif defined(windows) or defined(dos):
   proc FreeLibrary(lib: THINSTANCE) {.importc, header: "<windows.h>", stdcall.}
   proc winLoadLibrary(path: cstring): THINSTANCE {.
       importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
-  proc GetProcAddress(lib: THINSTANCE, name: cstring): pointer {.
+  proc getProcAddress(lib: THINSTANCE, name: cstring): pointer {.
       importc: "GetProcAddress", header: "<windows.h>", stdcall.}
 
-  proc LoadLib(path: string): TLibHandle =
+  proc loadLib(path: string): TLibHandle =
     result = cast[TLibHandle](winLoadLibrary(path))
-  proc LoadLib(): TLibHandle =
+  proc loadLib(): TLibHandle =
     result = cast[TLibHandle](winLoadLibrary(nil))
-  proc UnloadLib(lib: TLibHandle) = FreeLibrary(cast[THINSTANCE](lib))
+  proc unloadLib(lib: TLibHandle) = FreeLibrary(cast[THINSTANCE](lib))
 
   proc symAddr(lib: TLibHandle, name: cstring): pointer =
     result = GetProcAddress(cast[THINSTANCE](lib), name)
diff --git a/lib/pure/htmlparser.nim b/lib/pure/htmlparser.nim
index 060f0e386..c38eb7063 100644
--- a/lib/pure/htmlparser.nim
+++ b/lib/pure/htmlparser.nim
@@ -480,7 +480,7 @@ proc untilElementEnd(x: var TXmlParser, result: PXmlNode,
         if htmlTag(x.elemName) in {tagOption, tagOptgroup}:
           errors.add(expected(x, result))
           break
-      else: nil
+      else: discard
       result.addNode(parse(x, errors))
     of xmlElementEnd: 
       if cmpIgnoreCase(x.elemName, result.tag) == 0: 
@@ -547,7 +547,7 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode =
     var u = entityToUtf8(x.rawData)
     if u.len != 0: result = newText(u)
     next(x)
-  of xmlEof: nil
+  of xmlEof: discard
 
 proc parseHtml*(s: PStream, filename: string, 
                 errors: var seq[string]): PXmlNode = 
diff --git a/lib/pure/irc.nim b/lib/pure/irc.nim
index 750c98516..c1b519b0b 100644
--- a/lib/pure/irc.nim
+++ b/lib/pure/irc.nim
@@ -476,12 +476,12 @@ when isMainModule:
   var client = irc("amber.tenthbit.net", nick="TestBot1234",
                    joinChans = @["#flood"])
   client.connect()
-  while True:
+  while true:
     var event: TIRCEvent
     if client.poll(event):
       case event.typ
       of EvConnected:
-        nil
+        discard
       of EvDisconnected:
         break
       of EvMsg:
diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim
new file mode 100644
index 000000000..284384b37
--- /dev/null
+++ b/lib/pure/logging.nim
@@ -0,0 +1,267 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Andreas Rumpf, Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements a simple logger. It has been designed to be as simple
+## as possible to avoid bloat, if this library does not fullfill your needs,
+## write your own.
+## 
+## Format strings support the following variables which must be prefixed with
+## the dollar operator (``$``):
+##
+## ============  =======================
+##   Operator     Output
+## ============  =======================
+## $date         Current date
+## $time         Current time
+## $app          ``os.getAppFilename()``
+## ============  =======================
+## 
+##
+## The following example demonstrates logging to three different handlers
+## simultaneously:
+##
+## .. code-block:: nimrod
+##     
+##    var L = newConsoleLogger()
+##    var fL = newFileLogger("test.log", fmtStr = verboseFmtStr)
+##    var rL = newRollingFileLogger("rolling.log", fmtStr = verboseFmtStr)
+##    handlers.add(L)
+##    handlers.add(fL)
+##    handlers.add(rL)
+##    info("920410:52 accepted")
+##    warn("4 8 15 16 23 4-- Error")
+##    error("922044:16 SYSTEM FAILURE")
+##    fatal("SYSTEM FAILURE SYSTEM FAILURE")
+
+import strutils, os, times
+
+type
+  TLevel* = enum  ## logging level
+    lvlAll,       ## all levels active
+    lvlDebug,     ## debug level (and any above) active
+    lvlInfo,      ## info level (and any above) active
+    lvlWarn,      ## warn level (and any above) active
+    lvlError,     ## error level (and any above) active
+    lvlFatal,     ## fatal level (and any above) active
+    lvlNone       ## no levels active
+
+const
+  LevelNames*: array [TLevel, string] = [
+    "DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE"
+  ]
+
+  defaultFmtStr* = "" ## default string between log level and message per logger
+  verboseFmtStr* = "$date $time "
+
+type
+  PLogger* = ref object of PObject ## abstract logger; the base type of all loggers
+    levelThreshold*: TLevel    ## only messages of level >= levelThreshold 
+                               ## should be processed
+    fmtStr: string ## = defaultFmtStr by default, see substituteLog for $date etc.
+    
+  PConsoleLogger* = ref object of PLogger ## logger that writes the messages to the
+                                      ## console
+  
+  PFileLogger* = ref object of PLogger ## logger that writes the messages to a file
+    f: TFile
+  
+  PRollingFileLogger* = ref object of PFileLogger ## logger that writes the 
+                                                  ## messages to a file and
+                                                  ## performs log rotation
+    maxLines: int # maximum number of lines    
+    curLine : int
+    baseName: string # initial filename
+    baseMode: TFileMode # initial file mode
+    logFiles: int # how many log files already created, e.g. basename.1, basename.2...
+
+proc substituteLog(frmt: string): string = 
+  ## converts $date to the current date
+  ## converts $time to the current time
+  ## converts $app to getAppFilename()
+  ## converts 
+  result = newStringOfCap(frmt.len + 20)
+  var i = 0
+  while i < frmt.len: 
+    if frmt[i] != '$': 
+      result.add(frmt[i])
+      inc(i)
+    else:
+      inc(i)
+      var v = ""
+      var app = getAppFilename()
+      while frmt[i] in IdentChars: 
+        v.add(toLower(frmt[i]))
+        inc(i)
+      case v
+      of "date": result.add(getDateStr())
+      of "time": result.add(getClockStr())
+      of "app":  result.add(app)
+      of "appdir": result.add(app.splitFile.dir)
+      of "appname": result.add(app.splitFile.name)
+
+method log*(logger: PLogger, level: TLevel,
+            frmt: string, args: varargs[string, `$`]) {.raises: [EBase], tags: [FTime, FWriteIO, FReadIO].} =
+  ## Override this method in custom loggers. Default implementation does
+  ## nothing.
+  discard
+  
+method log*(logger: PConsoleLogger, level: TLevel,
+            frmt: string, args: varargs[string, `$`]) =
+  ## Logs to the console using ``logger`` only.
+  if level >= logger.levelThreshold:
+    writeln(stdout, LevelNames[level], " ", substituteLog(logger.fmtStr),
+            frmt % args)
+
+method log*(logger: PFileLogger, level: TLevel, 
+            frmt: string, args: varargs[string, `$`]) =
+  ## Logs to a file using ``logger`` only.
+  if level >= logger.levelThreshold:
+    writeln(logger.f, LevelNames[level], " ",
+            substituteLog(logger.fmtStr), frmt % args)
+
+proc defaultFilename*(): string = 
+  ## Returns the default filename for a logger.
+  var (path, name, ext) = splitFile(getAppFilename())
+  result = changeFileExt(path / name, "log")
+
+proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr): PConsoleLogger =
+  ## Creates a new console logger. This logger logs to the console.
+  new result
+  result.fmtStr = fmtStr
+  result.levelThreshold = levelThreshold
+
+proc newFileLogger*(filename = defaultFilename(), 
+                    mode: TFileMode = fmAppend,
+                    levelThreshold = lvlAll,
+                    fmtStr = defaultFmtStr): PFileLogger = 
+  ## Creates a new file logger. This logger logs to a file.
+  new(result)
+  result.levelThreshold = levelThreshold
+  result.f = open(filename, mode)
+  result.fmtStr = fmtStr
+
+# ------
+
+proc countLogLines(logger: PRollingFileLogger): int =
+  result = 0
+  for line in logger.f.lines():
+    result.inc()
+
+proc countFiles(filename: string): int =
+  # Example: file.log.1
+  result = 0
+  let (dir, name, ext) = splitFile(filename)
+  for kind, path in walkDir(dir):
+    if kind == pcFile:
+      let llfn = name & ext & ExtSep
+      if path.extractFilename.startsWith(llfn):
+        let numS = path.extractFilename[llfn.len .. -1]
+        try:
+          let num = parseInt(numS)
+          if num > result:
+            result = num
+        except EInvalidValue: discard
+
+proc newRollingFileLogger*(filename = defaultFilename(), 
+                           mode: TFileMode = fmReadWrite,
+                           levelThreshold = lvlAll,
+                           fmtStr = defaultFmtStr,
+                           maxLines = 1000): PRollingFileLogger =
+  ## Creates a new rolling file logger. Once a file reaches ``maxLines`` lines
+  ## a new log file will be started and the old will be renamed.
+  new(result)
+  result.levelThreshold = levelThreshold
+  result.fmtStr = defaultFmtStr
+  result.maxLines = maxLines
+  result.f = open(filename, mode)
+  result.curLine = 0
+  result.baseName = filename
+  result.baseMode = mode
+  
+  result.logFiles = countFiles(filename)
+  
+  if mode == fmAppend:
+    # We need to get a line count because we will be appending to the file.
+    result.curLine = countLogLines(result)
+
+proc rotate(logger: PRollingFileLogger) =
+  let (dir, name, ext) = splitFile(logger.baseName)
+  for i in countdown(logger.logFiles, 0):
+    let srcSuff = if i != 0: ExtSep & $i else: ""
+    moveFile(dir / (name & ext & srcSuff),
+             dir / (name & ext & ExtSep & $(i+1)))
+
+method log*(logger: PRollingFileLogger, level: TLevel, 
+            frmt: string, args: varargs[string, `$`]) =
+  ## Logs to a file using rolling ``logger`` only.
+  if level >= logger.levelThreshold:
+    if logger.curLine >= logger.maxLines:
+      logger.f.close()
+      rotate(logger)
+      logger.logFiles.inc
+      logger.curLine = 0
+      logger.f = open(logger.baseName, logger.baseMode)
+    
+    writeln(logger.f, LevelNames[level], " ", frmt % args)
+    logger.curLine.inc
+
+# --------
+
+var
+  level* = lvlAll  ## global log filter
+  handlers*: seq[PLogger] = @[] ## handlers with their own log levels
+
+proc logLoop(level: TLevel, frmt: string, args: varargs[string, `$`]) =
+  for logger in items(handlers): 
+    if level >= logger.levelThreshold:
+      log(logger, level, frmt, args)
+
+template log*(level: TLevel, frmt: string, args: varargs[string, `$`]) =
+  ## Logs a message to all registered handlers at the given level.
+  bind logLoop
+  bind `%`
+  bind logging.Level
+  
+  if level >= logging.Level:
+    logLoop(level, frmt, args)
+
+template debug*(frmt: string, args: varargs[string, `$`]) =
+  ## Logs a debug message to all registered handlers.
+  log(lvlDebug, frmt, args)
+
+template info*(frmt: string, args: varargs[string, `$`]) = 
+  ## Logs an info message to all registered handlers.
+  log(lvlInfo, frmt, args)
+
+template warn*(frmt: string, args: varargs[string, `$`]) = 
+  ## Logs a warning message to all registered handlers.
+  log(lvlWarn, frmt, args)
+
+template error*(frmt: string, args: varargs[string, `$`]) = 
+  ## Logs an error message to all registered handlers.
+  log(lvlError, frmt, args)
+  
+template fatal*(frmt: string, args: varargs[string, `$`]) =  
+  ## Logs a fatal error message to all registered handlers.
+  log(lvlFatal, frmt, args)
+
+
+# --------------
+
+when isMainModule:
+  var L = newConsoleLogger()
+  var fL = newFileLogger("test.log", fmtStr = verboseFmtStr)
+  var rL = newRollingFileLogger("rolling.log", fmtStr = verboseFmtStr)
+  handlers.add(L)
+  handlers.add(fL)
+  handlers.add(rL)
+  for i in 0 .. 25:
+    info("hello" & $i, [])
+  
+
diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim
index b57e0c45a..2db7fa660 100644
--- a/lib/pure/matchers.nim
+++ b/lib/pure/matchers.nim
@@ -54,7 +54,7 @@ proc parseInt*(s: string, value: var int, validRange: TSlice[int]) {.
   try:
     discard parseutils.parseInt(s, x, 0)
   except EOverflow:
-    nil
+    discard
   if x in validRange: value = x
 
 when isMainModule:
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
new file mode 100644
index 000000000..bdcae677e
--- /dev/null
+++ b/lib/pure/net.nim
@@ -0,0 +1,40 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements a high-level cross-platform sockets interface.
+
+import sockets2, os
+
+type
+  TSocket* = TSocketHandle
+
+proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {.
+  tags: [FReadIO].} =
+
+  ## binds an address/port number to a socket.
+  ## Use address string in dotted decimal form like "a.b.c.d"
+  ## or leave "" for any address.
+
+  if address == "":
+    var name: TSockaddr_in
+    when defined(windows):
+      name.sin_family = toInt(AF_INET).int16
+    else:
+      name.sin_family = toInt(AF_INET)
+    name.sin_port = htons(int16(port))
+    name.sin_addr.s_addr = htonl(INADDR_ANY)
+    if bindAddr(socket, cast[ptr TSockAddr](addr(name)),
+                  sizeof(name).TSocklen) < 0'i32:
+      osError(osLastError())
+  else:
+    var aiList = getAddrInfo(address, port, AF_INET)
+    if bindAddr(socket, aiList.ai_addr, aiList.ai_addrlen.TSocklen) < 0'i32:
+      dealloc(aiList)
+      osError(osLastError())
+    dealloc(aiList)
\ No newline at end of file
diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim
index fbe0dda95..b3e74d2a1 100644
--- a/lib/pure/oids.nim
+++ b/lib/pure/oids.nim
@@ -28,7 +28,7 @@ proc hexbyte*(hex: char): int =
   of '0'..'9': result = (ord(hex) - ord('0'))
   of 'a'..'f': result = (ord(hex) - ord('a') + 10)
   of 'A'..'F': result = (ord(hex) - ord('A') + 10)
-  else: nil
+  else: discard
 
 proc parseOid*(str: cstring): TOid =
   ## parses an OID.
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 1f42d0d58..bb70f28b6 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -287,12 +287,18 @@ proc osLastError*(): TOSErrorCode =
     result = TOSErrorCode(errno)
 {.pop.}
 
-proc unixToNativePath*(path: string): string {.
+proc unixToNativePath*(path: string, drive=""): string {.
   noSideEffect, rtl, extern: "nos$1".} =
   ## Converts an UNIX-like path to a native one.
   ##
   ## On an UNIX system this does nothing. Else it converts
   ## '/', '.', '..' to the appropriate things.
+  ##
+  ## On systems with a concept of "drives", `drive` is used to determine
+  ## which drive label to use during absolute path conversion.
+  ## `drive` defaults to the drive of the current working directory, and is
+  ## ignored on systems that do not have a concept of "drives".
+
   when defined(unix):
     result = path
   else:
@@ -300,7 +306,10 @@ proc unixToNativePath*(path: string): string {.
     if path[0] == '/':
       # an absolute path
       when doslike:
-        result = r"C:\"
+        if drive != "":
+          result = drive & ":" & DirSep
+        else:
+          result = $DirSep
       elif defined(macos):
         result = "" # must not start with ':'
       else:
@@ -387,6 +396,21 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} =
     var res: TStat
     return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
 
+proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
+                                          tags: [FReadDir].} =
+  ## Returns true iff the symlink `link` exists. Will return true
+  ## regardless of whether the link points to a directory or file.
+  when defined(windows):
+    when useWinUnicode:
+      wrapUnary(a, getFileAttributesW, link)
+    else:
+      var a = getFileAttributesA(link)
+    if a != -1'i32:
+      result = (a and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32
+  else:
+    var res: TStat
+    return lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode)
+
 proc fileExists*(filename: string): bool {.inline.} =
   ## Synonym for existsFile
   existsFile(filename)
@@ -1013,7 +1037,7 @@ proc execShellCmd*(command: string): int {.rtl, extern: "nos$1",
   ## the process has finished. To execute a program without having a
   ## shell involved, use the `execProcess` proc of the `osproc`
   ## module.
-  result = c_system(command)
+  result = c_system(command) shr 8
 
 # Environment handling cannot be put into RTL, because the ``envPairs``
 # iterator depends on ``environment``.
@@ -1054,9 +1078,9 @@ when defined(windows):
         while true:
           var eend = strEnd(e)
           add(environment, $e)
-          e = cast[CString](cast[TAddress](eend)+1)
+          e = cast[cstring](cast[TAddress](eend)+1)
           if eend[1] == '\0': break
-        discard FreeEnvironmentStringsA(env)
+        discard freeEnvironmentStringsA(env)
       envComputed = true
 
 else:
@@ -1221,6 +1245,8 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {.
         if not skipFindData(f):
           if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32:
             k = pcDir
+          if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
+            k = succ(k)
           yield (k, dir / extractFilename(getFilename(f)))
         if findNextFile(h, f) == 0'i32: break
       findClose(h)
@@ -1245,6 +1271,10 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
   tags: [FReadDir].} =
   ## walks over the directory `dir` and yields for each file in `dir`. The
   ## full path for each file is returned.
+  ## **Warning**:
+  ## Modifying the directory structure while the iterator 
+  ## is traversing may result in undefined behavior! 
+  ## 
   ## Walking is recursive. `filter` controls the behaviour of the iterator:
   ##
   ## ---------------------   ---------------------------------------------
@@ -1336,6 +1366,46 @@ proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
       copyDir(path, dest / noSource)
     else: discard
 
+proc createSymlink*(src, dest: string) =
+  ## Create a symbolic link at `dest` which points to the item specified
+  ## by `src`. On most operating systems, will fail if a lonk
+  ##
+  ## **Warning**:
+  ## Some OS's (such as Microsoft Windows) restrict the creation 
+  ## of symlinks to root users (administrators).
+  when defined(Windows):
+    let flag = dirExists(src).int32
+    when useWinUnicode:
+      var wSrc = newWideCString(src)
+      var wDst = newWideCString(dest)
+      if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0:
+        osError(osLastError())
+    else:
+      if createSymbolicLinkA(dest, src, flag) == 0 or getLastError() != 0:
+        osError(osLastError())
+  else:
+    if symlink(src, dest) != 0:
+      osError(osLastError())
+
+proc createHardlink*(src, dest: string) =
+  ## Create a hard link at `dest` which points to the item specified
+  ## by `src`.
+  ##
+  ## **Warning**: Most OS's restrict the creation of hard links to 
+  ## root users (administrators) .
+  when defined(Windows):
+    when useWinUnicode:
+      var wSrc = newWideCString(src)
+      var wDst = newWideCString(dest)
+      if createHardLinkW(wDst, wSrc, nil) == 0:
+        osError(osLastError())
+    else:
+      if createHardLinkA(dest, src, nil) == 0:
+        osError(osLastError())
+  else:
+    if link(src, dest) != 0:
+      osError(osLastError())
+
 proc parseCmdLine*(c: string): seq[string] {.
   noSideEffect, rtl, extern: "nos$1".} =
   ## Splits a command line into several components;
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 676707abb..6df85bbc6 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -13,7 +13,7 @@
 include "system/inclrtl"
 
 import
-  strutils, os, strtabs, streams
+  strutils, os, strtabs, streams, sequtils
 
 when defined(windows):
   import winlean
@@ -36,11 +36,17 @@ type
 
   TProcessOption* = enum ## options that can be passed `startProcess`
     poEchoCmd,           ## echo the command before execution
-    poUseShell,          ## use the shell to execute the command; NOTE: This
-                         ## often creates a security hole!
+    poUsePath,           ## Asks system to search for executable using PATH environment
+                         ## variable.
+                         ## On Windows, this is the default.
+    poEvalCommand,       ## Pass `command` directly to the shell, without quoting.
+                         ## Use it only if `command` comes from trused source.
     poStdErrToStdOut,    ## merge stdout and stderr to the stdout stream
     poParentStreams      ## use the parent's streams
 
+template poUseShell*: TProcessOption {.deprecated.} = poUsePath
+  ## Deprecated alias for poUsePath.
+
 proc quoteShellWindows*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} =
   ## Quote s, so it can be safely passed to Windows API.
   ## Based on Python's subprocess.list2cmdline
@@ -94,12 +100,17 @@ proc quoteShell*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} =
     {.error:"quoteShell is not supported on your system".}
 
 proc execProcess*(command: string,
+                  args: openarray[string] = [],
+                  env: PStringTable = nil,
                   options: set[TProcessOption] = {poStdErrToStdOut,
-                                                  poUseShell}): TaintedString {.
+                                                  poUsePath,
+                                                  poEvalCommand}): TaintedString {.
                                                   rtl, extern: "nosp$1",
                                                   tags: [FExecIO, FReadIO].}
   ## A convenience procedure that executes ``command`` with ``startProcess``
   ## and returns its output as a string.
+  ## WARNING: this function uses poEvalCommand by default for backward compatibility.
+  ## Make sure to pass options explicitly.
 
 proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [FExecIO].}
   ## Executes ``command`` and returns its error code. Standard input, output,
@@ -109,8 +120,8 @@ proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [FExecIO].}
 proc startProcess*(command: string,
                    workingDir: string = "",
                    args: openArray[string] = [],
-                   env: PStringTable = nil, 
-                   options: set[TProcessOption] = {poStdErrToStdOut}): 
+                   env: PStringTable = nil,
+                   options: set[TProcessOption] = {poStdErrToStdOut}):
               PProcess {.rtl, extern: "nosp$1", tags: [FExecIO, FReadEnv].}
   ## Starts a process. `Command` is the executable file, `workingDir` is the
   ## process's working directory. If ``workingDir == ""`` the current directory
@@ -127,16 +138,10 @@ proc startProcess*(command: string,
   ## but ``EOS`` is raised in case of an error.
 
 proc startCmd*(command: string, options: set[TProcessOption] = {
-               poStdErrToStdOut, poUseShell}): PProcess {.
-               tags: [FExecIO, FReadEnv].} =
-  ## a simpler version of `startProcess` that parses the command line into
-  ## program and arguments and then calls `startProcess` with the empty string
-  ## for `workingDir` and the nil string table for `env`.
-  var c = parseCmdLine(command)
-  var a: seq[string]
-  newSeq(a, c.len-1) # avoid slicing for now (still unstable)
-  for i in 1 .. c.len-1: a[i-1] = c[i]
-  result = startProcess(command=c[0], args=a, options=options)
+               poStdErrToStdOut, poUsePath}): PProcess {.
+               tags: [FExecIO, FReadEnv], deprecated.} =
+  ## Deprecated - use `startProcess` directly.
+  result = startProcess(command=command, options=options + {poEvalCommand})
 
 proc close*(p: PProcess) {.rtl, extern: "nosp$1", tags: [].}
   ## When the process has finished executing, cleanup related handles
@@ -157,7 +162,7 @@ proc processID*(p: PProcess): int {.rtl, extern: "nosp$1".} =
   ## returns `p`'s process ID.
   return p.id
 
-proc waitForExit*(p: PProcess, timeout: int = -1): int {.rtl, 
+proc waitForExit*(p: PProcess, timeout: int = -1): int {.rtl,
   extern: "nosp$1", tags: [].}
   ## waits for the process to finish and returns `p`'s error code.
 
@@ -167,19 +172,19 @@ proc peekExitCode*(p: PProcess): int {.tags: [].}
 proc inputStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].}
   ## returns ``p``'s input stream for writing to.
   ##
-  ## **Warning**: The returned `PStream` should not be closed manually as it 
+  ## **Warning**: The returned `PStream` should not be closed manually as it
   ## is closed when closing the PProcess ``p``.
 
 proc outputStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].}
   ## returns ``p``'s output stream for reading from.
   ##
-  ## **Warning**: The returned `PStream` should not be closed manually as it 
+  ## **Warning**: The returned `PStream` should not be closed manually as it
   ## is closed when closing the PProcess ``p``.
 
 proc errorStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].}
   ## returns ``p``'s error stream for reading from.
   ##
-  ## **Warning**: The returned `PStream` should not be closed manually as it 
+  ## **Warning**: The returned `PStream` should not be closed manually as it
   ## is closed when closing the PProcess ``p``.
 
 proc inputHandle*(p: PProcess): TFileHandle {.rtl, extern: "nosp$1",
@@ -245,15 +250,15 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
 
 proc execProcesses*(cmds: openArray[string],
                     options = {poStdErrToStdOut, poParentStreams},
-                    n = countProcessors()): int {.rtl, extern: "nosp$1", 
-                    tags: [FExecIO, FTime, FReadEnv].} =
+                    n = countProcessors()): int {.rtl, extern: "nosp$1",
+                    tags: [FExecIO, FTime, FReadEnv]} =
   ## executes the commands `cmds` in parallel. Creates `n` processes
   ## that execute in parallel. The highest return value of all processes
   ## is returned.
   when defined(posix):
     # poParentStreams causes problems on Posix, so we simply disable it:
     var options = options - {poParentStreams}
-  
+
   assert n > 0
   if n > 1:
     var q: seq[PProcess]
@@ -307,13 +312,17 @@ proc select*(readfds: var seq[PProcess], timeout = 500): int
 
 when not defined(useNimRtl):
   proc execProcess(command: string,
+                   args: openarray[string] = [],
+                   env: PStringTable = nil,
                    options: set[TProcessOption] = {poStdErrToStdOut,
-                                                   poUseShell}): TaintedString =
-    var p = startCmd(command, options=options)
+                                                   poUsePath,
+                                                   poEvalCommand}): TaintedString =
+    var p = startProcess(command, args=args, env=env, options=options)
     var outp = outputStream(p)
     result = TaintedString""
     var line = newStringOfCap(120).TaintedString
     while true:
+      # FIXME: converts CR-LF to LF.
       if outp.readLine(line):
         result.string.add(line.string)
         result.string.add("\n")
@@ -427,8 +436,9 @@ when defined(Windows) and not defined(useNimRtl):
       result.errHandle = TFileHandle(si.hStdError)
 
     var cmdl: cstring
-    when false: # poUseShell in options:
-      cmdl = buildCommandLine(getEnv("COMSPEC"), @["/c", command] & args)
+    if poEvalCommand in options:
+      cmdl = command
+      assert args.len == 0
     else:
       cmdl = buildCommandLine(command, args)
     var wd: cstring = nil
@@ -441,11 +451,11 @@ when defined(Windows) and not defined(useNimRtl):
       var ee = newWideCString(e)
       var wwd = newWideCString(wd)
       success = winlean.createProcessW(nil,
-        tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT, 
+        tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT,
         ee, wwd, si, procInfo)
     else:
       success = winlean.createProcessA(nil,
-        cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo)
+        cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, si, procInfo)
     let lastError = osLastError()
 
     if poParentStreams notin options:
@@ -455,7 +465,6 @@ when defined(Windows) and not defined(useNimRtl):
         fileClose(si.hStdError)
 
     if e != nil: dealloc(e)
-    dealloc(cmdl)
     if success == 0: osError(lastError)
     # Close the handle now so anyone waiting is woken:
     discard closeHandle(procInfo.hThread)
@@ -495,7 +504,7 @@ when defined(Windows) and not defined(useNimRtl):
   proc peekExitCode(p: PProcess): int =
     var b = waitForSingleObject(p.fProcessHandle, 50) == WAIT_TIMEOUT
     if b: result = -1
-    else: 
+    else:
       var res: int32
       discard getExitCodeProcess(p.fProcessHandle, res)
       return res
@@ -525,7 +534,7 @@ when defined(Windows) and not defined(useNimRtl):
         NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
     else:
       var res = winlean.createProcessA(nil, command, nil, nil, 0,
-        NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo)
+        NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
     if res == 0:
       osError(osLastError())
     else:
@@ -538,13 +547,13 @@ when defined(Windows) and not defined(useNimRtl):
         result = -1
       discard closeHandle(process)
 
-  proc select(readfds: var seq[PProcess], timeout = 500): int = 
+  proc select(readfds: var seq[PProcess], timeout = 500): int =
     assert readfds.len <= MAXIMUM_WAIT_OBJECTS
     var rfds: TWOHandleArray
     for i in 0..readfds.len()-1:
       rfds[i] = readfds[i].fProcessHandle
-    
-    var ret = waitForMultipleObjects(readfds.len.int32, 
+
+    var ret = waitForMultipleObjects(readfds.len.int32,
                                      addr(rfds), 0'i32, timeout.int32)
     case ret
     of WAIT_TIMEOUT:
@@ -561,22 +570,7 @@ elif not defined(useNimRtl):
     readIdx = 0
     writeIdx = 1
 
-  proc addCmdArgs(command: string, args: openArray[string]): string =
-    result = quoteShell(command)
-    for i in 0 .. high(args):
-      add(result, " ")
-      add(result, quoteShell(args[i]))
-
-  proc toCStringArray(b, a: openArray[string]): cstringArray =
-    result = cast[cstringArray](alloc0((a.len + b.len + 1) * sizeof(cstring)))
-    for i in 0..high(b):
-      result[i] = cast[cstring](alloc(b[i].len+1))
-      copyMem(result[i], cstring(b[i]), b[i].len+1)
-    for i in 0..high(a):
-      result[i+b.len] = cast[cstring](alloc(a[i].len+1))
-      copyMem(result[i+b.len], cstring(a[i]), a[i].len+1)
-
-  proc toCStringArray(t: PStringTable): cstringArray =
+  proc envToCStringArray(t: PStringTable): cstringArray =
     result = cast[cstringArray](alloc0((t.len + 1) * sizeof(cstring)))
     var i = 0
     for key, val in pairs(t):
@@ -595,7 +589,7 @@ elif not defined(useNimRtl):
       result[i] = cast[cstring](alloc(x.len+1))
       copyMem(result[i], addr(x[0]), x.len+1)
       inc(i)
-    
+
   proc startProcess(command: string,
                  workingDir: string = "",
                  args: openArray[string] = [],
@@ -609,23 +603,38 @@ elif not defined(useNimRtl):
       if pipe(pStdin) != 0'i32 or pipe(pStdout) != 0'i32 or
          pipe(pStderr) != 0'i32:
         osError(osLastError())
-    
+
+    var sys_command: string
+    var sys_args_raw: seq[string]
+    if poEvalCommand in options:
+      sys_command = "/bin/sh"
+      sys_args_raw = @[sys_command, "-c", command]
+      assert args.len == 0
+    else:
+      sys_command = command
+      sys_args_raw = @[command]
+      for arg in args.items:
+        sys_args_raw.add arg
+
+    var sys_args = allocCStringArray(sys_args_raw)
+    finally: deallocCStringArray(sys_args)
+
     var pid: TPid
     when defined(posix_spawn) and not defined(useFork):
       var attr: Tposix_spawnattr
       var fops: Tposix_spawn_file_actions
 
-      template chck(e: expr) = 
+      template chck(e: expr) =
         if e != 0'i32: osError(osLastError())
 
       chck posix_spawn_file_actions_init(fops)
       chck posix_spawnattr_init(attr)
-      
+
       var mask: Tsigset
       chck sigemptyset(mask)
       chck posix_spawnattr_setsigmask(attr, mask)
       chck posix_spawnattr_setpgroup(attr, 0'i32)
-      
+
       chck posix_spawnattr_setflags(attr, POSIX_SPAWN_USEVFORK or
                                           POSIX_SPAWN_SETSIGMASK or
                                           POSIX_SPAWN_SETPGROUP)
@@ -639,27 +648,22 @@ elif not defined(useNimRtl):
         if poStdErrToStdOut in options:
           chck posix_spawn_file_actions_adddup2(fops, pStdout[writeIdx], 2)
         else:
-          chck posix_spawn_file_actions_adddup2(fops, pStderr[writeIdx], 2)
-      
-      var e = if env == nil: envToCStringArray() else: toCStringArray(env)
-      var a: cstringArray
+          chck posix_spawn_file_actions_adddup2(fops, p_stderr[writeIdx], 2)
+
+      var sys_env = if env == nil: envToCStringArray() else: envToCStringArray(env)
       var res: cint
+      # This is incorrect!
       if workingDir.len > 0: os.setCurrentDir(workingDir)
-      if poUseShell notin options:
-        a = toCStringArray([extractFilename(command)], args)
-        res = posix_spawn(pid, command, fops, attr, a, e)
+      if poUsePath in options:
+        res = posix_spawnp(pid, sys_command, fops, attr, sys_args, sys_env)
       else:
-        var x = addCmdArgs(command, args)
-        a = toCStringArray(["sh", "-c"], [x])
-        res = posix_spawn(pid, "/bin/sh", fops, attr, a, e)
-      deallocCStringArray(a)
-      deallocCStringArray(e)
+        res = posix_spawn(pid, sys_command, fops, attr, sys_args, sys_env)
+      deallocCStringArray(sys_env)
       discard posix_spawn_file_actions_destroy(fops)
       discard posix_spawnattr_destroy(attr)
       chck res
 
     else:
-    
       pid = fork()
       if pid < 0: osError(osLastError())
       if pid == 0:
@@ -680,19 +684,18 @@ elif not defined(useNimRtl):
         if setpgid(0, 0) == -1: quit("setpgid call failed: " & $strerror(errno))
 
         if workingDir.len > 0: os.setCurrentDir(workingDir)
-        if poUseShell notin options:
-          var a = toCStringArray([extractFilename(command)], args)
-          if env == nil:
-            discard execv(command, a)
+
+        if env == nil:
+          if poUsePath in options:
+            discard execvp(sys_command, sys_args)
           else:
-            discard execve(command, a, toCStringArray(env))
+            discard execv(sys_command, sys_args)
         else:
-          var x = addCmdArgs(command, args)
-          var a = toCStringArray(["sh", "-c"], [x])
-          if env == nil:
-            discard execv("/bin/sh", a)
+          var c_env = envToCStringArray(env)
+          if poUsePath in options:
+            discard execvpe(sys_command, sys_args, c_env)
           else:
-            discard execve("/bin/sh", a, toCStringArray(env))
+            discard execve(sys_command, sys_args, c_env)
         # too risky to raise an exception here:
         quit("execve call failed: " & $strerror(errno))
     # Parent process. Copy process information.
@@ -788,15 +791,15 @@ elif not defined(useNimRtl):
   proc csystem(cmd: cstring): cint {.nodecl, importc: "system".}
 
   proc execCmd(command: string): int =
-    result = csystem(command)
+    result = csystem(command) shr 8
 
-  proc createFdSet(fd: var TFdSet, s: seq[PProcess], m: var int) = 
+  proc createFdSet(fd: var TFdSet, s: seq[PProcess], m: var int) =
     FD_ZERO(fd)
-    for i in items(s): 
+    for i in items(s):
       m = max(m, int(i.outHandle))
       FD_SET(cint(i.outHandle), fd)
-     
-  proc pruneProcessSet(s: var seq[PProcess], fd: var TFdSet) = 
+
+  proc pruneProcessSet(s: var seq[PProcess], fd: var TFdSet) =
     var i = 0
     var L = s.len
     while i < L:
@@ -807,26 +810,26 @@ elif not defined(useNimRtl):
         inc(i)
     setLen(s, L)
 
-  proc select(readfds: var seq[PProcess], timeout = 500): int = 
-    var tv: Ttimeval
+  proc select(readfds: var seq[PProcess], timeout = 500): int =
+    var tv: TTimeVal
     tv.tv_sec = 0
     tv.tv_usec = timeout * 1000
-    
+
     var rd: TFdSet
     var m = 0
     createFdSet((rd), readfds, m)
-    
+
     if timeout != -1:
       result = int(select(cint(m+1), addr(rd), nil, nil, addr(tv)))
     else:
       result = int(select(cint(m+1), addr(rd), nil, nil, nil))
-    
+
     pruneProcessSet(readfds, (rd))
 
 
 proc execCmdEx*(command: string, options: set[TProcessOption] = {
-                poStdErrToStdOut, poUseShell}): tuple[
-                output: TaintedString, 
+                poStdErrToStdOut, poUsePath}): tuple[
+                output: TaintedString,
                 exitCode: int] {.tags: [FExecIO, FReadIO].} =
   ## a convenience proc that runs the `command`, grabs all its output and
   ## exit code and returns both.
diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim
index 5970f2090..4b25babec 100644
--- a/lib/pure/parsecsv.nim
+++ b/lib/pure/parsecsv.nim
@@ -149,7 +149,7 @@ proc readRow*(my: var TCsvParser, columns = 0): bool =
           of '\c': my.bufpos = handleCR(my, my.bufpos)
           of '\l': my.bufpos = handleLF(my, my.bufpos)
           else: break
-      of '\0': nil
+      of '\0': discard
       else: error(my, my.bufpos, my.sep & " expected")
       break
   
diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim
index 31951e966..3f9686e1e 100644
--- a/lib/pure/parsesql.nim
+++ b/lib/pure/parsesql.nim
@@ -79,7 +79,7 @@ proc handleHexChar(c: var TSqlLexer, xi: var int) =
     xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
     inc(c.bufpos)
   else: 
-    nil
+    discard
 
 proc handleOctChar(c: var TSqlLexer, xi: var int) = 
   if c.buf[c.bufpos] in {'0'..'7'}:
@@ -373,7 +373,7 @@ proc getOperator(c: var TSqlLexer, tok: var TToken) =
     of '+':
       if not trailingPlusMinus and buf[pos+1] notin operators and
            tok.literal.len > 0: break
-    of '*', '<', '>', '=': nil
+    of '*', '<', '>', '=': discard
     else: break
     add(tok.literal, buf[pos])
     inc(pos)
@@ -1120,7 +1120,7 @@ proc rs(n: PSqlNode, s: var string, indent: int,
 proc ra(n: PSqlNode, s: var string, indent: int) =
   if n == nil: return
   case n.kind
-  of nkNone: nil
+  of nkNone: discard
   of nkIdent:
     if allCharsInSet(n.strVal, {'\33'..'\127'}):
       s.add(n.strVal)
diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim
new file mode 100644
index 000000000..83c158da1
--- /dev/null
+++ b/lib/pure/selectors.nim
@@ -0,0 +1,249 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2013 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+# TODO: Docs.
+
+import tables, os, unsigned
+when defined(windows):
+  import winlean
+else:
+  import posix
+
+type
+  TEvent* = enum
+    EvRead, EvWrite
+
+  TSelectorKey* = object
+    fd: cint
+    events: set[TEvent]
+    data: PObject
+
+  TReadyInfo* = tuple[key: TSelectorKey, events: set[TEvent]]
+
+  PSelector* = ref object of PObject ## Selector interface.
+    fds*: TTable[cint, TSelectorKey]
+    registerImpl*: proc (s: PSelector, fd: cint, events: set[TEvent],
+                    data: PObject): TSelectorKey {.nimcall, tags: [FWriteIO].}
+    unregisterImpl*: proc (s: PSelector, fd: cint): TSelectorKey {.nimcall, tags: [FWriteIO].}
+    selectImpl*: proc (s: PSelector, timeout: int): seq[TReadyInfo] {.nimcall, tags: [FReadIO].}
+    closeImpl*: proc (s: PSelector) {.nimcall.}
+
+template initSelector(r: expr) =
+  new r
+  r.fds = initTable[cint, TSelectorKey]()
+
+proc register*(s: PSelector, fd: cint, events: set[TEvent], data: PObject):
+    TSelectorKey =
+  if not s.registerImpl.isNil: result = s.registerImpl(s, fd, events, data)
+
+proc unregister*(s: PSelector, fd: cint): TSelectorKey =
+  ##
+  ## **Note:** For the ``epoll`` implementation the resulting ``TSelectorKey``
+  ## will only have the ``fd`` field set. This is an optimisation and may
+  ## change in the future if a viable use case is presented. 
+  if not s.unregisterImpl.isNil: result = s.unregisterImpl(s, fd)
+
+proc select*(s: PSelector, timeout = 500): seq[TReadyInfo] =
+  ##
+  ## The ``events`` field of the returned ``key`` contains the original events
+  ## for which the ``fd`` was bound. This is contrary to the ``events`` field
+  ## of the ``TReadyInfo`` tuple which determines which events are ready
+  ## on the ``fd``.
+
+  if not s.selectImpl.isNil: result = s.selectImpl(s, timeout)
+
+proc close*(s: PSelector) =
+  if not s.closeImpl.isNil: s.closeImpl(s)
+
+# ---- Select() ----------------------------------------------------------------
+
+type
+  PSelectSelector* = ref object of PSelector ## Implementation of select()
+
+proc ssRegister(s: PSelector, fd: cint, events: set[TEvent],
+    data: PObject): TSelectorKey =
+  if s.fds.hasKey(fd):
+    raise newException(EInvalidValue, "FD already exists in selector.")
+  var sk = TSelectorKey(fd: fd, events: events, data: data)
+  s.fds[fd] = sk
+  result = sk
+
+proc ssUnregister(s: PSelector, fd: cint): TSelectorKey =
+  result = s.fds[fd]
+  s.fds.del(fd)
+
+proc ssClose(s: PSelector) = nil
+
+proc timeValFromMilliseconds(timeout: int): TTimeVal =
+  if timeout != -1:
+    var seconds = timeout div 1000
+    result.tv_sec = seconds.int32
+    result.tv_usec = ((timeout - seconds * 1000) * 1000).int32
+
+proc createFdSet(rd, wr: var TFdSet, fds: TTable[cint, TSelectorKey],
+    m: var int) =
+  FD_ZERO(rd); FD_ZERO(wr)
+  for k, v in pairs(fds):
+    if EvRead in v.events: 
+      m = max(m, int(k))
+      FD_SET(k, rd)
+    if EvWrite in v.events:
+      m = max(m, int(k))
+      FD_SET(k, wr)
+   
+proc getReadyFDs(rd, wr: var TFdSet, fds: TTable[cint, TSelectorKey]):
+    seq[TReadyInfo] =
+  result = @[]
+  for k, v in pairs(fds):
+    var events: set[TEvent] = {}
+    if FD_ISSET(k, rd) != 0'i32:
+      events = events + {EvRead}
+    if FD_ISSET(k, wr) != 0'i32:
+      events = events + {EvWrite}
+    result.add((v, events))
+
+proc select(fds: TTable[cint, TSelectorKey], timeout = 500):
+  seq[TReadyInfo] =
+  var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout)
+  
+  var rd, wr: TFdSet
+  var m = 0
+  createFdSet(rd, wr, fds, m)
+  
+  var retCode = 0
+  if timeout != -1:
+    retCode = int(select(cint(m+1), addr(rd), addr(wr), nil, addr(tv)))
+  else:
+    retCode = int(select(cint(m+1), addr(rd), addr(wr), nil, nil))
+  
+  if retCode < 0:
+    OSError(OSLastError())
+  elif retCode == 0:
+    return @[]
+  else:
+    return getReadyFDs(rd, wr, fds)
+
+proc ssSelect(s: PSelector, timeout: int): seq[TReadyInfo] =
+  result = select(s.fds, timeout)
+
+proc newSelectSelector*(): PSelectSelector =
+  initSelector(result)
+  result.registerImpl = ssRegister
+  result.unregisterImpl = ssUnregister
+  result.selectImpl = ssSelect
+  result.closeImpl = ssClose
+
+# ---- Epoll -------------------------------------------------------------------
+
+when defined(linux):
+  import epoll
+  type
+    PEpollSelector* = ref object of PSelector
+      epollFD: cint
+      events: array[64, ptr epoll_event]
+  
+    TDataWrapper = object
+      fd: cint
+      boundEvents: set[TEvent] ## The events which ``fd`` listens for.
+      data: PObject ## User object.
+  
+  proc esRegister(s: PSelector, fd: cint, events: set[TEvent],
+      data: PObject): TSelectorKey =
+    var es = PEpollSelector(s)
+    var event: epoll_event
+    if EvRead in events:
+      event.events = EPOLLIN
+    if EvWrite in events:
+      event.events = event.events or EPOLLOUT
+    
+    var dw = cast[ptr TDataWrapper](alloc0(sizeof(TDataWrapper))) # TODO: This needs to be dealloc'd
+    dw.fd = fd
+    dw.boundEvents = events
+    dw.data = data
+    event.data.thePtr = dw
+    
+    if epoll_ctl(es.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0:
+      OSError(OSLastError())
+    
+    result = TSelectorKey(fd: fd, events: events, data: data)
+  
+  proc esUnregister(s: PSelector, fd: cint): TSelectorKey =
+    # We cannot find out the information about this ``fd`` from the epoll
+    # context. As such I will simply return an almost empty TSelectorKey.
+    var es = PEpollSelector(s)
+    if epoll_ctl(es.epollFD, EPOLL_CTL_DEL, fd, nil) != 0:
+      OSError(OSLastError())
+    # We could fill in the ``fds`` TTable to get the info, but that wouldn't
+    # be nice for our memory.
+    result = TSelectorKey(fd: fd, events: {}, data: nil)
+
+  proc esClose(s: PSelector) =
+    var es = PEpollSelector(s)
+    if es.epollFD.close() != 0: OSError(OSLastError())
+    dealloc(addr es.events) # TODO: Test this
+  
+  proc esSelect(s: PSelector, timeout: int): seq[TReadyInfo] =
+    result = @[]
+    var es = PEpollSelector(s)
+    
+    let evNum = epoll_wait(es.epollFD, es.events[0], 64.cint, timeout.cint)
+    if evNum < 0: OSError(OSLastError())
+    if evNum == 0: return @[]
+    for i in 0 .. <evNum:
+      var evSet: set[TEvent] = {}
+      if (es.events[i].events and EPOLLIN) != 0: evSet = evSet + {EvRead}
+      if (es.events[i].events and EPOLLOUT) != 0: evSet = evSet + {EvWrite}
+      let dw = cast[ptr TDataWrapper](es.events[i].data.thePtr)
+      
+      let selectorKey = TSelectorKey(fd: dw.fd, events: dw.boundEvents, 
+          data: dw.data)
+      result.add((selectorKey, evSet))
+  
+  proc newEpollSelector*(): PEpollSelector =
+    new result
+    result.epollFD = epoll_create(64)
+    result.events = cast[array[64, ptr epoll_event]](alloc0(sizeof(epoll_event)*64))
+    if result.epollFD < 0:
+      OSError(OSLastError())
+    result.registerImpl = esRegister
+    result.unregisterImpl = esUnregister
+    result.closeImpl = esClose
+    result.selectImpl = esSelect
+
+when isMainModule:
+  # Select()
+  import sockets
+  type
+    PSockWrapper = ref object of PObject
+      sock: TSocket
+  
+  var sock = socket()
+  sock.connect("irc.freenode.net", TPort(6667))
+  
+  var selector = newEpollSelector()
+  var data = PSockWrapper(sock: sock)
+  let key = selector.register(sock.getFD.cint, {EvRead}, data)
+  var i = 0
+  while true:
+    let ready = selector.select(1000)
+    echo ready.len
+    if ready.len > 0: echo ready[0].events
+    i.inc
+    if i == 6:
+      selector.close()
+      break
+  
+  
+  
+  
+  
+  
+  
+  
+  
\ No newline at end of file
diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim
index 6a3f65279..88afeb589 100644
--- a/lib/pure/smtp.nim
+++ b/lib/pure/smtp.nim
@@ -66,13 +66,15 @@ proc checkReply(smtp: var TSMTP, reply: string) =
   if not line.string.startswith(reply):
     quitExcpt(smtp, "Expected " & reply & " reply, got: " & line.string)
 
+const compiledWithSsl = defined(ssl)
+
 proc connect*(address: string, port = 25, 
               ssl = false, debug = false): TSMTP =
   ## Establishes a connection with a SMTP server.
   ## May fail with EInvalidReply or with a socket error.
   result.sock = socket()
   if ssl:
-    when defined(ssl):
+    when compiledWithSsl:
       let ctx = newContext(verifyMode = CVerifyNone)
       ctx.wrapSocket(result.sock)
     else:
diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim
index fd6403118..76d37879b 100644
--- a/lib/pure/sockets.nim
+++ b/lib/pure/sockets.nim
@@ -311,7 +311,8 @@ when defined(ssl):
       newCTX.SSLCTXSetVerify(SSLVerifyNone, nil)
     if newCTX == nil:
       SSLError()
-    
+
+    discard newCTX.SSLCTXSetMode(SSL_MODE_AUTO_RETRY)
     newCTX.loadCertificates(certFile, keyFile)
     return PSSLContext(newCTX)
 
@@ -1291,14 +1292,14 @@ proc readLine*(socket: TSocket, line: var TaintedString, timeout = -1) {.
     var c: char
     discard waitFor(socket, waited, timeout, 1, "readLine")
     var n = recv(socket, addr(c), 1)
-    if n < 0: osError(osLastError())
+    if n < 0: socket.socketError()
     elif n == 0: return
     if c == '\r':
       discard waitFor(socket, waited, timeout, 1, "readLine")
       n = peekChar(socket, c)
       if n > 0 and c == '\L':
         discard recv(socket, addr(c), 1)
-      elif n <= 0: osError(osLastError())
+      elif n <= 0: socket.socketError()
       addNLIfEmpty()
       return
     elif c == '\L': 
diff --git a/lib/pure/sockets2.nim b/lib/pure/sockets2.nim
new file mode 100644
index 000000000..22624bbad
--- /dev/null
+++ b/lib/pure/sockets2.nim
@@ -0,0 +1,202 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements a low-level cross-platform sockets interface. Look
+## at the ``net`` module for the higher-level version.
+
+import unsigned, os
+
+when hostos == "solaris":
+  {.passl: "-lsocket -lnsl".}
+
+when defined(Windows):
+  import winlean
+else:
+  import posix
+
+export TSocketHandle, TSockaddr_in, TAddrinfo, INADDR_ANY, TSockAddr, TSockLen,
+  inet_ntoa
+
+type
+  
+  TPort* = distinct uint16  ## port type
+  
+  TDomain* = enum   ## domain, which specifies the protocol family of the
+                    ## created socket. Other domains than those that are listed
+                    ## here are unsupported.
+    AF_UNIX,        ## for local socket (using a file). Unsupported on Windows.
+    AF_INET = 2,    ## for network protocol IPv4 or
+    AF_INET6 = 23   ## for network protocol IPv6.
+
+  TType* = enum        ## second argument to `socket` proc
+    SOCK_STREAM = 1,   ## reliable stream-oriented service or Stream Sockets
+    SOCK_DGRAM = 2,    ## datagram service or Datagram Sockets
+    SOCK_RAW = 3,      ## raw protocols atop the network layer.
+    SOCK_SEQPACKET = 5 ## reliable sequenced packet service
+
+  TProtocol* = enum     ## third argument to `socket` proc
+    IPPROTO_TCP = 6,    ## Transmission control protocol. 
+    IPPROTO_UDP = 17,   ## User datagram protocol.
+    IPPROTO_IP,         ## Internet protocol. Unsupported on Windows.
+    IPPROTO_IPV6,       ## Internet Protocol Version 6. Unsupported on Windows.
+    IPPROTO_RAW,        ## Raw IP Packets Protocol. Unsupported on Windows.
+    IPPROTO_ICMP        ## Control message protocol. Unsupported on Windows.
+
+  TServent* {.pure, final.} = object ## information about a service
+    name*: string
+    aliases*: seq[string]
+    port*: TPort
+    proto*: string
+
+  Thostent* {.pure, final.} = object ## information about a given host
+    name*: string
+    aliases*: seq[string]
+    addrtype*: TDomain
+    length*: int
+    addrList*: seq[string]
+
+when defined(windows):
+  let
+    OSInvalidSocket* = winlean.INVALID_SOCKET
+else:
+  let
+    OSInvalidSocket* = posix.INVALID_SOCKET
+
+proc `==`*(a, b: TPort): bool {.borrow.}
+  ## ``==`` for ports.
+
+proc `$`*(p: TPort): string {.borrow.}
+  ## returns the port number as a string
+
+proc toInt*(domain: TDomain): cint
+  ## Converts the TDomain enum to a platform-dependent ``cint``.
+
+proc toInt*(typ: TType): cint
+  ## Converts the TType enum to a platform-dependent ``cint``.
+
+proc toInt*(p: TProtocol): cint
+  ## Converts the TProtocol enum to a platform-dependent ``cint``.
+
+when defined(posix):
+  proc toInt(domain: TDomain): cint =
+    case domain
+    of AF_UNIX:        result = posix.AF_UNIX
+    of AF_INET:        result = posix.AF_INET
+    of AF_INET6:       result = posix.AF_INET6
+    else: nil
+
+  proc toInt(typ: TType): cint =
+    case typ
+    of SOCK_STREAM:    result = posix.SOCK_STREAM
+    of SOCK_DGRAM:     result = posix.SOCK_DGRAM
+    of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET
+    of SOCK_RAW:       result = posix.SOCK_RAW
+    else: nil
+
+  proc toInt(p: TProtocol): cint =
+    case p
+    of IPPROTO_TCP:    result = posix.IPPROTO_TCP
+    of IPPROTO_UDP:    result = posix.IPPROTO_UDP
+    of IPPROTO_IP:     result = posix.IPPROTO_IP
+    of IPPROTO_IPV6:   result = posix.IPPROTO_IPV6
+    of IPPROTO_RAW:    result = posix.IPPROTO_RAW
+    of IPPROTO_ICMP:   result = posix.IPPROTO_ICMP
+    else: nil
+
+else:
+  proc toInt(domain: TDomain): cint = 
+    result = toU16(ord(domain))
+
+  proc toInt(typ: TType): cint =
+    result = cint(ord(typ))
+  
+  proc toInt(p: TProtocol): cint =
+    result = cint(ord(p))
+
+
+proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
+             protocol: TProtocol = IPPROTO_TCP): TSocketHandle =
+  ## Creates a new socket; returns `InvalidSocket` if an error occurs.
+  
+  # TODO: The function which will use this will raise EOS.
+  socket(toInt(domain), toInt(typ), toInt(protocol))
+
+proc close*(socket: TSocketHandle) =
+  ## closes a socket.
+  when defined(windows):
+    discard winlean.closeSocket(socket)
+  else:
+    discard posix.close(socket)
+  # TODO: These values should not be discarded. An EOS should be raised.
+  # http://stackoverflow.com/questions/12463473/what-happens-if-you-call-close-on-a-bsd-socket-multiple-times
+
+proc bindAddr*(socket: TSocketHandle, name: ptr TSockAddr, namelen: TSockLen): cint =
+  result = bindSocket(socket, name, namelen)
+
+proc listen*(socket: TSocketHandle, backlog = SOMAXCONN) {.tags: [FReadIO].} =
+  ## Marks ``socket`` as accepting connections. 
+  ## ``Backlog`` specifies the maximum length of the 
+  ## queue of pending connections.
+  when defined(windows):
+    if winlean.listen(socket, cint(backlog)) < 0'i32: osError(osLastError())
+  else:
+    if posix.listen(socket, cint(backlog)) < 0'i32: osError(osLastError())
+
+proc getAddrInfo*(address: string, port: TPort, af: TDomain = AF_INET, typ: TType = SOCK_STREAM,
+                 prot: TProtocol = IPPROTO_TCP): ptr TAddrInfo =
+  ##
+  ##
+  ## **Warning**: The resulting ``ptr TAddrInfo`` must be freed using ``dealloc``!
+  var hints: TAddrInfo
+  result = nil
+  hints.ai_family = toInt(af)
+  hints.ai_socktype = toInt(typ)
+  hints.ai_protocol = toInt(prot)
+  var gaiResult = getAddrInfo(address, $port, addr(hints), result)
+  if gaiResult != 0'i32:
+    when defined(windows):
+      OSError(OSLastError())
+    else:
+      raise newException(EOS, $gai_strerror(gaiResult))
+
+proc dealloc*(ai: ptr TAddrInfo) =
+  freeaddrinfo(ai)
+
+proc ntohl*(x: int32): int32 = 
+  ## Converts 32-bit integers from network to host byte order.
+  ## On machines where the host byte order is the same as network byte order,
+  ## this is a no-op; otherwise, it performs a 4-byte swap operation.
+  when cpuEndian == bigEndian: result = x
+  else: result = (x shr 24'i32) or
+                 (x shr 8'i32 and 0xff00'i32) or
+                 (x shl 8'i32 and 0xff0000'i32) or
+                 (x shl 24'i32)
+
+proc ntohs*(x: int16): int16 =
+  ## Converts 16-bit integers from network to host byte order. On machines
+  ## where the host byte order is the same as network byte order, this is
+  ## a no-op; otherwise, it performs a 2-byte swap operation.
+  when cpuEndian == bigEndian: result = x
+  else: result = (x shr 8'i16) or (x shl 8'i16)
+
+proc htonl*(x: int32): int32 =
+  ## Converts 32-bit integers from host to network byte order. On machines
+  ## where the host byte order is the same as network byte order, this is
+  ## a no-op; otherwise, it performs a 4-byte swap operation.
+  result = sockets2.ntohl(x)
+
+proc htons*(x: int16): int16 =
+  ## Converts 16-bit positive integers from host to network byte order.
+  ## On machines where the host byte order is the same as network byte
+  ## order, this is a no-op; otherwise, it performs a 2-byte swap operation.
+  result = sockets2.ntohs(x)
+
+when defined(Windows):
+  var wsa: TWSADATA
+  if WSAStartup(0x0101'i16, addr wsa) != 0: OSError(OSLastError())
\ No newline at end of file
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index de8dc5e51..b63224cec 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -45,6 +45,16 @@ const
   NewLines* = {'\13', '\10'}
     ## 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:
+    ##
+    ## .. code-block:: nimrod
+    ##   let invalid = AllChars - Digits
+    ##   doAssert "01234".find(invalid) == -1
+    ##   doAssert "01A34".find(invalid) == 2
+
 proc toLower*(c: char): char {.noSideEffect, procvar,
   rtl, extern: "nsuToLowerChar".} =
   ## Converts `c` into lower case. This works only for the letters A-Z.
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 6186fcad8..de6c4e4fa 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -211,7 +211,9 @@ proc initInterval*(miliseconds, seconds, minutes, hours, days, months,
   result.months = months
   result.years = years
 
-proc isLeapYear(year: int): bool =
+proc isLeapYear*(year: int): bool =
+  ## returns true if ``year`` is a leap year
+
   if year mod 400 == 0:
     return true
   elif year mod 100 == 0: 
@@ -221,7 +223,9 @@ proc isLeapYear(year: int): bool =
   else:
     return false
 
-proc getDaysInMonth(month: TMonth, year: int): int =
+proc getDaysInMonth*(month: TMonth, year: int): int =
+  ## gets the amount of days in a ``month`` of a ``year``
+
   # http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month
   case month 
   of mFeb: result = if isLeapYear(year): 29 else: 28
diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim
index 16bbe1455..8b8bb3b03 100644
--- a/lib/pure/xmlparser.nim
+++ b/lib/pure/xmlparser.nim
@@ -96,7 +96,7 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode =
     ## &entity;
     errors.add(errorMsg(x, "unknown entity: " & x.entityName))
     next(x)
-  of xmlEof: nil
+  of xmlEof: discard
 
 proc parseXml*(s: PStream, filename: string, 
                errors: var seq[string]): PXmlNode = 
@@ -110,7 +110,7 @@ proc parseXml*(s: PStream, filename: string,
     of xmlElementOpen, xmlElementStart: 
       result = parse(x, errors)
       break
-    of xmlComment, xmlWhitespace, xmlSpecial, xmlPI: nil # just skip it
+    of xmlComment, xmlWhitespace, xmlSpecial, xmlPI: discard # just skip it
     of xmlError:
       errors.add(errorMsg(x))
     else:
diff --git a/lib/system.nim b/lib/system.nim
index 09e44a45a..2acb989c5 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2333,29 +2333,29 @@ when not defined(JS): #and not defined(NimrodVM):
 
 elif defined(JS):
   # Stubs:
-  proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = nil
-
-  proc GC_disable() = nil
-  proc GC_enable() = nil
-  proc GC_fullCollect() = nil
-  proc GC_setStrategy(strategy: TGC_Strategy) = nil
-  proc GC_enableMarkAndSweep() = nil
-  proc GC_disableMarkAndSweep() = nil
+  proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = discard
+
+  proc GC_disable() = discard
+  proc GC_enable() = discard
+  proc GC_fullCollect() = discard
+  proc GC_setStrategy(strategy: TGC_Strategy) = discard
+  proc GC_enableMarkAndSweep() = discard
+  proc GC_disableMarkAndSweep() = discard
   proc GC_getStatistics(): string = return ""
   
   proc getOccupiedMem(): int = return -1
   proc getFreeMem(): int = return -1
   proc getTotalMem(): int = return -1
 
-  proc dealloc(p: pointer) = nil
-  proc alloc(size: int): pointer = nil
-  proc alloc0(size: int): pointer = nil
-  proc realloc(p: Pointer, newsize: int): pointer = nil
+  proc dealloc(p: pointer) = discard
+  proc alloc(size: int): pointer = discard
+  proc alloc0(size: int): pointer = discard
+  proc realloc(p: Pointer, newsize: int): pointer = discard
 
-  proc allocShared(size: int): pointer = nil
-  proc allocShared0(size: int): pointer = nil
-  proc deallocShared(p: pointer) = nil
-  proc reallocShared(p: pointer, newsize: int): pointer = nil
+  proc allocShared(size: int): pointer = discard
+  proc allocShared0(size: int): pointer = discard
+  proc deallocShared(p: pointer) = discard
+  proc reallocShared(p: pointer, newsize: int): pointer = discard
 
   when defined(JS):
     include "system/jssys"
@@ -2490,11 +2490,11 @@ proc staticRead*(filename: string): string {.magic: "Slurp".}
   ## ``slurp`` is an alias for ``staticRead``.
 
 proc gorge*(command: string, input = ""): string {.
-  magic: "StaticExec".} = nil
+  magic: "StaticExec".} = discard
   ## This is an alias for ``staticExec``.
 
 proc staticExec*(command: string, input = ""): string {.
-  magic: "StaticExec".} = nil
+  magic: "StaticExec".} = discard
   ## Executes an external process at compile-time.
   ## if `input` is not an empty string, it will be passed as a standard input
   ## to the executed program.
@@ -2561,7 +2561,7 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[
   ##         $pos.line, astToStr(code)]
   ##       assert false, "A test expecting failure succeeded?"
   ##     except exception:
-  ##       nil
+  ##       discard
   ##
   ##   proc tester(pos: int): int =
   ##     let
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index a3f6669d4..e50ba7b9f 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -23,7 +23,7 @@ else:
   proc MessageBoxA(hWnd: cint, lpText, lpCaption: cstring, uType: int): int32 {.
     header: "<windows.h>", nodecl.}
 
-  proc writeToStdErr(msg: CString) =
+  proc writeToStdErr(msg: cstring) =
     discard MessageBoxA(0, msg, nil, 0)
 
 proc showErrorMessage(data: cstring) =
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 820093b3e..b08a6d214 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -802,7 +802,7 @@ when defined(sparc): # For SPARC architecture.
     # Addresses decrease as the stack grows.
     while sp <= max:
       gcMark(gch, sp[])
-      sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
+      sp = cast[PPointer](cast[TAddress](sp) +% sizeof(pointer))
 
 elif defined(ELATE):
   {.error: "stack marking code is to be written for this architecture".}
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index 2e3596985..e78a4e5cd 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -59,11 +59,11 @@ var
   gch {.rtlThreadVar.}: TGcHeap
 
 when not defined(useNimRtl):
-  InstantiateForRegion(gch.region)
+  instantiateForRegion(gch.region)
 
 template acquire(gch: TGcHeap) = 
   when hasThreadSupport and hasSharedHeap:
-    AcquireSys(HeapLock)
+    acquireSys(HeapLock)
 
 template release(gch: TGcHeap) = 
   when hasThreadSupport and hasSharedHeap:
@@ -90,7 +90,7 @@ proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
   # used for code generation concerning debugging
   result = usrToCell(c).typ
 
-proc unsureAsgnRef(dest: ppointer, src: pointer) {.inline.} =
+proc unsureAsgnRef(dest: PPointer, src: pointer) {.inline.} =
   dest[] = src
 
 proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
@@ -114,10 +114,10 @@ when BitsPerPage mod (sizeof(int)*8) != 0:
 
 # forward declarations:
 proc collectCT(gch: var TGcHeap)
-proc IsOnStack*(p: pointer): bool {.noinline.}
+proc isOnStack*(p: pointer): bool {.noinline.}
 proc forAllChildren(cell: PCell, op: TWalkOp)
 proc doOperation(p: pointer, op: TWalkOp)
-proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp)
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp)
 # we need the prototype here for debugging purposes
 
 proc prepareDealloc(cell: PCell) =
@@ -162,19 +162,19 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
     if m != nil: forAllSlotsAux(dest, m, op)
   of nkNone: sysAssert(false, "forAllSlotsAux")
 
-proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
   var d = cast[TAddress](dest)
   if dest == nil: return # nothing to do
   if ntfNoRefs notin mt.flags:
-    case mt.Kind
+    case mt.kind
     of tyRef, tyString, tySequence: # leaf:
-      doOperation(cast[ppointer](d)[], op)
+      doOperation(cast[PPointer](d)[], op)
     of tyObject, tyTuple:
       forAllSlotsAux(dest, mt.node, op)
     of tyArray, tyArrayConstr, tyOpenArray:
       for i in 0..(mt.size div mt.base.size)-1:
         forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
-    else: nil
+    else: discard
 
 proc forAllChildren(cell: PCell, op: TWalkOp) =
   gcAssert(cell != nil, "forAllChildren: 1")
@@ -184,7 +184,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
   if marker != nil:
     marker(cellToUsr(cell), op.int)
   else:
-    case cell.typ.Kind
+    case cell.typ.kind
     of tyRef: # common case
       forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
     of tySequence:
@@ -194,7 +194,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
         for i in 0..s.len-1:
           forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
             GenericSeqSize), cell.typ.base, op)
-    else: nil
+    else: discard
 
 proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
   # generates a new object and sets its reference counter to 0
@@ -466,7 +466,7 @@ else:
         sp = sp +% sizeof(pointer)*8
       # last few entries:
       while sp <=% max:
-        gcMark(gch, cast[ppointer](sp)[])
+        gcMark(gch, cast[PPointer](sp)[])
         sp = sp +% sizeof(pointer)
 
 # ----------------------------------------------------------------------------
@@ -505,7 +505,7 @@ when not defined(useNimRtl):
       else:
         dec(gch.recGcLock)
 
-  proc GC_setStrategy(strategy: TGC_Strategy) = nil
+  proc GC_setStrategy(strategy: TGC_Strategy) = discard
 
   proc GC_enableMarkAndSweep() =
     gch.cycleThreshold = InitialThreshold
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 91c6495ce..6c8fa4882 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -16,8 +16,12 @@ const
 type
   THandle* = int
   LONG* = int32
+  ULONG* = int
+  PULONG* = ptr int
   WINBOOL* = int32
   DWORD* = int32
+  PDWORD* = ptr DWORD
+  LPINT* = ptr int32
   HDC* = THandle
   HGLRC* = THandle
 
@@ -195,16 +199,31 @@ else:
     importc: "GetCurrentDirectoryA", dynlib: "kernel32", stdcall.}
   proc setCurrentDirectoryA*(lpPathName: cstring): int32 {.
     importc: "SetCurrentDirectoryA", dynlib: "kernel32", stdcall.}
-  proc createDirectoryA*(pathName: cstring, security: Pointer=nil): int32 {.
+  proc createDirectoryA*(pathName: cstring, security: pointer=nil): int32 {.
     importc: "CreateDirectoryA", dynlib: "kernel32", stdcall.}
   proc removeDirectoryA*(lpPathName: cstring): int32 {.
     importc: "RemoveDirectoryA", dynlib: "kernel32", stdcall.}
   proc setEnvironmentVariableA*(lpName, lpValue: cstring): int32 {.
     stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableA".}
 
-  proc getModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {.
+  proc getModuleFileNameA*(handle: THandle, buf: cstring, size: int32): int32 {.
     importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.}
-  
+
+when useWinUnicode:
+  proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: WideCString,
+                         flags: DWORD): int32 {.
+    importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall.}
+  proc createHardLinkW*(lpFileName, lpExistingFileName: WideCString,
+                         security: pointer=nil): int32 {.
+    importc:"CreateHardLinkW", dynlib: "kernel32", stdcall.}
+else:
+  proc createSymbolicLinkA*(lpSymlinkFileName, lpTargetFileName: cstring,
+                           flags: DWORD): int32 {.
+    importc:"CreateSymbolicLinkA", dynlib: "kernel32", stdcall.}
+  proc createHardLinkA*(lpFileName, lpExistingFileName: cstring,
+                           security: pointer=nil): int32 {.
+    importc:"CreateHardLinkA", dynlib: "kernel32", stdcall.}
+
 const
   FILE_ATTRIBUTE_ARCHIVE* = 32'i32
   FILE_ATTRIBUTE_COMPRESSED* = 2048'i32
@@ -212,6 +231,7 @@ const
   FILE_ATTRIBUTE_DIRECTORY* = 16'i32
   FILE_ATTRIBUTE_HIDDEN* = 2'i32
   FILE_ATTRIBUTE_READONLY* = 1'i32
+  FILE_ATTRIBUTE_REPARSE_POINT* = 1024'i32
   FILE_ATTRIBUTE_SYSTEM* = 4'i32
   FILE_ATTRIBUTE_TEMPORARY* = 256'i32
 
@@ -284,7 +304,7 @@ else:
                            dwFileAttributes: int32): WINBOOL {.
       stdcall, dynlib: "kernel32", importc: "SetFileAttributesA".}
 
-  proc copyFileA*(lpExistingFileName, lpNewFileName: CString,
+  proc copyFileA*(lpExistingFileName, lpNewFileName: cstring,
                  bFailIfExists: cint): cint {.
     importc: "CopyFileA", stdcall, dynlib: "kernel32".}
 
@@ -616,3 +636,76 @@ when not useWinUnicode:
 proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall,
     dynlib: "kernel32", importc: "UnmapViewOfFile".}
 
+type
+  TOVERLAPPED* {.final, pure.} = object
+    Internal*: DWORD
+    InternalHigh*: DWORD
+    Offset*: DWORD
+    OffsetHigh*: DWORD
+    hEvent*: THANDLE
+
+  POVERLAPPED* = ptr TOVERLAPPED
+
+  POVERLAPPED_COMPLETION_ROUTINE* = proc (para1: DWORD, para2: DWORD,
+      para3: POVERLAPPED){.stdcall.}
+
+  TGUID* {.final, pure.} = object
+    D1*: int32
+    D2*: int16
+    D3*: int16
+    D4*: array [0..7, int8]
+
+const
+  ERROR_IO_PENDING* = 997
+
+proc CreateIoCompletionPort*(FileHandle: THANDLE, ExistingCompletionPort: THANDLE,
+                             CompletionKey: DWORD,
+                             NumberOfConcurrentThreads: DWORD): THANDLE{.stdcall,
+    dynlib: "kernel32", importc: "CreateIoCompletionPort".}
+
+proc GetQueuedCompletionStatus*(CompletionPort: THandle,
+    lpNumberOfBytesTransferred: PDWORD, lpCompletionKey: PULONG,
+                                lpOverlapped: ptr POverlapped,
+                                dwMilliseconds: DWORD): WINBOOL{.stdcall,
+    dynlib: "kernel32", importc: "GetQueuedCompletionStatus".}
+
+const 
+ IOC_OUT* = 0x40000000
+ IOC_IN*  = 0x80000000
+ IOC_WS2* = 0x08000000
+ IOC_INOUT* = IOC_IN or IOC_OUT
+
+template WSAIORW*(x,y): expr = (IOC_INOUT or x or y)
+
+const
+  SIO_GET_EXTENSION_FUNCTION_POINTER* = WSAIORW(IOC_WS2,6).DWORD
+  SO_UPDATE_ACCEPT_CONTEXT* = 0x700B
+
+var
+  WSAID_CONNECTEX*: TGUID = TGUID(D1: 0x25a207b9, D2: 0xddf3'i16, D3: 0x4660, D4: [
+    0x8e'i8, 0xe9'i8, 0x76'i8, 0xe5'i8, 0x8c'i8, 0x74'i8, 0x06'i8, 0x3e'i8])
+  WSAID_ACCEPTEX*: TGUID = TGUID(D1: 0xb5367df1'i32, D2: 0xcbac'i16, D3: 0x11cf, D4: [
+    0x95'i8, 0xca'i8, 0x00'i8, 0x80'i8, 0x5f'i8, 0x48'i8, 0xa1'i8, 0x92'i8])
+  WSAID_GETACCEPTEXSOCKADDRS*: TGUID = TGUID(D1: 0xb5367df2'i32, D2: 0xcbac'i16, D3: 0x11cf, D4: [
+    0x95'i8, 0xca'i8, 0x00'i8, 0x80'i8, 0x5f'i8, 0x48'i8, 0xa1'i8, 0x92'i8])
+
+proc WSAIoctl*(s: TSocketHandle, dwIoControlCode: DWORD, lpvInBuffer: pointer,
+  cbInBuffer: DWORD, lpvOutBuffer: pointer, cbOutBuffer: DWORD,
+  lpcbBytesReturned: PDword, lpOverlapped: POVERLAPPED,
+  lpCompletionRoutine: POVERLAPPED_COMPLETION_ROUTINE): cint 
+  {.stdcall, importc: "WSAIoctl", dynlib: "Ws2_32.dll".}
+
+type
+  TWSABuf* {.importc: "WSABUF", header: "winsock2.h".} = object
+    len*: ULONG
+    buf*: cstring
+
+proc WSARecv*(s: TSocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
+  bytesReceived, flags: PDWORD, lpOverlapped: POverlapped,
+  completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {.
+  stdcall, importc: "WSARecv", dynlib: "Ws2_32.dll".}
+
+proc WSASend*(s: TSocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
+  bytesSent: PDWord, flags: DWORD, lpOverlapped: POverlapped,
+  completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {.
+  stdcall, importc: "WSASend", dynlib: "Ws2_32.dll".}
diff --git a/lib/wrappers/mongo.nim b/lib/wrappers/mongo.nim
index 6673e8ddf..098b4f4d3 100644
--- a/lib/wrappers/mongo.nim
+++ b/lib/wrappers/mongo.nim
@@ -109,11 +109,12 @@ type
     cur*: cstring
     dataSize*: cint
     finished*: TBsonBool
-    stack*: array[0..32 - 1, cint]
+    ownsData*: TBsonBool
+    err*: cint
+    stackSize*: cint
     stackPos*: cint
-    err*: cint       ## Bitfield representing errors or warnings on this buffer 
-    errstr*: cstring ## A string representation of the most recent error
-                     ## or warning. 
+    stackPtr*: ptr csize
+    stack*: array[0..32 - 1, csize]
   
   TDate* = int64
 
@@ -141,6 +142,7 @@ proc print*(TBson: cstring, depth: cint) {.stdcall,
     importc: "bson_print_raw", dynlib: bsondll.}
   ## Print a string representation of a BSON object up to `depth`.
 
+
 proc data*(b: var TBson): cstring{.stdcall, importc: "bson_data", 
                                    dynlib: bsondll.}
   ## Return a pointer to the raw buffer stored by this bson object.
@@ -590,19 +592,30 @@ type
     hosts*: ptr THostPort    ## List of host/ports given by the replica set 
     name*: cstring           ## Name of the replica set. 
     primary_connected*: TBsonBool ## Primary node connection status. 
+
+  TWriteConcern*{.pure, final.} = object ## mongo_write_concern
+    w*: cint
+    wtimeout*: cint
+    j*: cint
+    fsync*: cint
+    mode*: cstring
+    cmd*: TBSon
   
   TMongo*{.pure, final.} = object ## mongo
-    primary*: ptr THostPort   ## Primary connection info. 
-    replset*: ptr TReplSet    ## replset object if connected to a replica set. 
-    sock*: cint               ## Socket file descriptor. 
-    flags*: cint              ## Flags on this connection object. 
-    conn_timeout_ms*: cint    ## Connection timeout in milliseconds. 
-    op_timeout_ms*: cint      ## Read and write timeout in milliseconds. 
-    connected*: TBsonBool     ## Connection status. 
-    err*: TError              ## Most recent driver error code. 
-    errstr*: array[0..128 - 1, char] ## String version of most recent driver error code. 
-    lasterrcode*: cint        ## getlasterror code given by the server on error. 
-    lasterrstr*: cstring      ## getlasterror string generated by server. 
+    primary*: ptr THostPort              ## Primary connection info. 
+    replset*: ptr TReplSet               ## replset object if connected to a replica set. 
+    sock*: cint                          ## Socket file descriptor. 
+    flags*: cint                         ## Flags on this connection object. 
+    conn_timeout_ms*: cint               ## Connection timeout in milliseconds. 
+    op_timeout_ms*: cint                 ## Read and write timeout in milliseconds. 
+    max_bson_size*: cint                 ## Largest BSON object allowed on this connection. 
+    connected*: TBsonBool                ## Connection status. 
+    write_concern*: TWriteConcern        ## The default write concern.
+    err*: TError                         ## Most recent driver error code. 
+    errcode*: cint                       ## Most recent errno or WSAGetLastError().
+    errstr*: array[0..128 - 1, char]     ## String version of most recent driver error code. 
+    lasterrcode*: cint                   ## getlasterror code given by the server on error. 
+    lasterrstr*: array[0..128 - 1, char] ## getlasterror string generated by server. 
   
   TCursor*{.pure, final.} = object ## cursor
     reply*: ptr TReply        ## reply is owned by cursor 
@@ -654,7 +667,11 @@ proc init*(conn: var TMongo){.stdcall, importc: "mongo_init", dynlib: mongodll.}
 
 proc connect*(conn: var TMongo, host: cstring = defaultHost, 
               port: cint = defaultPort): cint {.stdcall, 
-    importc: "mongo_connect", dynlib: mongodll.}
+    importc: "mongo_connect", dynlib: mongodll, deprecated.}
+  ## Connect to a single MongoDB server.
+proc client*(conn: var TMongo, host: cstring = defaultHost, 
+              port: cint = defaultPort): cint {.stdcall, 
+    importc: "mongo_client", dynlib: mongodll.}
   ## Connect to a single MongoDB server.
 
 proc replsetInit*(conn: var TMongo, name: cstring){.stdcall, 
@@ -714,7 +731,8 @@ proc destroy*(conn: var TMongo){.stdcall, importc: "mongo_destroy",
   ## You must always call this function when finished with the connection
   ## object.
 
-proc insert*(conn: var TMongo, ns: cstring, data: var TBson): cint{.stdcall, 
+proc insert*(conn: var TMongo, ns: cstring, data: var TBson,
+             custom_write_concern: ptr TWriteConcern): cint{.stdcall, 
     importc: "mongo_insert", dynlib: mongodll, discardable.}
   ## Insert a BSON document into a MongoDB server. This function
   ## will fail if the supplied BSON struct is not UTF-8 or if
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index af72d04eb..90c398dce 100644
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
@@ -268,14 +268,22 @@ proc OpenSSL_add_all_algorithms*(){.cdecl, dynlib: DLLUtilName, importc: "OPENSS
 
 proc OPENSSL_config*(configName: cstring){.cdecl, dynlib: DLLSSLName, importc.}
 
-proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, dynlib: DLLSSLName, importc.}
+when not defined(windows):
+  proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, 
+    dynlib: DLLSSLName, importc.}
 
 proc CRYPTO_malloc_init*() =
   when not defined(windows):
     CRYPTO_set_mem_functions(alloc, realloc, dealloc)
 
-when True:
-  nil
+proc SSL_CTX_ctrl*(ctx: PSSL_CTX, cmd: cInt, larg: int, parg: pointer): int{.
+  cdecl, dynlib: DLLSSLName, importc.}
+
+proc SSLCTXSetMode*(ctx: PSSL_CTX, mode: int): int =
+  result = SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, mode, nil)
+
+when true:
+  discard
 else:
   proc SslCtxSetCipherList*(arg0: PSSL_CTX, str: cstring): cInt{.cdecl, 
       dynlib: DLLSSLName, importc.}
@@ -288,7 +296,6 @@ else:
   proc SslCTXCtrl*(ctx: PSSL_CTX, cmd: cInt, larg: int, parg: Pointer): int{.
       cdecl, dynlib: DLLSSLName, importc.}
 
-  proc SSLCTXSetMode*(ctx: PSSL_CTX, mode: int): int
   proc SSLSetMode*(s: PSSL, mode: int): int
   proc SSLCTXGetMode*(ctx: PSSL_CTX): int
   proc SSLGetMode*(s: PSSL): int
@@ -417,15 +424,12 @@ else:
                       enc: cInt){.cdecl, dynlib: DLLUtilName, importc.}
   # implementation
 
-  proc SSLCTXSetMode(ctx: PSSL_CTX, mode: int): int = 
-    Result = SslCTXCtrl(ctx, SSL_CTRL_MODE, mode, nil)
-
   proc SSLSetMode(s: PSSL, mode: int): int = 
-    Result = SSLctrl(s, SSL_CTRL_MODE, mode, nil)
+    result = SSLctrl(s, SSL_CTRL_MODE, mode, nil)
 
   proc SSLCTXGetMode(ctx: PSSL_CTX): int = 
-    Result = SSLCTXctrl(ctx, SSL_CTRL_MODE, 0, nil)
+    result = SSLCTXctrl(ctx, SSL_CTRL_MODE, 0, nil)
 
   proc SSLGetMode(s: PSSL): int = 
-    Result = SSLctrl(s, SSL_CTRL_MODE, 0, nil)
+    result = SSLctrl(s, SSL_CTRL_MODE, 0, nil)
 
diff --git a/readme.md b/readme.md
index 8d42c66db..3eaef0b35 100644
--- a/readme.md
+++ b/readme.md
@@ -61,5 +61,5 @@ allowing you to create commercial applications.
 
 Read copying.txt for more details.
 
-Copyright (c) 2004-2013 Andreas Rumpf.
+Copyright (c) 2004-2014 Andreas Rumpf.
 All rights reserved.
diff --git a/readme.txt b/readme.txt
index 8d42c66db..3eaef0b35 100644
--- a/readme.txt
+++ b/readme.txt
@@ -61,5 +61,5 @@ allowing you to create commercial applications.
 
 Read copying.txt for more details.
 
-Copyright (c) 2004-2013 Andreas Rumpf.
+Copyright (c) 2004-2014 Andreas Rumpf.
 All rights reserved.
diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim
new file mode 100644
index 000000000..f374d5504
--- /dev/null
+++ b/tests/collections/ttables.nim
@@ -0,0 +1,22 @@
+import tables
+
+doAssert indexBy(newSeq[int](), proc(x: int):int = x) == initTable[int, int](), "empty int table"
+
+var tbl1 = initTable[int, int]()
+tbl1.add(1,1)
+tbl1.add(2,2)
+doAssert indexBy(@[1,2], proc(x: int):int = x) == tbl1, "int table"
+
+type
+  TElem = object
+    foo: int
+    bar: string
+    
+let
+  elem1 = TElem(foo: 1, bar: "bar")
+  elem2 = TElem(foo: 2, bar: "baz")
+  
+var tbl2 = initTable[string, TElem]()
+tbl2.add("bar", elem1)
+tbl2.add("baz", elem2)
+doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table"
diff --git a/tests/exprs/tstmtexprs.nim b/tests/exprs/tstmtexprs.nim
index 497a2f6d0..816e58cb1 100644
--- a/tests/exprs/tstmtexprs.nim
+++ b/tests/exprs/tstmtexprs.nim
@@ -1,5 +1,6 @@
 discard """
-  output: '''(bar: bar)
+  output: '''24
+(bar: bar)
 1244
 6
 abcdefghijklmnopqrstuvwxyz
@@ -8,6 +9,10 @@ abcdefghijklmnopqrstuvwxyz
 
 import strutils
 
+const fac4 = (var x = 1; for i in 1..4: x *= i; x)
+
+echo fac4
+
 when true:
   proc test(foo: proc (x, y: int): bool) =
     echo foo(5, 5)
@@ -69,3 +74,15 @@ proc semiProblem() =
   if false: echo "aye"; echo "indeed"
 
 semiProblem()
+
+
+# bug #844
+
+import json 
+proc parseResponse(): PJsonNode =
+  result = % { "key1": % { "key2": % "value" } }
+  for key, val in result["key1"]:
+    var excMsg = key & "("
+    if (var n=result["key2"]; n != nil):
+      excMsg &= n.str
+    raise newException(ESynch, excMsg)
diff --git a/tests/gc/gcleak4.nim b/tests/gc/gcleak4.nim
index bd7bded28..6f2b8a1fe 100644
--- a/tests/gc/gcleak4.nim
+++ b/tests/gc/gcleak4.nim
@@ -6,7 +6,7 @@ when defined(GC_setMaxPause):
   GC_setMaxPause 2_000
 
 type
-  TExpr = object ## abstract base class for an expression
+  TExpr = object {.inheritable.} ## abstract base class for an expression
   PLiteral = ref TLiteral
   TLiteral = object of TExpr
     x: int
diff --git a/tests/gc/gcleak5.nim b/tests/gc/gcleak5.nim
new file mode 100644
index 000000000..9e2948729
--- /dev/null
+++ b/tests/gc/gcleak5.nim
@@ -0,0 +1,25 @@
+discard """
+  output: "success"
+"""
+
+import os, times
+
+proc main =
+  var i = 0
+  for ii in 0..50_000:
+    #while true:
+    var t = getTime()
+    var g = t.getGMTime()
+    #echo isOnStack(addr g)
+    
+    if i mod 100 == 0:
+      let om = getOccupiedMem()
+      #echo "memory: ", om
+      if om > 100_000: quit "leak"
+     
+    inc(i)
+    sleep(1)
+
+  echo "success"
+
+main()
diff --git a/tests/generics/tgenericrefs.nim b/tests/generics/tgenericrefs.nim
index ef931dfa7..a44b96af9 100644
--- a/tests/generics/tgenericrefs.nim
+++ b/tests/generics/tgenericrefs.nim
@@ -6,6 +6,18 @@ var a: PA[string]
 new(a)
 a.field = "some string"
 
+
+proc someOther[T](len: string): seq[T] = discard
+proc someOther[T](len: int): seq[T] = echo "we"
+
+proc foo[T](x: T) =
+  var s = someOther[T](34)
+  #newSeq[T](34)
+
+foo 23
+
+
+
 when false:
   # Compiles unless you use var a: PA[string]
   type 
diff --git a/tests/iter/tanoniter1.nim b/tests/iter/tanoniter1.nim
index 9db5ab8ec..578749caf 100644
--- a/tests/iter/tanoniter1.nim
+++ b/tests/iter/tanoniter1.nim
@@ -22,11 +22,11 @@ proc factory2(a, b: int): iterator (): int =
       yield x
       inc x
 
-let foo = factory 1, 4
+let foo = factory(1, 4)
 
 for f in foo():
   echo f
 
-let foo2 = factory2 1,2
+let foo2 = factory2(1,2)
 
 for f in foo2(): echo f
diff --git a/tests/macros/tdebugstmt.nim b/tests/macros/tdebugstmt.nim
new file mode 100644
index 000000000..865dc436a
--- /dev/null
+++ b/tests/macros/tdebugstmt.nim
@@ -0,0 +1,29 @@
+discard """
+  output: '''a[0]: 42
+a[1]: 45
+x: some string'''
+"""
+
+import macros
+
+macro debug(n: varargs[expr]): stmt =
+  # `n` is a Nimrod AST that contains the whole macro invocation
+  # this macro returns a list of statements:
+  result = newNimNode(nnkStmtList, n)
+  # iterate over any argument that is passed to this macro:
+  for i in 0..n.len-1:
+    # add a call to the statement list that writes the expression;
+    # `toStrLit` converts an AST to its string representation:
+    add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
+    # add a call to the statement list that writes ": "
+    add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
+    # add a call to the statement list that writes the expressions value:
+    add(result, newCall("writeln", newIdentNode("stdout"), n[i]))
+
+var
+  a: array [0..10, int]
+  x = "some string"
+a[0] = 42
+a[1] = 45
+
+debug(a[0], a[1], x)
diff --git a/tests/macros/tdumpast.nim b/tests/macros/tdumpast.nim
index 55a964327..160e4e194 100644
--- a/tests/macros/tdumpast.nim
+++ b/tests/macros/tdumpast.nim
@@ -2,7 +2,7 @@
 
 import macros
 
-template plus(a, b: expr): expr =
+template plus(a, b: expr): expr {.dirty} =
   a + b
 
 macro call(e: expr): expr =
diff --git a/tests/macros/tdumpast2.nim b/tests/macros/tdumpast2.nim
index c6eab39a9..2a7024a01 100644
--- a/tests/macros/tdumpast2.nim
+++ b/tests/macros/tdumpast2.nim
@@ -7,7 +7,7 @@ proc dumpit(n: PNimrodNode): string {.compileTime.} =
   result = $n.kind
   add(result, "(")
   case n.kind
-  of nnkEmpty: nil # same as nil node in this representation 
+  of nnkEmpty: discard # same as nil node in this representation 
   of nnkNilLit:                  add(result, "nil")
   of nnkCharLit..nnkInt64Lit:    add(result, $n.intVal)
   of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
diff --git a/tests/macros/tmacrogenerics.nim b/tests/macros/tmacrogenerics.nim
index 5ae59e0da..b886f4fa5 100644
--- a/tests/macros/tmacrogenerics.nim
+++ b/tests/macros/tmacrogenerics.nim
@@ -1,10 +1,8 @@
 discard """
   file: "tmacrogenerics.nim"
   msg: '''
-instantiation 1 with int and float
-instantiation 2 with float and string
-instantiation 3 with string and string
-counter: 3
+instantiation 1 with typedesc and typedesc
+counter: 1
 '''
   output: "int\nfloat\nint\nstring"
 """
diff --git a/tests/macros/tmacrotypes.nim b/tests/macros/tmacrotypes.nim
index 7697dba27..f19aa2ddb 100644
--- a/tests/macros/tmacrotypes.nim
+++ b/tests/macros/tmacrotypes.nim
@@ -1,3 +1,7 @@
+discard """
+  disabled: true
+"""
+
 import macros, typetraits
 
 macro checkType(ex, expected: expr): stmt {.immediate.} =
diff --git a/tests/macros/tmemit.nim b/tests/macros/tmemit.nim
index e4bb2daed..6fb2f3b65 100644
--- a/tests/macros/tmemit.nim
+++ b/tests/macros/tmemit.nim
@@ -1,5 +1,5 @@
 discard """
-  out: '''HELLO WORLD'''
+  output: '''HELLO WORLD'''
 """
 
 import macros, strutils
diff --git a/tests/macros/tstringinterp.nim b/tests/macros/tstringinterp.nim
index f030213e0..a500ed56e 100644
--- a/tests/macros/tstringinterp.nim
+++ b/tests/macros/tstringinterp.nim
@@ -9,7 +9,7 @@ proc concat(strings: varargs[string]): string =
   result = newString(0)
   for s in items(strings): result.add(s)
 
-template ProcessInterpolations(e: expr) =
+template processInterpolations(e: expr) =
   var s = e[1].strVal
   for f in interpolatedFragments(s):
     case f.kind
@@ -35,7 +35,7 @@ macro formatStyleInterpolation(e: expr): expr =
   proc addDollar() =
     formatString.add("$$")
     
-  ProcessInterpolations(e)
+  processInterpolations(e)
 
   result = parseExpr("\"x\" % [y]")
   result[1].strVal = formatString
@@ -50,7 +50,7 @@ macro concatStyleInterpolation(e: expr): expr =
   proc addExpr(e: PNimrodNode) = args.add(e)
   proc addDollar()             = args.add(newStrLitNode"$")
 
-  ProcessInterpolations(e)
+  processInterpolations(e)
 
   result = newCall("concat", args)
 
diff --git a/tests/parser/tcommand_as_expr.nim b/tests/parser/tcommand_as_expr.nim
index f6868a2fc..22c49ab3f 100644
--- a/tests/parser/tcommand_as_expr.nim
+++ b/tests/parser/tcommand_as_expr.nim
@@ -1,12 +1,23 @@
 discard """
-  output: "12"
+  output: '''140
+5-120-120
+359'''
 """
+#import math
+
+proc optarg(x:int, y:int = 0):int = x + 3 * y
+proc singlearg(x:int):int = 20*x
+echo optarg 1, singlearg 2
+
 
 proc foo(x: int): int = x-1
 proc foo(x, y: int): int = x-y
 
-let x = foo 7.foo,  # comment here
-            foo(1, foo 8)
-#  12 =       6     -     -6
-echo x
+let x = optarg foo 7.foo
+let y = singlearg foo(1, foo 8)
+let z = singlearg 1.foo foo 8
+    
+echo x, y, z
 
+let a = [2,4,8].map do (d:int) -> int: d + 1
+echo a[0], a[1], a[2]
\ No newline at end of file
diff --git a/tests/sets/testequivalence.nim b/tests/sets/testequivalence.nim
new file mode 100644
index 000000000..7c5d9e3e9
--- /dev/null
+++ b/tests/sets/testequivalence.nim
@@ -0,0 +1,15 @@
+discard """
+  output: ''''''
+"""
+import unittest
+import sets
+
+doAssert(toSet(@[1,2,3]) <= toSet(@[1,2,3,4]), "equivalent or subset")
+doAssert(toSet(@[1,2,3]) <= toSet(@[1,2,3]), "equivalent or subset")
+doAssert((not(toSet(@[1,2,3]) <= toSet(@[1,2]))), "equivalent or subset")
+doAssert(toSet(@[1,2,3]) <= toSet(@[1,2,3,4]), "strict subset")
+doAssert((not(toSet(@[1,2,3]) < toSet(@[1,2,3]))), "strict subset")
+doAssert((not(toSet(@[1,2,3]) < toSet(@[1,2]))), "strict subset")
+doAssert((not(toSet(@[1,2,3]) == toSet(@[1,2,3,4]))), "==")
+doAssert(toSet(@[1,2,3]) == toSet(@[1,2,3]), "==")
+doAssert((not(toSet(@[1,2,3]) == toSet(@[1,2]))), "==")
diff --git a/tests/specials.nim b/tests/specials.nim
deleted file mode 100644
index 9ced66bbb..000000000
--- a/tests/specials.nim
+++ /dev/null
@@ -1,238 +0,0 @@
-#
-#
-#            Nimrod Tester
-#        (c) Copyright 2013 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## Include for the tester that contains test suites that test special features
-## of the compiler.
-
-# included from tester.nim
-# ---------------- ROD file tests ---------------------------------------------
-
-const
-  rodfilesDir = "tests/rodfiles"
-  nimcacheDir = rodfilesDir / "nimcache"
-
-proc delNimCache() =
-  try:
-    removeDir(nimcacheDir)
-  except EOS:
-    echo "[Warning] could not delete: ", nimcacheDir
-    
-proc runRodFiles(r: var TResults, options: string) =
-  template test(filename: expr): stmt =
-    runSingleTest(r, rodfilesDir / filename, options)
-  
-  delNimCache()
-  
-  # test basic recompilation scheme:
-  test "hallo"
-  test "hallo"
-  # test incremental type information:
-  test "hallo2"
-  delNimCache()
-  
-  # test type converters:
-  test "aconv"
-  test "bconv"
-  delNimCache()
-  
-  # test G, A, B example from the documentation; test init sections:
-  test "deada"
-  test "deada2"
-  delNimCache()
-  
-  # test method generation:
-  test "bmethods"
-  test "bmethods2"
-  delNimCache()
-  
-  # test generics:
-  test "tgeneric1"
-  test "tgeneric2"
-  delNimCache()
-
-proc compileRodFiles(r: var TResults, options: string) =
-  template test(filename: expr): stmt =
-    compileSingleTest(r, rodfilesDir / filename, options)
-    
-  delNimCache()
-  # test DLL interfacing:
-  test "gtkex1"
-  test "gtkex2"
-  delNimCache()
-
-# --------------------- DLL generation tests ----------------------------------
-
-proc safeCopyFile(src, dest: string) =
-  try:
-    copyFile(src, dest)
-  except EOS:
-    echo "[Warning] could not copy: ", src, " to ", dest
-
-proc runBasicDLLTest(c, r: var TResults, options: string) =
-  compileSingleTest c, "lib/nimrtl.nim", options & " --app:lib -d:createNimRtl"
-  compileSingleTest c, "tests/dll/server.nim", 
-    options & " --app:lib -d:useNimRtl"
-  
-  when defined(Windows): 
-    # windows looks in the dir of the exe (yay!):
-    var nimrtlDll = DynlibFormat % "nimrtl"
-    safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll)
-  else:
-    # posix relies on crappy LD_LIBRARY_PATH (ugh!):
-    var libpath = getenv"LD_LIBRARY_PATH".string
-    if peg"\i '/nimrod' (!'/')* '/lib'" notin libpath:
-      echo "[Warning] insufficient LD_LIBRARY_PATH"
-    var serverDll = DynlibFormat % "server"
-    safeCopyFile("tests/dll" / serverDll, "lib" / serverDll)
-  
-  runSingleTest r, "tests/dll/client.nim", options & " -d:useNimRtl"
-
-proc runDLLTests(r: var TResults, options: string) =
-  # dummy compile result:
-  var c = initResults()
-  
-  runBasicDLLTest c, r, options
-  runBasicDLLTest c, r, options & " -d:release"
-  runBasicDLLTest c, r, options & " --gc:boehm"
-  runBasicDLLTest c, r, options & " -d:release --gc:boehm"
-
-proc compileDLLTests(r: var TResults, options: string) =
-  # dummy run result:
-  var c = initResults()
-  
-  runBasicDLLTest r, c, options
-  runBasicDLLTest r, c, options & " -d:release"
-  runBasicDLLTest r, c, options & " --gc:boehm"
-  runBasicDLLTest r, c, options & " -d:release --gc:boehm"
-
-# ------------------------------ GC tests -------------------------------------
-
-proc runGcTests(r: var TResults, options: string) =
-  template test(filename: expr): stmt =
-    runSingleTest(r, "tests/gc" / filename, options)
-    runSingleTest(r, "tests/gc" / filename, options & " -d:release")
-    runSingleTest(r, "tests/gc" / filename, options &
-                  " -d:release -d:useRealtimeGC")
-    runSingleTest(r, "tests/gc" / filename, options &
-                  " --gc:markAndSweep")
-    runSingleTest(r, "tests/gc" / filename, options &
-                  " -d:release --gc:markAndSweep")
-  
-  test "gcbench"
-  test "gcleak"
-  test "gcleak2"
-  test "gctest"
-  test "gcleak3"
-  test "weakrefs"
-  test "cycleleak"
-  test "closureleak"
-
-# ------------------------- threading tests -----------------------------------
-
-proc runThreadTests(r: var TResults, options: string) =
-  template test(filename: expr): stmt =
-    runSingleTest(r, "tests/threads" / filename, options)
-    runSingleTest(r, "tests/threads" / filename, options & " -d:release")
-    runSingleTest(r, "tests/threads" / filename, options & " --tlsEmulation:on")
-  
-  test "tactors"
-  test "tactors2"
-  test "threadex"
-  # deactivated because output capturing still causes problems sometimes:
-  #test "trecursive_actor"
-  #test "threadring"
-  #test "tthreadanalysis"
-  #test "tthreadsort"
-
-proc rejectThreadTests(r: var TResults, options: string) =
-  rejectSingleTest(r, "tests/threads/tthreadanalysis2", options)
-  rejectSingleTest(r, "tests/threads/tthreadanalysis3", options)
-  rejectSingleTest(r, "tests/threads/tthreadheapviolation1", options)
-
-# ------------------------- IO tests ------------------------------------------
-
-proc runIOTests(r: var TResults, options: string) =
-  # We need readall_echo to be compiled for this test to run.
-  # dummy compile result:
-  var c = initResults()
-  compileSingleTest(c, "tests/system/helpers/readall_echo", options)
-  runSingleTest(r, "tests/system/io", options)
-  
-# ------------------------- debugger tests ------------------------------------
-
-proc compileDebuggerTests(r: var TResults, options: string) =
-  compileSingleTest(r, "tools/nimgrep", options & 
-                    " --debugger:on")
-
-# ------------------------- JS tests ------------------------------------------
-
-proc runJsTests(r: var TResults, options: string) =
-  template test(filename: expr): stmt =
-    runSingleTest(r, filename, options & " -d:nodejs", targetJS)
-    runSingleTest(r, filename, options & " -d:nodejs -d:release", targetJS)
-    
-  for t in os.walkFiles("tests/js/t*.nim"):
-    test(t)
-  for testfile in ["texceptions", "texcpt1", "texcsub", "tfinally",
-                   "tfinally2", "tfinally3", "tactiontable", "tmultim1",
-                   "tmultim3", "tmultim4"]:
-    test "tests/run/" & testfile & ".nim"
-
-# ------------------------- register special tests here -----------------------
-proc runSpecialTests(r: var TResults, options: string) =
-  runRodFiles(r, options)
-  #runDLLTests(r, options)
-  runGCTests(r, options)
-  runThreadTests(r, options & " --threads:on")
-  runIOTests(r, options)
-
-  for t in os.walkFiles("tests/patterns/t*.nim"):
-    runSingleTest(r, t, options)
-  for t in ["lib/packages/docutils/highlite"]:
-    runSingleTest(r, t, options)
-
-proc rejectSpecialTests(r: var TResults, options: string) =
-  rejectThreadTests(r, options)
-
-proc findMainFile(dir: string): string =
-  # finds the file belonging to ".nimrod.cfg"; if there is no such file
-  # it returns the some ".nim" file if there is only one: 
-  const cfgExt = ".nimrod.cfg"
-  result = ""
-  var nimFiles = 0
-  for kind, file in os.walkDir(dir):
-    if kind == pcFile:
-      if file.endsWith(cfgExt): return file[.. -(cfgExt.len+1)] & ".nim"
-      elif file.endsWith(".nim"):
-        if result.len == 0: result = file
-        inc nimFiles
-  if nimFiles != 1: result.setlen(0)
-
-proc compileManyLoc(r: var TResults, options: string) =
-  for kind, dir in os.walkDir("tests/manyloc"):
-    if kind == pcDir:
-      let mainfile = findMainFile(dir)
-      if mainfile != ".nim":
-        compileSingleTest(r, mainfile, options)
-
-proc compileSpecialTests(r: var TResults, options: string) =
-  compileRodFiles(r, options)
-
-  compileSingleTest(r, "compiler/c2nim/c2nim.nim", options)
-  compileSingleTest(r, "compiler/pas2nim/pas2nim.nim", options)
-
-  compileDLLTests(r, options)
-  compileDebuggerTests(r, options)
-  
-  compileManyLoc(r, options)
-
-  #var given = callCompiler("nimrod i", "nimrod i", options)
-  #r.addResult("nimrod i", given.msg, if given.err: reFailure else: reSuccess)
-  #if not given.err: inc(r.passed)
-
diff --git a/tests/stdlib/talgorithm.nim b/tests/stdlib/talgorithm.nim
new file mode 100644
index 000000000..7ab652c82
--- /dev/null
+++ b/tests/stdlib/talgorithm.nim
@@ -0,0 +1,8 @@
+import algorithm
+
+doAssert product[int](newSeq[seq[int]]()) == newSeq[seq[int]](), "empty input"
+doAssert product[int](@[newSeq[int](), @[], @[]]) == newSeq[seq[int]](), "bit more empty input"
+doAssert product(@[@[1,2]]) == @[@[1,2]], "a simple case of one element"
+doAssert product(@[@[1,2], @[3,4]]) == @[@[2,4],@[1,4],@[2,3],@[1,3]], "two elements"
+doAssert product(@[@[1,2], @[3,4], @[5,6]]) == @[@[2,4,6],@[1,4,6],@[2,3,6],@[1,3,6], @[2,4,5],@[1,4,5],@[2,3,5],@[1,3,5]], "three elements"
+doAssert product(@[@[1,2], @[]]) == newSeq[seq[int]](), "two elements, but one empty"
diff --git a/tests/template/tprefer_immediate.nim b/tests/template/tprefer_immediate.nim
new file mode 100644
index 000000000..578f447b0
--- /dev/null
+++ b/tests/template/tprefer_immediate.nim
@@ -0,0 +1,17 @@
+discard """
+  output: '''immediate'''
+"""
+
+# Test that immediate templates are preferred over non-immediate templates
+
+template foo(a, b: expr) = echo "foo expr"
+
+template foo(a, b: int) = echo "foo int"
+template foo(a, b: float) = echo "foo float"
+template foo(a, b: string) = echo "foo string"
+template foo(a, b: expr) {.immediate.} = echo "immediate"
+template foo(a, b: bool) = echo "foo bool"
+template foo(a, b: char) = echo "foo char"
+
+foo(undeclaredIdentifier, undeclaredIdentifier2)
+
diff --git a/tests/testament/backend.nim b/tests/testament/backend.nim
index bc1f92eba..5199bb9d6 100644
--- a/tests/testament/backend.nim
+++ b/tests/testament/backend.nim
@@ -49,10 +49,10 @@ proc createDb() =
   #  """, [])
 
 type
-  MachineId = distinct int64
+  MachineId* = distinct int64
   CommitId = distinct int64
 
-proc `$`(id: MachineId): string {.borrow.}
+proc `$`*(id: MachineId): string {.borrow.}
 proc `$`(id: CommitId): string {.borrow.}
 
 var
@@ -61,7 +61,7 @@ var
 
 proc `()`(cmd: string{lit}): string = cmd.execProcess.string.strip
 
-proc getMachine: MachineId =
+proc getMachine*(db: TDbConn): MachineId =
   var name = "hostname"()
   if name.len == 0:
     name = when defined(posix): getenv"HOSTNAME".string
@@ -76,7 +76,7 @@ proc getMachine: MachineId =
     result = db.insertId(sql"insert into Machine(name, os, cpu) values (?,?,?)",
                          name, system.hostOS, system.hostCPU).MachineId
 
-proc getCommit: CommitId =
+proc getCommit(db: TDbConn): CommitId =
   const commLen = "commit ".len
   let hash = "git log -n 1"()[commLen..commLen+10]
   let branch = "git symbolic-ref --short HEAD"()
@@ -115,7 +115,7 @@ proc open*() =
   db = open(connection="testament.db", user="testament", password="",
             database="testament")
   createDb()
-  thisMachine = getMachine()
-  thisCommit = getCommit()
+  thisMachine = getMachine(db)
+  thisCommit = getCommit(db)
 
 proc close*() = close(db)
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index 5dd841447..442dd1212 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -123,9 +123,14 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
   test "gcleak2"
   test "gctest"
   test "gcleak3"
+  test "gcleak4"
+  test "gcleak5"
   test "weakrefs"
   test "cycleleak"
   test "closureleak"
+  test "refarrayleak"
+  test "stackrefleak"
+  
 
 # ------------------------- threading tests -----------------------------------
 
diff --git a/tests/testament/htmlgen.nim b/tests/testament/htmlgen.nim
index bc2d8bd37..eb674a171 100644
--- a/tests/testament/htmlgen.nim
+++ b/tests/testament/htmlgen.nim
@@ -159,3 +159,22 @@ proc generateHtml*(filename: string, commit: int) =
   outfile.write(HtmlEnd)
   close(db)
   close(outfile)
+
+proc generateJson*(filename: string, commit: int) =
+  const selRow = """select count(*),
+                           sum(result = 'reSuccess'), 
+                           sum(result = 'reIgnored')
+                    from TestResult
+                    where [commit] = ? and machine = ?
+                    order by category"""
+  var db = open(connection="testament.db", user="testament", password="",
+                database="testament")
+  let lastCommit = db.getCommit(commit)
+
+  var outfile = open(filename, fmWrite)
+
+  let data = db.getRow(sql(selRow), lastCommit, $backend.getMachine(db))
+
+  outfile.writeln("""{"total": $#, "passed": $#, "skipped": $#}""" % data)
+  close(db)
+  close(outfile)
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index 54a6de2d0..fac97cf2a 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -208,20 +208,6 @@ proc makeTest(test, options: string, cat: Category, action = actionCompile,
 
 include categories
 
-proc toJson(res: TResults): PJsonNode =
-  result = newJObject()
-  result["total"] = newJInt(res.total)
-  result["passed"] = newJInt(res.passed)
-  result["skipped"] = newJInt(res.skipped)
-
-proc outputJson(reject, compile, run: TResults) =
-  var doc = newJObject()
-  doc["reject"] = toJson(reject)
-  doc["compile"] = toJson(compile)
-  doc["run"] = toJson(run)
-  var s = pretty(doc)
-  writeFile(jsonFile, s)
-
 # proc runCaasTests(r: var TResults) =
 #   for test, output, status, mode in caasTestsRunner():
 #     r.addResult(test, "", output & "-> " & $mode,
@@ -259,6 +245,7 @@ proc main() =
     var commit = 0
     discard parseInt(p.cmdLineRest.string, commit)
     generateHtml(resultsFile, commit)
+    generateJson(jsonFile, commit)
   else:
     quit usage
 
diff --git a/tests/tester.nim b/tests/tester.nim
deleted file mode 100644
index 0e125b1bb..000000000
--- a/tests/tester.nim
+++ /dev/null
@@ -1,457 +0,0 @@
-#
-#
-#            Nimrod Tester
-#        (c) Copyright 2013 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This program verifies Nimrod against the testcases.
-
-import
-  parseutils, strutils, pegs, os, osproc, streams, parsecfg, browsers, json,
-  marshal, cgi, parseopt #, caas
-
-const
-  cmdTemplate = r"nimrod cc --hints:on $# $#"
-  resultsFile = "testresults.html"
-  jsonFile = "testresults.json"
-  Usage = "usage: tester [--print] " &
-                    "reject|compile|run|" &
-                    "merge|special|rodfiles| [nimrod options]\n" &
-          "   or: tester test|comp|rej singleTest"
-
-type
-  TTestAction = enum
-    actionCompile, actionRun, actionReject
-  TResultEnum = enum
-    reNimrodcCrash,     # nimrod compiler seems to have crashed
-    reMsgsDiffer,       # error messages differ
-    reFilesDiffer,      # expected and given filenames differ
-    reLinesDiffer,      # expected and given line numbers differ
-    reOutputsDiffer,
-    reExitcodesDiffer,
-    reInvalidPeg,
-    reCodegenFailure,
-    reCodeNotFound,
-    reExeNotFound,
-    reIgnored,          # test is ignored
-    reSuccess           # test was successful
-
-  TTarget = enum
-    targetC, targetCpp, targetObjC, targetJS
-
-  TSpec = object
-    action: TTestAction
-    file, cmd: string
-    outp: string
-    line, exitCode: int
-    msg: string
-    ccodeCheck: string
-    err: TResultEnum
-    substr: bool
-  TResults = object
-    total, passed, skipped: int
-    data: string
-
-# ----------------------- Spec parser ----------------------------------------
-
-when not defined(parseCfgBool):
-  # candidate for the stdlib:
-  proc parseCfgBool(s: string): bool =
-    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 extractSpec(filename: string): string =
-  const tripleQuote = "\"\"\""
-  var x = readFile(filename).string
-  var a = x.find(tripleQuote)
-  var b = x.find(tripleQuote, a+3)
-  # look for """ only in the first section
-  if a >= 0 and b > a and a < 40:
-    result = x.substr(a+3, b-1).replace("'''", tripleQuote)
-  else:
-    #echo "warning: file does not contain spec: " & filename
-    result = ""
-
-when not defined(nimhygiene):
-  {.pragma: inject.}
-
-template parseSpecAux(fillResult: stmt) {.immediate.} =
-  var ss = newStringStream(extractSpec(filename))
-  var p {.inject.}: TCfgParser
-  open(p, ss, filename, 1)
-  while true:
-    var e {.inject.} = next(p)
-    case e.kind
-    of cfgEof: break
-    of cfgSectionStart, cfgOption, cfgError:
-      echo ignoreMsg(p, e)
-    of cfgKeyValuePair:
-      fillResult
-  close(p)
-
-proc parseSpec(filename: string): TSpec =
-  result.file = filename
-  result.msg = ""
-  result.outp = ""
-  result.ccodeCheck = ""
-  result.cmd = cmdTemplate
-  parseSpecAux:
-    case normalize(e.key)
-    of "action":
-      case e.value.normalize
-      of "compile": result.action = actionCompile
-      of "run": result.action = actionRun
-      of "reject": result.action = actionReject
-      else: echo ignoreMsg(p, e)
-    of "file": result.file = e.value
-    of "line": discard parseInt(e.value, result.line)
-    of "output": result.outp = e.value
-    of "outputsub":
-      result.outp = e.value
-      result.substr = true
-    of "exitcode": 
-      discard parseInt(e.value, result.exitCode)
-    of "errormsg", "msg": result.msg = e.value
-    of "disabled":
-      if parseCfgBool(e.value): result.err = reIgnored
-    of "cmd": result.cmd = e.value
-    of "ccodecheck": result.ccodeCheck = e.value
-    else: echo ignoreMsg(p, e)
-
-# ----------------------------------------------------------------------------
-
-let
-  pegLineError = 
-    peg"{[^(]*} '(' {\d+} ', ' \d+ ') ' ('Error'/'Warning') ':' \s* {.*}"
-  pegOtherError = peg"'Error:' \s* {.*}"
-  pegSuccess = peg"'Hint: operation successful'.*"
-  pegOfInterest = pegLineError / pegOtherError
-
-proc callCompiler(cmdTemplate, filename, options: string): TSpec =
-  let c = parseCmdLine(cmdTemplate % [options, filename])
-  var p = startProcess(command=c[0], args=c[1.. -1],
-                       options={poStdErrToStdOut, poUseShell})
-  let outp = p.outputStream
-  var suc = ""
-  var err = ""
-  var x = newStringOfCap(120)
-  while outp.readLine(x.TaintedString) or running(p):
-    if x =~ pegOfInterest:
-      # `err` should contain the last error/warning message
-      err = x
-    elif x =~ pegSuccess:
-      suc = x
-  close(p)
-  result.msg = ""
-  result.file = ""
-  result.outp = ""
-  result.line = -1
-  if err =~ pegLineError:
-    result.file = extractFilename(matches[0])
-    result.line = parseInt(matches[1])
-    result.msg = matches[2]
-  elif err =~ pegOtherError:
-    result.msg = matches[0]
-  elif suc =~ pegSuccess:
-    result.err = reSuccess
-
-proc initResults: TResults =
-  result.total = 0
-  result.passed = 0
-  result.skipped = 0
-  result.data = ""
-
-proc readResults(filename: string): TResults =
-  result = marshal.to[TResults](readFile(filename).string)
-
-proc writeResults(filename: string, r: TResults) =
-  writeFile(filename, $$r)
-
-proc `$`(x: TResults): string =
-  result = ("Tests passed: $1 / $3 <br />\n" &
-            "Tests skipped: $2 / $3 <br />\n") %
-            [$x.passed, $x.skipped, $x.total]
-
-proc colorResult(r: TResultEnum): string =
-  case r
-  of reIgnored: result = "<span style=\"color:fuchsia\">ignored</span>"
-  of reSuccess: result = "<span style=\"color:green\">yes</span>"
-  else: result = "<span style=\"color:red\">no</span>"
-
-const
-  TableHeader4 = "<table border=\"1\"><tr><td>Test</td><td>Expected</td>" &
-                 "<td>Given</td><td>Success</td></tr>\n"
-  TableHeader3 = "<table border=\"1\"><tr><td>Test</td>" &
-                 "<td>Given</td><td>Success</td></tr>\n"
-  TableFooter = "</table>\n"
-  HtmlBegin = """<html>
-    <head> 
-      <title>Test results</title>
-      <style type="text/css">
-      <!--""" & slurp("css/boilerplate.css") & "\n" &
-                slurp("css/style.css") &
-      """-->
-    </style>
-
-    </head>
-    <body>"""
-  
-  HtmlEnd = "</body></html>"
-
-proc td(s: string): string =
-  result = s.substr(0, 200).XMLEncode
-
-proc addResult(r: var TResults, test, expected, given: string,
-               success: TResultEnum) =
-  r.data.addf("<tr><td>$#</td><td>$#</td><td>$#</td><td>$#</td></tr>\n", [
-    XMLEncode(test), td(expected), td(given), success.colorResult])
-
-proc addResult(r: var TResults, test, given: string,
-               success: TResultEnum) =
-  r.data.addf("<tr><td>$#</td><td>$#</td><td>$#</td></tr>\n", [
-    XMLEncode(test), td(given), success.colorResult])
-
-proc listResults(reject, compile, run: TResults) =
-  var s = HtmlBegin
-  s.add("<h1>Tests to Reject</h1>\n")
-  s.add($reject)
-  s.add(TableHeader4 & reject.data & TableFooter)
-  s.add("<br /><br /><br /><h1>Tests to Compile</h1>\n")
-  s.add($compile)
-  s.add(TableHeader3 & compile.data & TableFooter)
-  s.add("<br /><br /><br /><h1>Tests to Run</h1>\n")
-  s.add($run)
-  s.add(TableHeader4 & run.data & TableFooter)
-  s.add(HtmlEnd)
-  writeFile(resultsFile, s)
-
-proc cmpMsgs(r: var TResults, expected, given: TSpec, test: string) =
-  if strip(expected.msg) notin strip(given.msg):
-    r.addResult(test, expected.msg, given.msg, reMsgsDiffer)
-  elif extractFilename(expected.file) != extractFilename(given.file) and
-      "internal error:" notin expected.msg:
-    r.addResult(test, expected.file, given.file, reFilesDiffer)
-  elif expected.line != given.line and expected.line != 0:
-    r.addResult(test, $expected.line, $given.line, reLinesDiffer)
-  else:
-    r.addResult(test, expected.msg, given.msg, reSuccess)
-    inc(r.passed)
-
-proc rejectSingleTest(r: var TResults, test, options: string) =
-  let test = test.addFileExt(".nim")
-  var t = extractFilename(test)
-  inc(r.total)
-  echo t
-  var expected = parseSpec(test)
-  if expected.err == reIgnored:
-    r.addResult(t, "", "", reIgnored)
-    inc(r.skipped)
-  else:
-    var given = callCompiler(expected.cmd, test, options)
-    cmpMsgs(r, expected, given, t)
-
-proc reject(r: var TResults, dir, options: string) =
-  ## handle all the tests that the compiler should reject
-  for test in os.walkFiles(dir / "t*.nim"): rejectSingleTest(r, test, options)
-
-proc codegenCheck(test, check, ext: string, given: var TSpec) =
-  if check.len > 0:
-    try:
-      let (path, name, ext2) = test.splitFile
-      echo path / "nimcache" / name.changeFileExt(ext)
-      let contents = readFile(path / "nimcache" / name.changeFileExt(ext)).string
-      if contents.find(check.peg) < 0:
-        given.err = reCodegenFailure
-    except EInvalidValue:
-      given.err = reInvalidPeg
-    except EIO:
-      given.err = reCodeNotFound
-  
-proc codegenChecks(test: string, expected: TSpec, given: var TSpec) =
-  codegenCheck(test, expected.ccodeCheck, ".c", given)
-  
-proc compile(r: var TResults, pattern, options: string) =
-  for test in os.walkFiles(pattern):
-    let t = extractFilename(test)
-    echo t
-    inc(r.total)
-    let expected = parseSpec(test)
-    if expected.err == reIgnored:
-      r.addResult(t, "", reIgnored)
-      inc(r.skipped)
-    else:
-      var given = callCompiler(expected.cmd, test, options)
-      if given.err == reSuccess:
-        codegenChecks(test, expected, given)
-      r.addResult(t, given.msg, given.err)
-      if given.err == reSuccess: inc(r.passed)
-
-proc compileSingleTest(r: var TResults, test, options: string) =
-  # does not extract the spec because the file is not supposed to have any
-  let test = test.addFileExt(".nim")
-  let t = extractFilename(test)
-  inc(r.total)
-  echo t
-  let given = callCompiler(cmdTemplate, test, options)
-  r.addResult(t, given.msg, given.err)
-  if given.err == reSuccess: inc(r.passed)
-
-proc runSingleTest(r: var TResults, test, options: string, target: TTarget) =
-  var test = test.addFileExt(".nim")
-  var t = extractFilename(test)
-  echo t
-  inc(r.total)
-  var expected = parseSpec(test)
-  if expected.err == reIgnored:
-    r.addResult(t, "", "", reIgnored)
-    inc(r.skipped)
-  else:
-    var given = callCompiler(expected.cmd, test, options)
-    if given.err != reSuccess:
-      r.addResult(t, "", given.msg, given.err)
-    else:
-      var exeFile: string
-      if target == targetC:
-        exeFile = changeFileExt(test, ExeExt)
-      else:
-        let (dir, file, ext) = splitFile(test)
-        exeFile = dir / "nimcache" / file & ".js"
-      
-      if existsFile(exeFile):
-        var (buf, exitCode) = execCmdEx(
-          (if target==targetJS: "node " else: "") & exeFile)
-        if exitCode != expected.ExitCode:
-          r.addResult(t, "exitcode: " & $expected.ExitCode,
-                         "exitcode: " & $exitCode, reExitCodesDiffer)
-        else:
-          if strip(buf.string) != strip(expected.outp):
-            if not (expected.substr and expected.outp in buf.string):
-              given.err = reOutputsDiffer
-          if given.err == reSuccess:
-            codeGenChecks(test, expected, given)
-          if given.err == reSuccess: inc(r.passed)
-          r.addResult(t, expected.outp, buf.string, given.err)
-      else:
-        r.addResult(t, expected.outp, "executable not found", reExeNotFound)
-
-proc runSingleTest(r: var TResults, test, options: string) =
-  runSingleTest(r, test, options, targetC)
-
-proc run(r: var TResults, dir, options: string) =
-  for test in os.walkFiles(dir / "t*.nim"): runSingleTest(r, test, options)
-
-include specials
-
-proc compileExample(r: var TResults, pattern, options: string) =
-  for test in os.walkFiles(pattern): compileSingleTest(r, test, options)
-
-proc toJson(res: TResults): PJsonNode =
-  result = newJObject()
-  result["total"] = newJInt(res.total)
-  result["passed"] = newJInt(res.passed)
-  result["skipped"] = newJInt(res.skipped)
-
-proc outputJSON(reject, compile, run: TResults) =
-  var doc = newJObject()
-  doc["reject"] = toJson(reject)
-  doc["compile"] = toJson(compile)
-  doc["run"] = toJson(run)
-  var s = pretty(doc)
-  writeFile(jsonFile, s)
-
-# proc runCaasTests(r: var TResults) =
-#   for test, output, status, mode in caasTestsRunner():
-#     r.addResult(test, "", output & "-> " & $mode,
-#                 if status: reSuccess else: reOutputsDiffer)
-
-proc main() =
-  os.putenv "NIMTEST_NO_COLOR", "1"
-  os.putenv "NIMTEST_OUTPUT_LVL", "PRINT_FAILURES"
-
-  const
-    compileJson = "compile.json"
-    runJson = "run.json"
-    rejectJson = "reject.json"
-  
-  var optPrintResults = false
-  var p = initOptParser()
-  p.next()
-  if p.kind == cmdLongoption:
-    case p.key.string
-    of "print": optPrintResults = true
-    else: quit usage
-    p.next()
-  if p.kind != cmdArgument: quit usage
-  var action = p.key.string.normalize
-  p.next()
-  var r = initResults()
-  case action
-  of "reject":
-    reject(r, "tests/reject", p.cmdLineRest.string)
-    rejectSpecialTests(r, p.cmdLineRest.string)
-    writeResults(rejectJson, r)
-  of "compile":
-    compile(r, "tests/compile/t*.nim", p.cmdLineRest.string)
-    compile(r, "tests/ccg/t*.nim", p.cmdLineRest.string)
-    compile(r, "tests/js.nim", p.cmdLineRest.string)
-    compileExample(r, "lib/pure/*.nim", p.cmdLineRest.string)
-    compileExample(r, "examples/*.nim", p.cmdLineRest.string)
-    compileExample(r, "examples/gtk/*.nim", p.cmdLineRest.string)
-    compileExample(r, "examples/talk/*.nim", p.cmdLineRest.string)
-    compileSpecialTests(r, p.cmdLineRest.string)
-    writeResults(compileJson, r)
-  of "run":
-    run(r, "tests/run", p.cmdLineRest.string)
-    runSpecialTests(r, p.cmdLineRest.string)
-    writeResults(runJson, r)
-  of "special":
-    runSpecialTests(r, p.cmdLineRest.string)
-    # runCaasTests(r)
-    writeResults(runJson, r)
-  of "rodfiles":
-    runRodFiles(r, p.cmdLineRest.string)
-    writeResults(runJson, r)
-  of "js":
-    if existsFile(runJSon):
-      r = readResults(runJson)
-    runJsTests(r, p.cmdLineRest.string)
-    writeResults(runJson, r)
-  of "merge":
-    var rejectRes = readResults(rejectJson)
-    var compileRes = readResults(compileJson)
-    var runRes = readResults(runJson)
-    listResults(rejectRes, compileRes, runRes)
-    outputJSON(rejectRes, compileRes, runRes)
-  of "dll":
-    runDLLTests r, p.cmdLineRest.string
-  of "gc":
-    runGCTests(r, p.cmdLineRest.string)
-  of "test":
-    if p.kind != cmdArgument: quit usage
-    var testFile = p.key.string
-    p.next()
-    runSingleTest(r, testFile, p.cmdLineRest.string)
-  of "comp", "rej":
-    if p.kind != cmdArgument: quit usage
-    var testFile = p.key.string
-    p.next()
-    if peg"'/reject/'" in testFile or action == "rej":
-      rejectSingleTest(r, testFile, p.cmdLineRest.string)
-    elif peg"'/compile/'" in testFile or action == "comp":
-      compileSingleTest(r, testFile, p.cmdLineRest.string)
-    else:
-      runSingleTest(r, testFile, p.cmdLineRest.string)
-  else:
-    quit usage
-
-  if optPrintResults: echo r, r.data
-
-if paramCount() == 0:
-  quit usage
-main()
-
diff --git a/todo.txt b/todo.txt
index d0aec9c8c..44aa39791 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,9 +1,10 @@
 version 0.9.4
 =============
 
-- better debugging support for writes to locations
-- document new templating symbol binding rules
-- fix eval in macros.nim
+- fix GC issues
+- fix macros\tstringinterp.nim
+- test and fix showoff
+- fix closure iterators
 
 
 Bugs
@@ -16,7 +17,6 @@ Bugs
 - compilation of niminst takes way too long. looks like a regression
 - docgen: sometimes effects are listed twice
 - 'result' is not properly cleaned for NRVO --> use uninit checking instead
-- sneaking with qualifiedLookup() is really broken!
 - blocks can "export" an identifier but the CCG generates {} for them ...
 - osproc execProcesses can deadlock if all processes fail (as experienced
   in c++ mode)
@@ -25,6 +25,9 @@ Bugs
 version 0.9.x
 =============
 
+- implement 'union' and 'bits' pragmas
+- fix closures
+- test and fix exception handling
 - ensure (ref T)(a, b) works as a type conversion and type constructor
 - optimize 'genericReset'; 'newException' leads to code bloat
 - stack-less GC
diff --git a/web/nimrod.ini b/web/nimrod.ini
index 9af3bc226..71e36dcdc 100644
--- a/web/nimrod.ini
+++ b/web/nimrod.ini
@@ -62,7 +62,7 @@ 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"
 srcdoc2: "packages/docutils/rst;packages/docutils/rstast"
-srcdoc2: "packages/docutils/rstgen"
+srcdoc2: "packages/docutils/rstgen;pure/logging"
 
 webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
 webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc"