summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/core/macros.nim8
-rw-r--r--lib/core/typeinfo.nim2
-rw-r--r--lib/impure/db_mysql.nim24
-rw-r--r--lib/impure/db_postgres.nim125
-rw-r--r--lib/impure/re.nim2
-rw-r--r--lib/impure/zipfiles.nim2
-rw-r--r--lib/packages/docutils/highlite.nim2
-rw-r--r--lib/posix/posix.nim10
-rw-r--r--lib/pure/asyncdispatch.nim264
-rw-r--r--lib/pure/asyncftpclient.nim295
-rw-r--r--lib/pure/asynchttpserver.nim35
-rw-r--r--lib/pure/asyncio.nim43
-rw-r--r--lib/pure/asyncnet.nim17
-rw-r--r--lib/pure/collections/sequtils.nim24
-rw-r--r--lib/pure/collections/sets.nim22
-rw-r--r--lib/pure/concurrency/cpuinfo.nim11
-rw-r--r--lib/pure/concurrency/threadpool.nim24
-rw-r--r--lib/pure/cookies.nim15
-rw-r--r--lib/pure/ftpclient.nim258
-rw-r--r--lib/pure/httpclient.nim3
-rw-r--r--lib/pure/irc.nim503
-rw-r--r--lib/pure/math.nim9
-rw-r--r--lib/pure/memfiles.nim4
-rw-r--r--lib/pure/net.nim590
-rw-r--r--lib/pure/nimprof.nim10
-rw-r--r--lib/pure/os.nim59
-rw-r--r--lib/pure/osproc.nim2
-rw-r--r--lib/pure/parseopt.nim4
-rw-r--r--lib/pure/parseopt2.nim2
-rw-r--r--lib/pure/pegs.nim2
-rw-r--r--lib/pure/rawsockets.nim2
-rw-r--r--lib/pure/ropes.nim4
-rw-r--r--lib/pure/strutils.nim35
-rw-r--r--lib/pure/subexes.nim3
-rw-r--r--lib/pure/times.nim78
-rw-r--r--lib/pure/typetraits.nim23
-rw-r--r--lib/pure/unittest.nim6
-rw-r--r--lib/pure/xmltree.nim4
-rw-r--r--lib/system.nim333
-rw-r--r--lib/system/ansi_c.nim25
-rw-r--r--lib/system/arithm.nim40
-rw-r--r--lib/system/assign.nim4
-rw-r--r--lib/system/atomics.nim56
-rw-r--r--lib/system/channels.nim11
-rw-r--r--lib/system/deepcopy.nim141
-rw-r--r--lib/system/excpt.nim10
-rw-r--r--lib/system/gc.nim4
-rw-r--r--lib/system/gc2.nim2
-rw-r--r--lib/system/hti.nim3
-rw-r--r--lib/system/jssys.nim4
-rw-r--r--lib/system/mmdisp.nim28
-rw-r--r--lib/system/repr.nim16
-rw-r--r--lib/system/sysspawn.nim2
-rw-r--r--lib/system/sysstr.nim4
-rw-r--r--lib/system/threads.nim88
-rw-r--r--lib/system/widestrs.nim8
-rw-r--r--lib/windows/ole2.nim208
-rw-r--r--lib/windows/winlean.nim1
-rw-r--r--lib/wrappers/postgres.nim2
-rw-r--r--lib/wrappers/sdl/sdl_ttf.nim10
-rw-r--r--lib/wrappers/zmq.nim322
61 files changed, 1875 insertions, 1973 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 334a4b8c7..455f99c9e 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -620,6 +620,8 @@ proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} =
     someProc[high(someProc)] = val
   else:
     badNodeKind someProc.kind, "body=" 
+
+proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.}
   
 
 proc `$`*(node: PNimrodNode): string {.compileTime.} =
@@ -627,7 +629,9 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
   case node.kind
   of nnkIdent:
     result = $node.ident
-  of nnkStrLit:
+  of nnkPostfix:
+    result = $node.basename.ident & "*"
+  of nnkStrLit..nnkTripleStrLit:
     result = node.strVal
   else: 
     badNodeKind node.kind, "$"
@@ -669,7 +673,7 @@ proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} =
       a[i + 1] = a[i]
     a[pos] = b
 
-proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.} =
+proc basename*(a: PNimrodNode): PNimrodNode =
   ## Pull an identifier from prefix/postfix expressions
   case a.kind
   of nnkIdent: return a
diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim
index 57e11664b..8df1b3dfb 100644
--- a/lib/core/typeinfo.nim
+++ b/lib/core/typeinfo.nim
@@ -102,7 +102,7 @@ proc newAny(value: pointer, rawType: PNimType): TAny =
   result.value = value
   result.rawType = rawType
 
-when defined(system.TVarSlot):
+when declared(system.TVarSlot):
   proc toAny*(x: TVarSlot): TAny {.inline.} =
     ## constructs a ``TAny`` object from a variable slot ``x``. 
     ## This captures `x`'s address, so `x` can be modified with its
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim
index eec4daf00..ce48a32ed 100644
--- a/lib/impure/db_mysql.nim
+++ b/lib/impure/db_mysql.nim
@@ -57,7 +57,8 @@ when false:
       binding: seq[MYSQL_BIND]
     discard mysql_stmt_close(stmt)
 
-proc dbQuote(s: string): string =
+proc dbQuote*(s: string): string =
+  ## DB quotes the string.
   result = "'"
   for c in items(s):
     if c == '\'': add(result, "''")
@@ -69,7 +70,10 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
   var a = 0
   for c in items(string(formatstr)):
     if c == '?':
-      add(result, dbQuote(args[a]))
+      if args[a] == nil:
+        add(result, "NULL")
+      else:
+        add(result, dbQuote(args[a]))
       inc(a)
     else: 
       add(result, c)
@@ -115,7 +119,10 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
       if row == nil: break
       for i in 0..L-1: 
         setLen(result[i], 0)
-        add(result[i], row[i])
+        if row[i] == nil:
+          result[i] = nil
+        else:
+          add(result[i], row[i])
       yield result
     properFreeResult(sqlres, row)
 
@@ -132,7 +139,10 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
     if row != nil: 
       for i in 0..L-1: 
         setLen(result[i], 0)
-        add(result[i], row[i])
+        if row[i] == nil:
+          result[i] = nil
+        else:
+          add(result[i], row[i])
     properFreeResult(sqlres, row)
 
 proc getAllRows*(db: TDbConn, query: TSqlQuery, 
@@ -150,7 +160,11 @@ proc getAllRows*(db: TDbConn, query: TSqlQuery,
       if row == nil: break
       setLen(result, j+1)
       newSeq(result[j], L)
-      for i in 0..L-1: result[j][i] = $row[i]
+      for i in 0..L-1:
+        if row[i] == nil:
+          result[j][i] = nil
+        else:
+          result[j][i] = $row[i]
       inc(j)
     mysql.FreeResult(sqlres)
 
diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim
index f6ae93303..510cb8e45 100644
--- a/lib/impure/db_postgres.nim
+++ b/lib/impure/db_postgres.nim
@@ -19,12 +19,13 @@ type
   EDb* = object of EIO ## exception that is raised if a database error occurs
   
   TSqlQuery* = distinct string ## an SQL query string
+  TSqlPrepared* = distinct string ## a identifier for the prepared queries
 
   FDb* = object of FIO ## effect that denotes a database operation
   FReadDb* = object of FDB   ## effect that denotes a read operation
   FWriteDb* = object of FDB  ## effect that denotes a write operation
-  
-proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =  
+
+proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =
   ## constructs a TSqlQuery from the string `query`. This is supposed to be 
   ## used as a raw-string-literal modifier:
   ## ``sql"update user set counter = counter + 1"``
@@ -33,21 +34,22 @@ proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =
   ## on, later versions will check the string for valid syntax.
   result = TSqlQuery(query)
  
-proc dbError(db: TDbConn) {.noreturn.} = 
+proc dbError*(db: TDbConn) {.noreturn.} =
   ## raises an EDb exception.
   var e: ref EDb
   new(e)
   e.msg = $PQerrorMessage(db)
   raise e
 
-proc dbError*(msg: string) {.noreturn.} = 
+proc dbError*(msg: string) {.noreturn.} =
   ## raises an EDb exception with message `msg`.
   var e: ref EDb
   new(e)
   e.msg = msg
   raise e
 
-proc dbQuote(s: string): string =
+proc dbQuote*(s: string): string =
+  ## DB quotes the string.
   result = "'"
   for c in items(s):
     if c == '\'': add(result, "''")
@@ -59,43 +61,78 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
   var a = 0
   for c in items(string(formatstr)):
     if c == '?':
-      add(result, dbQuote(args[a]))
+      if args[a] == nil:
+        add(result, "NULL")
+      else:
+        add(result, dbQuote(args[a]))
       inc(a)
-    else: 
+    else:
       add(result, c)
   
-proc tryExec*(db: TDbConn, query: TSqlQuery, 
+proc tryExec*(db: TDbConn, query: TSqlQuery,
               args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
   ## tries to execute the query and returns true if successful, false otherwise.
-  var q = dbFormat(query, args)
-  var res = PQExec(db, q)
+  var arr = allocCStringArray(args)
+  var res = PQexecParams(db, query.string, int32(args.len), nil, arr,
+                        nil, nil, 0)
+  deallocCStringArray(arr)
   result = PQresultStatus(res) == PGRES_COMMAND_OK
   PQclear(res)
 
 proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
   tags: [FReadDB, FWriteDb].} =
   ## executes the query and raises EDB if not successful.
-  var q = dbFormat(query, args)
-  var res = PQExec(db, q)
+  var arr = allocCStringArray(args)
+  var res = PQexecParams(db, query.string, int32(args.len), nil, arr,
+                        nil, nil, 0)
+  deallocCStringArray(arr)
   if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
   PQclear(res)
-  
+
+proc exec*(db: TDbConn, stmtName: TSqlPrepared,
+          args: varargs[string]) {.tags: [FReadDB, FWriteDb].} =
+  var arr = allocCStringArray(args)
+  var res = PQexecPrepared(db, stmtName.string, int32(args.len), arr,
+                           nil, nil, 0)
+  deallocCStringArray(arr)
+  if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
+  PQclear(res)
+
 proc newRow(L: int): TRow =
   newSeq(result, L)
   for i in 0..L-1: result[i] = ""
   
-proc setupQuery(db: TDbConn, query: TSqlQuery, 
-                args: varargs[string]): PPGresult = 
-  var q = dbFormat(query, args)
-  result = PQExec(db, q)
-  if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db)
-  
+proc setupQuery(db: TDbConn, query: TSqlQuery,
+                args: varargs[string]): PPGresult =
+  var arr = allocCStringArray(args)
+  result = PQexecParams(db, query.string, int32(args.len), nil, arr,
+                        nil, nil, 0)
+  deallocCStringArray(arr)
+  if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
+
+proc setupQuery(db: TDbConn, stmtName: TSqlPrepared,
+                 args: varargs[string]): PPGresult =
+  var arr = allocCStringArray(args)
+  result = PQexecPrepared(db, stmtName.string, int32(args.len), arr,
+                          nil, nil, 0)
+  deallocCStringArray(arr)
+  if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
+
+proc prepare*(db: TDbConn; stmtName: string, query: TSqlQuery;
+              nParams: int): TSqlPrepared =
+  var res = PQprepare(db, stmtName, query.string, int32(nParams), nil)
+  if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
+  return TSqlPrepared(stmtName)
+   
 proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
   for col in 0..cols-1:
     setLen(r[col], 0)
     var x = PQgetvalue(res, line, col)
-    add(r[col], x)
-  
+    if x == nil:
+      r[col] = nil
+    else:
+      add(r[col], x)
+
 iterator fastRows*(db: TDbConn, query: TSqlQuery,
                    args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## executes the query and iterates over the result dataset. This is very 
@@ -109,6 +146,17 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
     yield result
   PQclear(res)
 
+iterator fastRows*(db: TDbConn, stmtName: TSqlPrepared,
+                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+  ## executes the prepared query and iterates over the result dataset.
+  var res = setupQuery(db, stmtName, args)
+  var L = PQnfields(res)
+  var result = newRow(L)
+  for i in 0..PQntuples(res)-1:
+    setRow(res, result, i, L)
+    yield result
+  PQclear(res)
+
 proc getRow*(db: TDbConn, query: TSqlQuery,
              args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## retrieves a single row. If the query doesn't return any rows, this proc
@@ -119,40 +167,55 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
   setRow(res, result, 0, L)
   PQclear(res)
 
-proc getAllRows*(db: TDbConn, query: TSqlQuery, 
+proc getRow*(db: TDbConn, stmtName: TSqlPrepared,
+              args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+    var res = setupQuery(db, stmtName, args)
+    var L = PQnfields(res)
+    result = newRow(L)
+    setRow(res, result, 0, L)
+    PQclear(res)
+
+proc getAllRows*(db: TDbConn, query: TSqlQuery,
                  args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
   ## executes the query and returns the whole result dataset.
   result = @[]
   for r in FastRows(db, query, args):
     result.add(r)
 
-iterator rows*(db: TDbConn, query: TSqlQuery, 
+proc getAllRows*(db: TDbConn, stmtName: TSqlPrepared,
+                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
+  ## executes the prepared query and returns the whole result dataset.
+  result = @[]
+  for r in FastRows(db, stmtName, args):
+    result.add(r)
+
+iterator rows*(db: TDbConn, query: TSqlQuery,
                args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## same as `FastRows`, but slower and safe.
   for r in items(GetAllRows(db, query, args)): yield r
 
-proc getValue*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): string {.tags: [FReadDB].} = 
+proc getValue*(db: TDbConn, query: TSqlQuery,
+               args: varargs[string, `$`]): string {.tags: [FReadDB].} =
   ## executes the query and returns the first column of the first row of the
   ## result dataset. Returns "" if the dataset contains no rows or the database
   ## value is NULL.
   var x = PQgetvalue(setupQuery(db, query, args), 0, 0)
   result = if isNil(x): "" else: $x
   
-proc tryInsertID*(db: TDbConn, query: TSqlQuery, 
+proc tryInsertID*(db: TDbConn, query: TSqlQuery,
                   args: varargs[string, `$`]): int64  {.tags: [FWriteDb].}=
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row or -1 in case of an error. For Postgre this adds
   ## ``RETURNING id`` to the query, so it only works if your primary key is
   ## named ``id``. 
-  var x = PQgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"), 
+  var x = PQgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"),
     args), 0, 0)
   if not isNil(x):
     result = ParseBiggestInt($x)
   else:
     result = -1
 
-proc insertID*(db: TDbConn, query: TSqlQuery, 
+proc insertID*(db: TDbConn, query: TSqlQuery,
                args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row. For Postgre this adds
@@ -161,9 +224,9 @@ proc insertID*(db: TDbConn, query: TSqlQuery,
   result = TryInsertID(db, query, args)
   if result < 0: dbError(db)
   
-proc execAffectedRows*(db: TDbConn, query: TSqlQuery, 
+proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
                        args: varargs[string, `$`]): int64 {.tags: [
-                       FReadDB, FWriteDb].} = 
+                       FReadDB, FWriteDb].} =
   ## executes the query (typically "UPDATE") and returns the
   ## number of affected rows.
   var q = dbFormat(query, args)
@@ -172,7 +235,7 @@ proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
   result = parseBiggestInt($PQcmdTuples(res))
   PQclear(res)
 
-proc close*(db: TDbConn) {.tags: [FDb].} = 
+proc close*(db: TDbConn) {.tags: [FDb].} =
   ## closes the database connection.
   if db != nil: PQfinish(db)
 
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index f6511dab4..ac07b2d6b 100644
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -243,7 +243,7 @@ template `=~` *(s: string, pattern: TRegex): expr =
   ##     echo("syntax error")
   ##
   bind maxSubPatterns
-  when not definedInScope(matches):
+  when not declaredInScope(matches):
     var matches {.inject.}: array[0..MaxSubpatterns-1, string]
   match(s, pattern, matches)
 
diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim
index 1726449d8..b9f89dda0 100644
--- a/lib/impure/zipfiles.nim
+++ b/lib/impure/zipfiles.nim
@@ -56,6 +56,8 @@ proc addFile*(z: var TZipArchive, dest, src: string) =
   ## Adds the file `src` to the archive `z` with the name `dest`. `dest`
   ## may contain a path that will be created. 
   assert(z.mode != fmRead) 
+  if not fileExists(src):
+    raise newException(EIO, "File '" & src & "' does not exist")
   var zipsrc = zip_source_file(z.w, src, 0, -1)
   if zipsrc == nil:
     #echo("Dest: " & dest)
diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim
index 80fbf3a51..ff371f4e1 100644
--- a/lib/packages/docutils/highlite.nim
+++ b/lib/packages/docutils/highlite.nim
@@ -50,7 +50,7 @@ const
     "break", "case", "cast", "const", "continue", "converter", "discard",
     "distinct", "div", "do", "elif", "else", "end", "enum", "except", "export",
     "finally", "for", "from", "generic", "if", "import", "in", "include",
-    "interface", "is", "isnot", "iterator", "lambda", "let", "macro", "method",
+    "interface", "is", "isnot", "iterator", "let", "macro", "method",
     "mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc",
     "ptr", "raise", "ref", "return", "shl", "shr", "static",
     "template", "try", "tuple", "type", "using", "var", "when", "while", "with",
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index e1ecbb518..9334ceeae 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -1551,6 +1551,16 @@ var
   MSG_OOB* {.importc, header: "<sys/socket.h>".}: cint
     ## Out-of-band data.
 
+
+when defined(linux):
+  var
+    MAP_POPULATE* {.importc, header: "<sys/mman.h>".}: cint
+      ## Populate (prefault) page tables for a mapping.
+else:
+  var
+    MAP_POPULATE*: cint = 0
+
+
 when defined(macosx):
   var
     MSG_HAVEMORE* {.importc, header: "<sys/socket.h>".}: cint
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index d410f8ce1..0ea8ef43b 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -9,7 +9,7 @@
 
 include "system/inclrtl"
 
-import os, oids, tables, strutils, macros
+import os, oids, tables, strutils, macros, times
 
 import rawsockets, net
 
@@ -27,12 +27,12 @@ export TPort, TSocketFlags
 ## **Note:** This module is still largely experimental.
 
 
-# TODO: Discarded void PFutures need to be checked for exception.
 # TODO: ``except`` statement (without `try`) does not work.
 # TODO: Multiple exception names in a ``except`` don't work.
 # TODO: The effect system (raises: []) has trouble with my try transformation.
 # TODO: Can't await in a 'except' body
 # TODO: getCurrentException(Msg) don't work
+# TODO: Check if yielded future is nil and throw a more meaningful exception
 
 # -- Futures
 
@@ -41,27 +41,41 @@ type
     cb: proc () {.closure,gcsafe.}
     finished: bool
     error*: ref EBase
-    stackTrace: string ## For debugging purposes only.
+    errorStackTrace*: string
+    when not defined(release):
+      stackTrace: string ## For debugging purposes only.
+      id: int
+      fromProc: string
 
   PFuture*[T] = ref object of PFutureBase
     value: T
 
-proc newFuture*[T](): PFuture[T] =
+var currentID* = 0
+proc newFuture*[T](fromProc: string = "unspecified"): PFuture[T] =
   ## Creates a new future.
+  ##
+  ## Specifying ``fromProc``, which is a string specifying the name of the proc
+  ## that this future belongs to, is a good habit as it helps with debugging.
   new(result)
   result.finished = false
-  result.stackTrace = getStackTrace()
+  when not defined(release):
+    result.stackTrace = getStackTrace()
+    result.id = currentID
+    result.fromProc = fromProc
+    currentID.inc()
 
 proc checkFinished[T](future: PFuture[T]) =
-  if future.finished:
-    echo("<----->")
-    echo(future.stackTrace)
-    echo("-----")
-    when T is string:
-      echo("Contents: ", future.value.repr)
-    echo("<----->")
-    echo("Future already finished, cannot finish twice.")
-    assert false
+  when not defined(release):
+    if future.finished:
+      echo("<-----> ", future.id, " ", future.fromProc)
+      echo(future.stackTrace)
+      echo("-----")
+      when T is string:
+        echo("Contents: ", future.value.repr)
+      echo("<----->")
+      echo("Future already finished, cannot finish twice.")
+      echo getStackTrace()
+      assert false
 
 proc complete*[T](future: PFuture[T], val: T) =
   ## Completes ``future`` with value ``val``.
@@ -88,6 +102,8 @@ proc fail*[T](future: PFuture[T], error: ref EBase) =
   checkFinished(future)
   future.finished = true
   future.error = error
+  future.errorStackTrace =
+    if getStackTrace(error) == "": getStackTrace() else: getStackTrace(error)
   if future.cb != nil:
     future.cb()
   else:
@@ -115,13 +131,24 @@ proc `callback=`*[T](future: PFuture[T],
   ## If future has already completed then ``cb`` will be called immediately.
   future.callback = proc () = cb(future)
 
+proc echoOriginalStackTrace[T](future: PFuture[T]) =
+  # TODO: Come up with something better.
+  when not defined(release):
+    echo("Original stack trace in ", future.fromProc, ":")
+    if not future.errorStackTrace.isNil() and future.errorStackTrace != "":
+      echo(future.errorStackTrace)
+    else:
+      echo("Empty or nil stack trace.")
+
 proc read*[T](future: PFuture[T]): T =
   ## Retrieves the value of ``future``. Future must be finished otherwise
   ## this function will fail with a ``EInvalidValue`` exception.
   ##
   ## If the result of the future is an error then that error will be raised.
   if future.finished:
-    if future.error != nil: raise future.error
+    if future.error != nil:
+      echoOriginalStackTrace(future)
+      raise future.error
     when T isnot void:
       return future.value
   else:
@@ -150,7 +177,44 @@ proc asyncCheck*[T](future: PFuture[T]) =
   ## This should be used instead of ``discard`` to discard void futures.
   future.callback =
     proc () =
-      if future.failed: raise future.error
+      if future.failed:
+        echoOriginalStackTrace(future)
+        raise future.error
+
+proc `and`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] =
+  ## Returns a future which will complete once both ``fut1`` and ``fut2``
+  ## complete.
+  var retFuture = newFuture[void]("asyncdispatch.`and`")
+  fut1.callback =
+    proc () =
+      if fut2.finished: retFuture.complete()
+  fut2.callback =
+    proc () =
+      if fut1.finished: retFuture.complete()
+  return retFuture
+
+proc `or`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] =
+  ## Returns a future which will complete once either ``fut1`` or ``fut2``
+  ## complete.
+  var retFuture = newFuture[void]("asyncdispatch.`or`")
+  proc cb() =
+    if not retFuture.finished: retFuture.complete()
+  fut1.callback = cb
+  fut2.callback = cb
+  return retFuture
+
+type
+  PDispatcherBase = ref object of PObject
+    timers: seq[tuple[finishAt: float, fut: PFuture[void]]]
+
+proc processTimers(p: PDispatcherBase) =
+  var oldTimers = p.timers
+  p.timers = @[]
+  for t in oldTimers:
+    if epochTime() >= t.finishAt:
+      t.fut.complete()
+    else:
+      p.timers.add(t)
 
 when defined(windows) or defined(nimdoc):
   import winlean, sets, hashes
@@ -162,7 +226,7 @@ when defined(windows) or defined(nimdoc):
       cb: proc (sock: TAsyncFD, bytesTransferred: DWORD,
                 errcode: TOSErrorCode) {.closure,gcsafe.}
 
-    PDispatcher* = ref object
+    PDispatcher* = ref object of PDispatcherBase
       ioPort: THandle
       handles: TSet[TAsyncFD]
 
@@ -181,6 +245,7 @@ when defined(windows) or defined(nimdoc):
     new result
     result.ioPort = CreateIOCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1)
     result.handles = initSet[TAsyncFD]()
+    result.timers = @[]
 
   var gDisp{.threadvar.}: PDispatcher ## Global dispatcher
   proc getGlobalDispatcher*(): PDispatcher =
@@ -207,8 +272,9 @@ when defined(windows) or defined(nimdoc):
   proc poll*(timeout = 500) =
     ## Waits for completion events and processes them.
     let p = getGlobalDispatcher()
-    if p.handles.len == 0:
-      raise newException(EInvalidValue, "No handles registered in dispatcher.")
+    if p.handles.len == 0 and p.timers.len == 0:
+      raise newException(EInvalidValue,
+        "No handles or timers registered in dispatcher.")
     
     let llTimeout =
       if timeout ==  -1: winlean.INFINITE
@@ -242,6 +308,9 @@ when defined(windows) or defined(nimdoc):
           discard
         else: osError(errCode)
 
+    # Timer processing.
+    processTimers(p)
+
   var connectExPtr: pointer = nil
   var acceptExPtr: pointer = nil
   var getAcceptExSockAddrsPtr: pointer = nil
@@ -314,7 +383,7 @@ when defined(windows) or defined(nimdoc):
     ## Returns a ``PFuture`` which will complete when the connection succeeds
     ## or an error occurs.
     verifyPresence(socket)
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("connect")
     # Apparently ``ConnectEx`` expects the socket to be initially bound:
     var saddr: Tsockaddr_in
     saddr.sin_family = int16(toInt(af))
@@ -384,7 +453,7 @@ when defined(windows) or defined(nimdoc):
     #     '\0' in the message currently signifies a socket disconnect. Who
     #     knows what will happen when someone sends that to our socket.
     verifyPresence(socket)
-    var retFuture = newFuture[string]()    
+    var retFuture = newFuture[string]("recv")
     var dataBuf: TWSABuf
     dataBuf.buf = cast[cstring](alloc0(size))
     dataBuf.len = size
@@ -405,7 +474,10 @@ when defined(windows) or defined(nimdoc):
               copyMem(addr data[0], addr dataBuf.buf[0], bytesCount)
               retFuture.complete($data)
           else:
-            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+            if flags.isDisconnectionError(errcode):
+              retFuture.complete("")
+            else:
+              retFuture.fail(newException(EOS, osErrorMsg(errcode)))
         if dataBuf.buf != nil:
           dealloc dataBuf.buf
           dataBuf.buf = nil
@@ -459,7 +531,7 @@ when defined(windows) or defined(nimdoc):
     ## Sends ``data`` to ``socket``. The returned future will complete once all
     ## data has been sent.
     verifyPresence(socket)
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("send")
 
     var dataBuf: TWSABuf
     dataBuf.buf = data # since this is not used in a callback, this is fine
@@ -474,7 +546,10 @@ when defined(windows) or defined(nimdoc):
           if errcode == TOSErrorCode(-1):
             retFuture.complete()
           else:
-            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+            if flags.isDisconnectionError(errcode):
+              retFuture.complete()
+            else:
+              retFuture.fail(newException(EOS, osErrorMsg(errcode)))
     )
 
     let ret = WSASend(socket.TSocketHandle, addr dataBuf, 1, addr bytesReceived,
@@ -494,15 +569,21 @@ when defined(windows) or defined(nimdoc):
       # free ``ol``.
     return retFuture
 
-  proc acceptAddr*(socket: TAsyncFD): 
+  proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}):
       PFuture[tuple[address: string, client: TAsyncFD]] =
     ## Accepts a new connection. Returns a future containing the client socket
     ## corresponding to that connection and the remote address of the client.
     ## The future will complete when the connection is successfully accepted.
     ##
-    ## The resulting client socket is automatically registered to dispatcher.
+    ## The resulting client socket is automatically registered to the
+    ## dispatcher.
+    ##
+    ## The ``accept`` call may result in an error if the connecting socket
+    ## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
+    ## flag is specified then this error will not be raised and instead
+    ## accept will be called again.
     verifyPresence(socket)
-    var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]()
+    var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]("acceptAddr")
 
     var clientSock = newRawSocket()
     if clientSock == osInvalidSocket: osError(osLastError())
@@ -534,6 +615,18 @@ when defined(windows) or defined(nimdoc):
          client: clientSock.TAsyncFD)
       )
 
+    template failAccept(errcode): stmt =
+      if flags.isDisconnectionError(errcode):
+        var newAcceptFut = acceptAddr(socket, flags)
+        newAcceptFut.callback =
+          proc () =
+            if newAcceptFut.failed:
+              retFuture.fail(newAcceptFut.readError)
+            else:
+              retFuture.complete(newAcceptFut.read)
+      else:
+        retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+
     var ol = PCustomOverlapped()
     GC_ref(ol)
     ol.data = TCompletionData(sock: socket, cb:
@@ -542,7 +635,7 @@ when defined(windows) or defined(nimdoc):
           if errcode == TOSErrorCode(-1):
             completeAccept()
           else:
-            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+            failAccept(errcode)
     )
 
     # http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
@@ -555,7 +648,7 @@ when defined(windows) or defined(nimdoc):
     if not ret:
       let err = osLastError()
       if err.int32 != ERROR_IO_PENDING:
-        retFuture.fail(newException(EOS, osErrorMsg(err)))
+        failAccept(err)
         GC_unref(ol)
     else:
       completeAccept()
@@ -606,7 +699,7 @@ else:
       readCBs: seq[TCallback]
       writeCBs: seq[TCallback]
 
-    PDispatcher* = ref object
+    PDispatcher* = ref object of PDispatcherBase
       selector: PSelector
 
   proc `==`*(x, y: TAsyncFD): bool {.borrow.}
@@ -614,6 +707,7 @@ else:
   proc newDispatcher*(): PDispatcher =
     new result
     result.selector = newSelector()
+    result.timers = @[]
 
   var gDisp{.threadvar.}: PDispatcher ## Global dispatcher
   proc getGlobalDispatcher*(): PDispatcher =
@@ -693,10 +787,12 @@ else:
       else:
         # FD no longer a part of the selector. Likely been closed
         # (e.g. socket disconnected).
+
+    processTimers(p)
   
   proc connect*(socket: TAsyncFD, address: string, port: TPort,
     af = AF_INET): PFuture[void] =
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("connect")
     
     proc cb(sock: TAsyncFD): bool =
       # We have connected.
@@ -731,7 +827,7 @@ else:
 
   proc recv*(socket: TAsyncFD, size: int,
              flags = {TSocketFlags.SafeDisconn}): PFuture[string] =
-    var retFuture = newFuture[string]()
+    var retFuture = newFuture[string]("recv")
     
     var readBuffer = newString(size)
 
@@ -762,7 +858,7 @@ else:
 
   proc send*(socket: TAsyncFD, data: string,
              flags = {TSocketFlags.SafeDisconn}): PFuture[void] =
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("send")
     
     var written = 0
     
@@ -792,9 +888,10 @@ else:
     addWrite(socket, cb)
     return retFuture
 
-  proc acceptAddr*(socket: TAsyncFD): 
+  proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}):
       PFuture[tuple[address: string, client: TAsyncFD]] =
-    var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]()
+    var retFuture = newFuture[tuple[address: string,
+        client: TAsyncFD]]("acceptAddr")
     proc cb(sock: TAsyncFD): bool =
       result = true
       var sockAddress: Tsockaddr_in
@@ -807,19 +904,31 @@ else:
         if lastError.int32 == EINTR:
           return false
         else:
-          retFuture.fail(newException(EOS, osErrorMsg(lastError)))
+          if flags.isDisconnectionError(lastError):
+            return false
+          else:
+            retFuture.fail(newException(EOS, osErrorMsg(lastError)))
       else:
         register(client.TAsyncFD)
         retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client.TAsyncFD))
     addRead(socket, cb)
     return retFuture
 
-proc accept*(socket: TAsyncFD): PFuture[TAsyncFD] =
+proc sleepAsync*(ms: int): PFuture[void] =
+  ## Suspends the execution of the current async procedure for the next
+  ## ``ms`` miliseconds.
+  var retFuture = newFuture[void]("sleepAsync")
+  let p = getGlobalDispatcher()
+  p.timers.add((epochTime() + (ms / 1000), retFuture))
+  return retFuture
+
+proc accept*(socket: TAsyncFD,
+    flags = {TSocketFlags.SafeDisconn}): PFuture[TAsyncFD] =
   ## Accepts a new connection. Returns a future containing the client socket
   ## corresponding to that connection.
   ## The future will complete when the connection is successfully accepted.
-  var retFut = newFuture[TAsyncFD]()
-  var fut = acceptAddr(socket)
+  var retFut = newFuture[TAsyncFD]("accept")
+  var fut = acceptAddr(socket, flags)
   fut.callback =
     proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
       assert future.finished
@@ -845,11 +954,16 @@ template createCb*(retFutureSym, iteratorNameSym,
         else:
           next.callback = cb
     except:
-      retFutureSym.fail(getCurrentException())
+      if retFutureSym.finished:
+        # Take a look at tasyncexceptions for the bug which this fixes.
+        # That test explains it better than I can here.
+        raise
+      else:
+        retFutureSym.fail(getCurrentException())
   cb()
   #{.pop.}
 proc generateExceptionCheck(futSym,
-    exceptBranch, rootReceiver: PNimrodNode): PNimrodNode {.compileTime.} =
+    exceptBranch, rootReceiver, fromNode: PNimrodNode): PNimrodNode {.compileTime.} =
   if exceptBranch == nil:
     result = rootReceiver
   else:
@@ -869,20 +983,21 @@ proc generateExceptionCheck(futSym,
            )
          )
       )
-    let elseNode = newNimNode(nnkElse)
-    elseNode.add newNimNode(nnkStmtList)
+    let elseNode = newNimNode(nnkElse, fromNode)
+    elseNode.add newNimNode(nnkStmtList, fromNode)
     elseNode[0].add rootReceiver
     result.add elseNode
 
 template createVar(result: var PNimrodNode, futSymName: string,
                    asyncProc: PNimrodNode,
-                   valueReceiver, rootReceiver: expr) =
-  result = newNimNode(nnkStmtList)
+                   valueReceiver, rootReceiver: expr,
+                   fromNode: PNimrodNode) =
+  result = newNimNode(nnkStmtList, fromNode)
   var futSym = genSym(nskVar, "future")
   result.add newVarStmt(futSym, asyncProc) # -> var future<x> = y
-  result.add newNimNode(nnkYieldStmt).add(futSym) # -> yield future<x>
+  result.add newNimNode(nnkYieldStmt, fromNode).add(futSym) # -> yield future<x>
   valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future<x>.read
-  result.add generateExceptionCheck(futSym, exceptBranch, rootReceiver)
+  result.add generateExceptionCheck(futSym, exceptBranch, rootReceiver, fromNode)
 
 proc processBody(node, retFutureSym: PNimrodNode,
                  subTypeIsVoid: bool,
@@ -891,7 +1006,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
   result = node
   case node.kind
   of nnkReturnStmt:
-    result = newNimNode(nnkStmtList)
+    result = newNimNode(nnkStmtList, node)
     if node[0].kind == nnkEmpty:
       if not subtypeIsVoid:
         result.add newCall(newIdentNode("complete"), retFutureSym,
@@ -902,36 +1017,36 @@ proc processBody(node, retFutureSym: PNimrodNode,
       result.add newCall(newIdentNode("complete"), retFutureSym,
         node[0].processBody(retFutureSym, subtypeIsVoid, exceptBranch))
 
-    result.add newNimNode(nnkReturnStmt).add(newNilLit())
+    result.add newNimNode(nnkReturnStmt, node).add(newNilLit())
     return # Don't process the children of this return stmt
-  of nnkCommand:
+  of nnkCommand, nnkCall:
     if node[0].kind == nnkIdent and node[0].ident == !"await":
       case node[1].kind
-      of nnkIdent:
+      of nnkIdent, nnkInfix:
         # await x
-        result = newNimNode(nnkYieldStmt).add(node[1]) # -> yield x
-      of nnkCall:
+        result = newNimNode(nnkYieldStmt, node).add(node[1]) # -> yield x
+      of nnkCall, nnkCommand:
         # await foo(p, x)
         var futureValue: PNimrodNode
         result.createVar("future" & $node[1][0].toStrLit, node[1], futureValue,
-                  futureValue)
+                  futureValue, node)
       else:
         error("Invalid node kind in 'await', got: " & $node[1].kind)
-    elif node[1].kind == nnkCommand and node[1][0].kind == nnkIdent and
-         node[1][0].ident == !"await":
+    elif node.len > 1 and node[1].kind == nnkCommand and
+         node[1][0].kind == nnkIdent and node[1][0].ident == !"await":
       # foo await x
       var newCommand = node
       result.createVar("future" & $node[0].toStrLit, node[1][1], newCommand[1],
-                newCommand)
+                newCommand, node)
 
   of nnkVarSection, nnkLetSection:
     case node[0][2].kind
     of nnkCommand:
-      if node[0][2][0].ident == !"await":
+      if node[0][2][0].kind == nnkIdent and node[0][2][0].ident == !"await":
         # var x = await y
         var newVarSection = node # TODO: Should this use copyNimNode?
         result.createVar("future" & $node[0][0].ident, node[0][2][1],
-          newVarSection[0][2], newVarSection)
+          newVarSection[0][2], newVarSection, node)
     else: discard
   of nnkAsgn:
     case node[1].kind
@@ -939,7 +1054,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
       if node[1][0].ident == !"await":
         # x = await y
         var newAsgn = node
-        result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn)
+        result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn, node)
     else: discard
   of nnkDiscardStmt:
     # discard await x
@@ -947,10 +1062,10 @@ proc processBody(node, retFutureSym: PNimrodNode,
           node[0][0].ident == !"await":
       var newDiscard = node
       result.createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1],
-                newDiscard[0], newDiscard)
+                newDiscard[0], newDiscard, node)
   of nnkTryStmt:
     # try: await x; except: ...
-    result = newNimNode(nnkStmtList)
+    result = newNimNode(nnkStmtList, node)
     proc processForTry(n: PNimrodNode, i: var int,
                        res: PNimrodNode): bool {.compileTime.} =
       result = false
@@ -1009,7 +1124,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
         (returnType.kind == nnkBracketExpr and
          returnType[1].kind == nnkIdent and returnType[1].ident == !"void")
 
-  var outerProcBody = newNimNode(nnkStmtList)
+  var outerProcBody = newNimNode(nnkStmtList, prc[6])
 
   # -> var retFuture = newFuture[T]()
   var retFutureSym = genSym(nskVar, "retFuture")
@@ -1019,9 +1134,10 @@ macro async*(prc: stmt): stmt {.immediate.} =
   outerProcBody.add(
     newVarStmt(retFutureSym, 
       newCall(
-        newNimNode(nnkBracketExpr).add(
+        newNimNode(nnkBracketExpr, prc[6]).add(
           newIdentNode(!"newFuture"), # TODO: Strange bug here? Remove the `!`.
-          subRetType)))) # Get type from return type of this proc
+          subRetType),
+      newLit(prc[0].getName)))) # Get type from return type of this proc
   
   # -> iterator nameIter(): PFutureBase {.closure.} = 
   # ->   var result: T
@@ -1030,7 +1146,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   var iteratorNameSym = genSym(nskIterator, $prc[0].getName & "Iter")
   var procBody = prc[6].processBody(retFutureSym, subtypeIsVoid, nil)
   if not subtypeIsVoid:
-    procBody.insert(0, newNimNode(nnkVarSection).add(
+    procBody.insert(0, newNimNode(nnkVarSection, prc[6]).add(
       newIdentDefs(newIdentNode("result"), returnType[1]))) # -> var result: T
     procBody.add(
       newCall(newIdentNode("complete"),
@@ -1041,7 +1157,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   
   var closureIterator = newProc(iteratorNameSym, [newIdentNode("PFutureBase")],
                                 procBody, nnkIteratorDef)
-  closureIterator[4] = newNimNode(nnkPragma).add(newIdentNode("closure"))
+  closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure"))
   outerProcBody.add(closureIterator)
 
   # -> createCb(retFuture)
@@ -1051,7 +1167,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   outerProcBody.add procCb
 
   # -> return retFuture
-  outerProcBody.add newNimNode(nnkReturnStmt).add(retFutureSym)
+  outerProcBody.add newNimNode(nnkReturnStmt, prc[6][prc[6].len-1]).add(retFutureSym)
   
   result = prc
 
@@ -1068,8 +1184,8 @@ macro async*(prc: stmt): stmt {.immediate.} =
   result[6] = outerProcBody
 
   #echo(treeRepr(result))
-  #if prc[0].getName == "routeReq":
-  #echo(toStrLit(result))
+  #if prc[0].getName == "getFile":
+  #  echo(toStrLit(result))
 
 proc recvLine*(socket: TAsyncFD): PFuture[string] {.async.} =
   ## Reads a line of data from ``socket``. Returned future will complete once
@@ -1110,3 +1226,11 @@ proc runForever*() =
   ## Begins a never ending global dispatcher poll loop.
   while true:
     poll()
+
+proc waitFor*[T](fut: PFuture[T]) =
+  ## **Blocks** the current thread until the specified future completes.
+  while not fut.finished:
+    poll()
+
+  if fut.failed:
+    raise fut.error
diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim
new file mode 100644
index 000000000..f1b1d1400
--- /dev/null
+++ b/lib/pure/asyncftpclient.nim
@@ -0,0 +1,295 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Dominik Picheta
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+import asyncdispatch, asyncnet, strutils, parseutils, os, times
+
+from ftpclient import TFtpBase, EInvalidReply, TFtpEvent
+from net import bufferSize
+
+type
+  TAsyncFtpClient* = TFtpBase[PAsyncSocket]
+  PAsyncFtpClient* = ref TAsyncFtpClient
+
+  ProgressChangedProc* =
+    proc (total, progress: BiggestInt, speed: float):
+      PFuture[void] {.closure, gcsafe.}
+
+proc expectReply(ftp: PAsyncFtpClient): PFuture[TaintedString] =
+  result = ftp.csock.recvLine()
+
+proc send*(ftp: PAsyncFtpClient, m: string): PFuture[TaintedString] {.async.} =
+  ## Send a message to the server, and wait for a primary reply.
+  ## ``\c\L`` is added for you.
+  await ftp.csock.send(m & "\c\L")
+  return await ftp.expectReply()
+
+proc assertReply(received: TaintedString, expected: varargs[string]) =
+  for i in items(expected):
+    if received.string.startsWith(i): return
+  raise newException(EInvalidReply,
+                     "Expected reply '$1' got: $2" %
+                     [expected.join("' or '"), received.string])
+
+proc pasv(ftp: PAsyncFtpClient) {.async.} =
+  ## Negotiate a data connection.
+  ftp.dsock = newAsyncSocket()
+
+  var pasvMsg = (await ftp.send("PASV")).string.strip.TaintedString
+  assertReply(pasvMsg, "227")
+  var betweenParens = captureBetween(pasvMsg.string, '(', ')')
+  var nums = betweenParens.split(',')
+  var ip = nums[0.. -3]
+  var port = nums[-2.. -1]
+  var properPort = port[0].parseInt()*256+port[1].parseInt()
+  await ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
+  ftp.dsockConnected = True
+
+proc normalizePathSep(path: string): string =
+  return replace(path, '\\', '/')
+
+proc connect*(ftp: PAsyncFtpClient) {.async.} =
+  ## Connect to the FTP server specified by ``ftp``.
+  await ftp.csock.connect(ftp.address, ftp.port)
+
+  var reply = await ftp.expectReply()
+  if reply.startsWith("120"):
+    # 120 Service ready in nnn minutes.
+    # We wait until we receive 220.
+    reply = await ftp.expectReply()
+  assertReply(reply, "220")
+
+  if ftp.user != "":
+    assertReply(await(ftp.send("USER " & ftp.user)), "230", "331")
+
+  if ftp.pass != "":
+    assertReply(await(ftp.send("PASS " & ftp.pass)), "230")
+
+proc pwd*(ftp: PAsyncFtpClient): PFuture[TaintedString] {.async.} =
+  ## Returns the current working directory.
+  let wd = await ftp.send("PWD")
+  assertReply wd, "257"
+  return wd.string.captureBetween('"').TaintedString # "
+
+proc cd*(ftp: PAsyncFtpClient, dir: string) {.async.} =
+  ## Changes the current directory on the remote FTP server to ``dir``.
+  assertReply(await(ftp.send("CWD " & dir.normalizePathSep)), "250")
+
+proc cdup*(ftp: PAsyncFtpClient) {.async.} =
+  ## Changes the current directory to the parent of the current directory.
+  assertReply(await(ftp.send("CDUP")), "200")
+
+proc getLines(ftp: PAsyncFtpClient): PFuture[string] {.async.} =
+  ## Downloads text data in ASCII mode
+  result = ""
+  assert ftp.dsockConnected
+  while ftp.dsockConnected:
+    let r = await ftp.dsock.recvLine()
+    if r.string == "":
+      ftp.dsockConnected = false
+    else:
+      result.add(r.string & "\n")
+
+  assertReply(await(ftp.expectReply()), "226")
+
+proc listDirs*(ftp: PAsyncFtpClient, dir = ""): PFuture[seq[string]] {.async.} =
+  ## Returns a list of filenames in the given directory. If ``dir`` is "",
+  ## the current directory is used. If ``async`` is true, this
+  ## function will return immediately and it will be your job to
+  ## use asyncio's ``poll`` to progress this operation.
+  await ftp.pasv()
+
+  assertReply(await(ftp.send("NLST " & dir.normalizePathSep)), ["125", "150"])
+
+  result = splitLines(await ftp.getLines())
+
+proc existsFile*(ftp: PAsyncFtpClient, file: string): PFuture[bool] {.async.} =
+  ## Determines whether ``file`` exists.
+  var files = await ftp.listDirs()
+  for f in items(files):
+    if f.normalizePathSep == file.normalizePathSep: return true
+
+proc createDir*(ftp: PAsyncFtpClient, dir: string, recursive = false){.async.} =
+  ## Creates a directory ``dir``. If ``recursive`` is true, the topmost
+  ## subdirectory of ``dir`` will be created first, following the secondmost...
+  ## etc. this allows you to give a full path as the ``dir`` without worrying
+  ## about subdirectories not existing.
+  if not recursive:
+    assertReply(await(ftp.send("MKD " & dir.normalizePathSep)), "257")
+  else:
+    var reply = TaintedString""
+    var previousDirs = ""
+    for p in split(dir, {os.dirSep, os.altSep}):
+      if p != "":
+        previousDirs.add(p)
+        reply = await ftp.send("MKD " & previousDirs)
+        previousDirs.add('/')
+    assertReply reply, "257"
+
+proc chmod*(ftp: PAsyncFtpClient, path: string,
+            permissions: set[TFilePermission]) {.async.} =
+  ## Changes permission of ``path`` to ``permissions``.
+  var userOctal = 0
+  var groupOctal = 0
+  var otherOctal = 0
+  for i in items(permissions):
+    case i
+    of fpUserExec: userOctal.inc(1)
+    of fpUserWrite: userOctal.inc(2)
+    of fpUserRead: userOctal.inc(4)
+    of fpGroupExec: groupOctal.inc(1)
+    of fpGroupWrite: groupOctal.inc(2)
+    of fpGroupRead: groupOctal.inc(4)
+    of fpOthersExec: otherOctal.inc(1)
+    of fpOthersWrite: otherOctal.inc(2)
+    of fpOthersRead: otherOctal.inc(4)
+
+  var perm = $userOctal & $groupOctal & $otherOctal
+  assertReply(await(ftp.send("SITE CHMOD " & perm &
+                    " " & path.normalizePathSep)), "200")
+
+proc list*(ftp: PAsyncFtpClient, dir = ""): PFuture[string] {.async.} =
+  ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current
+  ## working directory.
+  await ftp.pasv()
+
+  let reply = await ftp.send("LIST" & " " & dir.normalizePathSep)
+  assertReply(reply, ["125", "150"])
+
+  result = await ftp.getLines()
+
+proc retrText*(ftp: PAsyncFtpClient, file: string): PFuture[string] {.async.} =
+  ## Retrieves ``file``. File must be ASCII text.
+  await ftp.pasv()
+  let reply = await ftp.send("RETR " & file.normalizePathSep)
+  assertReply(reply, ["125", "150"])
+
+  result = await ftp.getLines()
+
+proc getFile(ftp: PAsyncFtpClient, file: TFile, total: BiggestInt,
+             onProgressChanged: ProgressChangedProc) {.async.} =
+  assert ftp.dsockConnected
+  var progress = 0
+  var progressInSecond = 0
+  var countdownFut = sleepAsync(1000)
+  var dataFut = ftp.dsock.recv(bufferSize)
+  while ftp.dsockConnected:
+    await dataFut or countdownFut
+    if countdownFut.finished:
+      asyncCheck onProgressChanged(total, progress,
+          progressInSecond.float)
+      progressInSecond = 0
+      countdownFut = sleepAsync(1000)
+
+    if dataFut.finished:
+      let data = dataFut.read
+      if data != "":
+        progress.inc(data.len)
+        progressInSecond.inc(data.len)
+        file.write(data)
+        dataFut = ftp.dsock.recv(bufferSize)
+      else:
+        ftp.dsockConnected = False
+
+  assertReply(await(ftp.expectReply()), "226")
+
+proc defaultOnProgressChanged*(total, progress: BiggestInt,
+    speed: float): PFuture[void] {.nimcall,gcsafe.} =
+  ## Default FTP ``onProgressChanged`` handler. Does nothing.
+  result = newFuture[void]()
+  #echo(total, " ", progress, " ", speed)
+  result.complete()
+
+proc retrFile*(ftp: PAsyncFtpClient, file, dest: string,
+               onProgressChanged = defaultOnProgressChanged) {.async.} =
+  ## Downloads ``file`` and saves it to ``dest``.
+  ## The ``EvRetr`` event is passed to the specified ``handleEvent`` function
+  ## when the download is finished. The event's ``filename`` field will be equal
+  ## to ``file``.
+  var destFile = open(dest, mode = fmWrite)
+  await ftp.pasv()
+  var reply = await ftp.send("RETR " & file.normalizePathSep)
+  assertReply reply, ["125", "150"]
+  if {'(', ')'} notin reply.string:
+    raise newException(EInvalidReply, "Reply has no file size.")
+  var fileSize: biggestInt
+  if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0:
+    raise newException(EInvalidReply, "Reply has no file size.")
+
+  await getFile(ftp, destFile, fileSize, onProgressChanged)
+
+proc doUpload(ftp: PAsyncFtpClient, file: TFile,
+              onProgressChanged: ProgressChangedProc) {.async.} =
+  assert ftp.dsockConnected
+
+  let total = file.getFileSize()
+  var data = newStringOfCap(4000)
+  var progress = 0
+  var progressInSecond = 0
+  var countdownFut = sleepAsync(1000)
+  var sendFut: PFuture[void] = nil
+  while ftp.dsockConnected:
+    if sendFut == nil or sendFut.finished:
+      progress.inc(data.len)
+      progressInSecond.inc(data.len)
+      # TODO: Async file reading.
+      let len = file.readBuffer(addr(data[0]), 4000)
+      setLen(data, len)
+      if len == 0:
+        # File finished uploading.
+        ftp.dsock.close()
+        ftp.dsockConnected = false
+
+        assertReply(await(ftp.expectReply()), "226")
+      else:
+        sendFut = ftp.dsock.send(data)
+
+    if countdownFut.finished:
+      asyncCheck onProgressChanged(total, progress, progressInSecond.float)
+      progressInSecond = 0
+      countdownFut = sleepAsync(1000)
+
+    await countdownFut or sendFut
+
+proc storeFile*(ftp: PAsyncFtpClient, file, dest: string,
+            onProgressChanged = defaultOnProgressChanged) {.async.} =
+  ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this
+  ## function asynchronously is recommended to view the progress of
+  ## the download.
+  ## The ``EvStore`` event is passed to the specified ``handleEvent`` function
+  ## when the upload is finished, and the ``filename`` field will be
+  ## equal to ``file``.
+  var destFile = open(file)
+  await ftp.pasv()
+
+  let reply = await ftp.send("STOR " & dest.normalizePathSep)
+  assertReply reply, ["125", "150"]
+
+  await doUpload(ftp, destFile, onProgressChanged)
+
+proc newAsyncFtpClient*(address: string, port = TPort(21),
+    user, pass = ""): PAsyncFtpClient =
+  ## Creates a new ``PAsyncFtpClient`` object.
+  new result
+  result.user = user
+  result.pass = pass
+  result.address = address
+  result.port = port
+  result.dsockConnected = false
+  result.csock = newAsyncSocket()
+
+when isMainModule:
+  var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
+  proc main(ftp: PAsyncFtpClient) {.async.} =
+    await ftp.connect()
+    echo await ftp.pwd()
+    echo await ftp.listDirs()
+    await ftp.storeFile("payload.jpg", "payload.jpg")
+    await ftp.retrFile("payload.jpg", "payload2.jpg")
+    echo("Finished")
+
+  waitFor main(ftp)
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index ee6658fd1..c8bd5cfc1 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -11,14 +11,14 @@
 ##
 ## **Note:** This module is still largely experimental.
 
-import strtabs, asyncnet, asyncdispatch, parseutils, parseurl, strutils
+import strtabs, asyncnet, asyncdispatch, parseutils, uri, strutils
 type
   TRequest* = object
     client*: PAsyncSocket # TODO: Separate this into a Response object?
     reqMethod*: string
     headers*: PStringTable
     protocol*: tuple[orig: string, major, minor: int]
-    url*: TURL
+    url*: TUri
     hostname*: string ## The hostname of the client that made the request.
     body*: string
 
@@ -97,7 +97,8 @@ proc sendStatus(client: PAsyncSocket, status: string): PFuture[void] =
   client.send("HTTP/1.1 " & status & "\c\L")
 
 proc processClient(client: PAsyncSocket, address: string,
-                 callback: proc (request: TRequest): PFuture[void]) {.async.} =
+                   callback: proc (request: TRequest):
+                      PFuture[void] {.closure, gcsafe.}) {.async.} =
   while true:
     # GET /path HTTP/1.1
     # Header: val
@@ -135,7 +136,7 @@ proc processClient(client: PAsyncSocket, address: string,
       request.headers[kv.key] = kv.value
 
     request.reqMethod = reqMethod
-    request.url = parseUrl(path)
+    request.url = parseUri(path)
     try:
       request.protocol = protocol.parseProtocol()
     except EInvalidValue:
@@ -184,7 +185,7 @@ proc processClient(client: PAsyncSocket, address: string,
       break
 
 proc serve*(server: PAsyncHttpServer, port: TPort,
-            callback: proc (request: TRequest): PFuture[void],
+            callback: proc (request: TRequest): PFuture[void] {.closure,gcsafe.},
             address = "") {.async.} =
   ## Starts the process of listening for incoming HTTP connections on the
   ## specified address and port.
@@ -199,19 +200,23 @@ proc serve*(server: PAsyncHttpServer, port: TPort,
     #var (address, client) = await server.socket.acceptAddr()
     var fut = await server.socket.acceptAddr()
     asyncCheck processClient(fut.client, fut.address, callback)
+    #echo(f.isNil)
+    #echo(f.repr)
 
 proc close*(server: PAsyncHttpServer) =
   ## Terminates the async http server instance.
   server.socket.close()
 
 when isMainModule:
-  var server = newAsyncHttpServer()
-  proc cb(req: TRequest) {.async.} =
-    #echo(req.reqMethod, " ", req.url)
-    #echo(req.headers)
-    let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT",
-        "Content-type": "text/plain; charset=utf-8"}
-    await req.respond(Http200, "Hello World", headers.newStringTable())
-
-  asyncCheck server.serve(TPort(5555), cb)
-  runForever()
+  proc main =
+    var server = newAsyncHttpServer()
+    proc cb(req: TRequest) {.async.} =
+      #echo(req.reqMethod, " ", req.url)
+      #echo(req.headers)
+      let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT",
+          "Content-type": "text/plain; charset=utf-8"}
+      await req.respond(Http200, "Hello World", headers.newStringTable())
+
+    asyncCheck server.serve(TPort(5555), cb)
+    runForever()
+  main()
diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim
index c68ca4350..6b67bf4b5 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/pure/asyncio.nim
@@ -671,25 +671,26 @@ when isMainModule:
         testRead(s, 2)
     disp.register(client)
 
-  var d = newDispatcher()
-  
-  var s = AsyncSocket()
-  s.connect("amber.tenthbit.net", TPort(6667))
-  s.handleConnect = 
-    proc (s: PAsyncSocket) =
-      testConnect(s, 1)
-  s.handleRead = 
-    proc (s: PAsyncSocket) =
-      testRead(s, 1)
-  d.register(s)
-  
-  var server = AsyncSocket()
-  server.handleAccept =
-    proc (s: PAsyncSocket) = 
-      testAccept(s, d, 78)
-  server.bindAddr(TPort(5555))
-  server.listen()
-  d.register(server)
-  
-  while d.poll(-1): discard
+  proc main =
+    var d = newDispatcher()
+    
+    var s = AsyncSocket()
+    s.connect("amber.tenthbit.net", TPort(6667))
+    s.handleConnect = 
+      proc (s: PAsyncSocket) =
+        testConnect(s, 1)
+    s.handleRead = 
+      proc (s: PAsyncSocket) =
+        testRead(s, 1)
+    d.register(s)
+    
+    var server = AsyncSocket()
+    server.handleAccept =
+      proc (s: PAsyncSocket) = 
+        testAccept(s, d, 78)
+    server.bindAddr(TPort(5555))
+    server.listen()
+    d.register(server)
     
+    while d.poll(-1): discard
+  main()
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index 374ac77e3..5095d9461 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -36,9 +36,9 @@
 ##       let client = await server.accept()
 ##       clients.add client
 ##
-##       processClient(client)
+##       asyncCheck processClient(client)
 ##
-##   serve()
+##   asyncCheck serve()
 ##   runForever()
 ##
 ##
@@ -135,13 +135,13 @@ proc send*(socket: PAsyncSocket, data: string,
   assert socket != nil
   result = send(socket.fd.TAsyncFD, data, flags)
 
-proc acceptAddr*(socket: PAsyncSocket): 
+proc acceptAddr*(socket: PAsyncSocket, flags = {TSocketFlags.SafeDisconn}):
       PFuture[tuple[address: string, client: PAsyncSocket]] =
   ## Accepts a new connection. Returns a future containing the client socket
   ## corresponding to that connection and the remote address of the client.
   ## The future will complete when the connection is successfully accepted.
-  var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]()
-  var fut = acceptAddr(socket.fd.TAsyncFD)
+  var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]("asyncnet.acceptAddr")
+  var fut = acceptAddr(socket.fd.TAsyncFD, flags)
   fut.callback =
     proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
       assert future.finished
@@ -153,12 +153,13 @@ proc acceptAddr*(socket: PAsyncSocket):
         retFuture.complete(resultTup)
   return retFuture
 
-proc accept*(socket: PAsyncSocket): PFuture[PAsyncSocket] =
+proc accept*(socket: PAsyncSocket,
+    flags = {TSocketFlags.SafeDisconn}): PFuture[PAsyncSocket] =
   ## Accepts a new connection. Returns a future containing the client socket
   ## corresponding to that connection.
   ## The future will complete when the connection is successfully accepted.
-  var retFut = newFuture[PAsyncSocket]()
-  var fut = acceptAddr(socket)
+  var retFut = newFuture[PAsyncSocket]("asyncnet.accept")
+  var fut = acceptAddr(socket, flags)
   fut.callback =
     proc (future: PFuture[tuple[address: string, client: PAsyncSocket]]) =
       assert future.finished
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index c50c4165b..2629e9f40 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -409,6 +409,23 @@ template mapIt*(varSeq, pred: expr) =
     let it {.inject.} = varSeq[i]
     varSeq[i] = pred
 
+template newSeqWith*(len: int, init: expr): expr =
+  ## creates a new sequence, calling `init` to initialize each value. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var seq2D = newSeqWith(20, newSeq[bool](10))
+  ##   seq2D[0][0] = true
+  ##   seq2D[1][0] = true
+  ##   seq2D[0][1] = true
+  ##
+  ##   import math
+  ##   var seqRand = newSeqWith(20, random(10))
+  ##   echo seqRand
+  var result {.gensym.} = newSeq[type(init)](len)
+  for i in 0 .. <len:
+    result[i] = init
+  result
+
 when isMainModule:
   import strutils
   block: # concat test
@@ -557,4 +574,11 @@ when isMainModule:
     doAssert b.distribute(5, true)[4].len == 5
     doAssert b.distribute(5, false)[4].len == 2
 
+  block: # newSeqWith tests
+    var seq2D = newSeqWith(4, newSeq[bool](2))
+    seq2D[0][0] = true
+    seq2D[1][0] = true
+    seq2D[0][1] = true
+    doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
+
   echo "Finished doc tests"
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index 42cdc682f..ce901963e 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -128,7 +128,7 @@ proc mget*[A](s: var TSet[A], key: A): var A =
   ## for sharing.
   assert s.isValid, "The set needs to be initialized."
   var index = rawGet(s, key)
-  if index >= 0: result = t.data[index].key
+  if index >= 0: result = s.data[index].key
   else: raise newException(EInvalidKey, "key not found: " & $key)
 
 proc contains*[A](s: TSet[A], key: A): bool =
@@ -713,6 +713,24 @@ proc `$`*[A](s: TOrderedSet[A]): string =
   assert s.isValid, "The set needs to be initialized."
   dollarImpl()
 
+proc `==`*[A](s, t: TOrderedSet[A]): bool =
+  ## Equality for ordered sets.
+  if s.counter != t.counter: return false
+  var h = s.first
+  var g = s.first
+  var compared = 0
+  while h >= 0 and g >= 0:
+    var nxh = s.data[h].next
+    var nxg = t.data[g].next
+    if s.data[h].slot == seFilled and s.data[g].slot == seFilled:
+      if s.data[h].key == s.data[g].key:
+        inc compared
+      else:
+        return false
+    h = nxh
+    g = nxg
+  result = compared == s.counter
+
 proc testModule() =
   ## Internal micro test to validate docstrings and such.
   block isValidTest:
@@ -858,7 +876,7 @@ proc testModule() =
     var b = initOrderedSet[int]()
     for x in [2, 4, 5]: b.incl(x)
     assert($a == $b)
-    # assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
+    assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
 
   block initBlocks:
     var a: TOrderedSet[int]
diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim
index dfa819f64..8d7f28f8e 100644
--- a/lib/pure/concurrency/cpuinfo.nim
+++ b/lib/pure/concurrency/cpuinfo.nim
@@ -18,15 +18,24 @@ when not defined(windows):
 
 when defined(linux):
   import linux
+  
+when defined(freebsd) or defined(macosx):
+  {.emit:"#include <sys/types.h>".}
+
+when defined(openbsd) or defined(netbsd):
+  {.emit:"#include <sys/param.h>".}
 
 when defined(macosx) or defined(bsd):
+  # we HAVE to emit param.h before sysctl.h so we cannot use .header here
+  # either. The amount of archaic bullshit in Poonix based OSes is just insane.
+  {.emit:"#include <sys/sysctl.h>".}
   const
     CTL_HW = 6
     HW_AVAILCPU = 25
     HW_NCPU = 3
   proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer,
               a: var csize, b: pointer, c: int): cint {.
-             importc: "sysctl", header: "<sys/sysctl.h>".}
+              importc: "sysctl", nodecl.}
 
 proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
   ## returns the numer of the processors/cores the machine has.
diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim
index fd1041918..f46822d94 100644
--- a/lib/pure/concurrency/threadpool.nim
+++ b/lib/pure/concurrency/threadpool.nim
@@ -9,6 +9,9 @@
 
 ## Implements Nimrod's 'spawn'.
 
+when not compileOption("threads"):
+  {.error: "Threadpool requires --threads:on option.".}
+
 import cpuinfo, cpuload, locks
 
 {.push stackTrace:off.}
@@ -92,7 +95,7 @@ type
 
   FlowVarBase* = ref FlowVarBaseObj ## untyped base class for 'FlowVar[T]'
   FlowVarBaseObj = object of TObject
-    ready, usesCondVar: bool
+    ready, usesCondVar, awaited: bool
     cv: CondVar #\
     # for 'awaitAny' support
     ai: ptr AwaitInfo
@@ -126,15 +129,15 @@ type
 proc await*(fv: FlowVarBase) =
   ## waits until the value for the flowVar arrives. Usually it is not necessary
   ## to call this explicitly.
-  if fv.usesCondVar:
-    fv.usesCondVar = false
+  if fv.usesCondVar and not fv.awaited:
+    fv.awaited = true
     await(fv.cv)
     destroyCondVar(fv.cv)
 
 proc finished(fv: FlowVarBase) =
   doAssert fv.ai.isNil, "flowVar is still attached to an 'awaitAny'"
   # we have to protect against the rare cases where the owner of the flowVar
-  # simply disregards the flowVar and yet the "flowVarr" has not yet written
+  # simply disregards the flowVar and yet the "flowVar" has not yet written
   # anything to it:
   await(fv)
   if fv.data.isNil: return
@@ -207,6 +210,7 @@ proc `^`*[T](fv: FlowVar[T]): T =
   ## blocks until the value is available and then returns this value.
   await(fv)
   when T is string or T is seq:
+    # XXX closures? deepCopy?
     result = cast[T](fv.data)
   else:
     result = fv.blob
@@ -264,6 +268,10 @@ proc slave(w: ptr Worker) {.thread.} =
       w.shutdown = false
       atomicDec currentPoolSize
 
+var
+  workers: array[MaxThreadPoolSize, TThread[ptr Worker]]
+  workersData: array[MaxThreadPoolSize, Worker]
+
 proc setMinPoolSize*(size: range[1..MaxThreadPoolSize]) =
   ## sets the minimal thread pool size. The default value of this is 4.
   minPoolSize = size
@@ -272,10 +280,10 @@ proc setMaxPoolSize*(size: range[1..MaxThreadPoolSize]) =
   ## sets the minimal thread pool size. The default value of this
   ## is ``MaxThreadPoolSize``.
   maxPoolSize = size
-
-var
-  workers: array[MaxThreadPoolSize, TThread[ptr Worker]]
-  workersData: array[MaxThreadPoolSize, Worker]
+  if currentPoolSize > maxPoolSize:
+    for i in maxPoolSize..currentPoolSize-1:
+      let w = addr(workersData[i])
+      w.shutdown = true
 
 proc activateThread(i: int) {.noinline.} =
   workersData[i].taskArrived = createCondVar()
diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim
index d1cf36a87..49bf92980 100644
--- a/lib/pure/cookies.nim
+++ b/lib/pure/cookies.nim
@@ -28,8 +28,9 @@ proc parseCookies*(s: string): PStringTable =
     if s[i] == '\0': break
     inc(i) # skip ';'
 
-proc setCookie*(key, value: string, domain = "", path = "", 
-                expires = "", noName = false): string =
+proc setCookie*(key, value: string, domain = "", path = "",
+                expires = "", noName = false,
+                secure = false, httpOnly = false): string =
   ## Creates a command in the format of 
   ## ``Set-Cookie: key=value; Domain=...; ...``
   result = ""
@@ -38,16 +39,20 @@ proc setCookie*(key, value: string, domain = "", path = "",
   if domain != "": result.add("; Domain=" & domain)
   if path != "": result.add("; Path=" & path)
   if expires != "": result.add("; Expires=" & expires)
+  if secure: result.add("; secure")
+  if httpOnly: result.add("; HttpOnly")
 
 proc setCookie*(key, value: string, expires: TTimeInfo,
-                domain = "", path = "", noName = false): string =
+                domain = "", path = "", noName = false,
+                secure = false, httpOnly = false): string =
   ## Creates a command in the format of 
   ## ``Set-Cookie: key=value; Domain=...; ...``
   ##
   ## **Note:** UTC is assumed as the timezone for ``expires``.
   
   return setCookie(key, value, domain, path,
-            format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), noname)
+                   format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"),
+                   noname, secure, httpOnly)
   
 when isMainModule:
   var tim = TTime(int(getTime()) + 76 * (60 * 60 * 24))
@@ -55,5 +60,3 @@ when isMainModule:
   echo(setCookie("test", "value", tim.getGMTime()))
   
   echo parseCookies("uid=1; kp=2")
-  
-                
\ No newline at end of file
diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim
index 53f6688b9..e8d3f762e 100644
--- a/lib/pure/ftpclient.nim
+++ b/lib/pure/ftpclient.nim
@@ -10,6 +10,10 @@ include "system/inclrtl"
 
 import sockets, strutils, parseutils, times, os, asyncio
 
+from asyncnet import nil
+from rawsockets import nil
+from asyncdispatch import PFuture
+
 ## This module **partially** implements an FTP client as specified
 ## by `RFC 959 <http://tools.ietf.org/html/rfc959>`_. 
 ## 
@@ -34,34 +38,32 @@ import sockets, strutils, parseutils, times, os, asyncio
 
 
 type
-  TFTPClient* = object of TObject
-    case isAsync: bool
-    of false:
-      csock: TSocket # Command connection socket
-      dsock: TSocket # Data connection socket
-    else:
-      dummyA, dummyB: pointer # workaround a Nimrod API issue
-      asyncCSock: PAsyncSocket
-      asyncDSock: PAsyncSocket
+  PFtpBase*[SockType] = ref TFtpBase[SockType]
+  TFtpBase*[SockType] = object
+    csock*: SockType
+    dsock*: SockType
+    when SockType is asyncio.PAsyncSocket:
       handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent){.closure,gcsafe.}
       disp: PDispatcher
       asyncDSockID: PDelegate
-    user, pass: string
-    address: string
-    port: TPort
+    user*, pass*: string
+    address*: string
+    when SockType is asyncnet.PAsyncSocket:
+      port*: rawsockets.TPort
+    else:
+      port*: TPort
     
-    jobInProgress: bool
-    job: ref TFTPJob
+    jobInProgress*: bool
+    job*: PFTPJob[SockType]
 
-    dsockConnected: bool
-
-  PFTPClient* = ref TFTPClient
+    dsockConnected*: bool
 
   FTPJobType* = enum
     JRetrText, JRetr, JStore
 
-  TFTPJob = object
-    prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall, gcsafe.}
+  PFtpJob[T] = ref TFtpJob[T]
+  TFTPJob[T] = object
+    prc: proc (ftp: PFTPBase[T], async: bool): bool {.nimcall, gcsafe.}
     case typ*: FTPJobType
     of JRetrText:
       lines: string
@@ -75,8 +77,11 @@ type
       toStore: string # Data left to upload (Only used with async)
     else: nil
 
+  TFtpClient* = TFtpBase[TSocket]
+  PFtpClient* = ref TFTPClient
+
   PAsyncFTPClient* = ref TAsyncFTPClient ## Async alternative to TFTPClient.
-  TAsyncFTPClient* = object of TFTPClient
+  TAsyncFTPClient* = TFtpBase[asyncio.PAsyncSocket]
 
   FTPEventType* = enum
     EvTransferProgress, EvLines, EvRetr, EvStore
@@ -106,30 +111,30 @@ proc ftpClient*(address: string, port = TPort(21),
   result.address = address
   result.port = port
 
-  result.isAsync = false
   result.dsockConnected = false
   result.csock = socket()
   if result.csock == InvalidSocket: osError(osLastError())
 
-proc getDSock(ftp: PFTPClient): TSocket =
-  if ftp.isAsync: return ftp.asyncDSock else: return ftp.dsock
+proc getDSock[T](ftp: PFTPBase[T]): TSocket =
+  return ftp.dsock
 
-proc getCSock(ftp: PFTPClient): TSocket =
-  if ftp.isAsync: return ftp.asyncCSock else: return ftp.csock
+proc getCSock[T](ftp: PFTPBase[T]): TSocket =
+  return ftp.csock
 
 template blockingOperation(sock: TSocket, body: stmt) {.immediate.} =
-  if ftp.isAsync:
-    sock.setBlocking(true)
   body
-  if ftp.isAsync:
-    sock.setBlocking(false)
 
-proc expectReply(ftp: PFTPClient): TaintedString =
+template blockingOperation(sock: asyncio.PAsyncSocket, body: stmt) {.immediate.} =
+  sock.setBlocking(true)
+  body
+  sock.setBlocking(false)
+
+proc expectReply[T](ftp: PFtpBase[T]): TaintedString =
   result = TaintedString""
   blockingOperation(ftp.getCSock()):
     ftp.getCSock().readLine(result)
 
-proc send*(ftp: PFTPClient, m: string): TaintedString =
+proc send*[T](ftp: PFtpBase[T], m: string): TaintedString =
   ## Send a message to the server, and wait for a primary reply.
   ## ``\c\L`` is added for you.
   blockingOperation(ftp.getCSock()):
@@ -149,8 +154,8 @@ proc assertReply(received: TaintedString, expected: varargs[string]) =
                      "Expected reply '$1' got: $2" %
                      [expected.join("' or '"), received.string])
 
-proc createJob(ftp: PFTPClient,
-               prc: proc (ftp: PFTPClient, async: bool): bool {.
+proc createJob[T](ftp: PFtpBase[T],
+               prc: proc (ftp: PFtpBase[T], async: bool): bool {.
                           nimcall,gcsafe.},
                cmd: FTPJobType) =
   if ftp.jobInProgress:
@@ -165,7 +170,7 @@ proc createJob(ftp: PFTPClient,
   of JRetr, JStore:
     ftp.job.toStore = ""
 
-proc deleteJob(ftp: PFTPClient) =
+proc deleteJob[T](ftp: PFtpBase[T]) =
   assert ftp.jobInProgress
   ftp.jobInProgress = false
   case ftp.job.typ
@@ -173,12 +178,9 @@ proc deleteJob(ftp: PFTPClient) =
     ftp.job.lines = ""
   of JRetr, JStore:
     ftp.job.file.close()
-  if ftp.isAsync:
-    ftp.asyncDSock.close()
-  else:
-    ftp.dsock.close()
+  ftp.dsock.close()
 
-proc handleTask(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleTask(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   if ftp.jobInProgress:
     if ftp.job.typ in {JRetr, JStore}:
       if epochTime() - ftp.job.lastProgressReport >= 1.0:
@@ -193,12 +195,12 @@ proc handleTask(s: PAsyncSocket, ftp: PFTPClient) =
         ftp.job.oneSecond = 0
         ftp.handleEvent(PAsyncFTPClient(ftp), r)
 
-proc handleWrite(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleWrite(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   if ftp.jobInProgress:
     if ftp.job.typ == JStore:
       assert (not ftp.job.prc(ftp, true))
 
-proc handleConnect(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleConnect(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   ftp.dsockConnected = true
   assert(ftp.jobInProgress)
   if ftp.job.typ == JStore:
@@ -206,30 +208,32 @@ proc handleConnect(s: PAsyncSocket, ftp: PFTPClient) =
   else:
     s.delHandleWrite()
 
-proc handleRead(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   assert ftp.jobInProgress
   assert ftp.job.typ != JStore
   # This can never return true, because it shouldn't check for code 
   # 226 from csock.
   assert(not ftp.job.prc(ftp, true))
 
-proc pasv(ftp: PFTPClient) =
+proc pasv[T](ftp: PFtpBase[T]) =
   ## Negotiate a data connection.
-  if not ftp.isAsync:
+  when T is TSocket:
     ftp.dsock = socket()
     if ftp.dsock == InvalidSocket: osError(osLastError())
-  else:
-    ftp.asyncDSock = AsyncSocket()
-    ftp.asyncDSock.handleRead =
+  elif T is PAsyncSocket:
+    ftp.dsock = AsyncSocket()
+    ftp.dsock.handleRead =
       proc (s: PAsyncSocket) =
         handleRead(s, ftp)
-    ftp.asyncDSock.handleConnect =
+    ftp.dsock.handleConnect =
       proc (s: PAsyncSocket) =
         handleConnect(s, ftp)
-    ftp.asyncDSock.handleTask =
+    ftp.dsock.handleTask =
       proc (s: PAsyncSocket) =
         handleTask(s, ftp)
-    ftp.disp.register(ftp.asyncDSock)
+    ftp.disp.register(ftp.dsock)
+  else:
+    {.fatal: "Incorrect socket instantiation".}
   
   var pasvMsg = ftp.send("PASV").string.strip.TaintedString
   assertReply(pasvMsg, "227")
@@ -238,23 +242,24 @@ proc pasv(ftp: PFTPClient) =
   var ip = nums[0.. -3]
   var port = nums[-2.. -1]
   var properPort = port[0].parseInt()*256+port[1].parseInt()
-  if ftp.isAsync:
-    ftp.asyncDSock.connect(ip.join("."), TPort(properPort.toU16))
+  ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
+  when T is PAsyncSocket:
     ftp.dsockConnected = False
   else:
-    ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
     ftp.dsockConnected = True
 
 proc normalizePathSep(path: string): string =
   return replace(path, '\\', '/')
 
-proc connect*(ftp: PFTPClient) =
+proc connect*[T](ftp: PFtpBase[T]) =
   ## Connect to the FTP server specified by ``ftp``.
-  if ftp.isAsync:
-    blockingOperation(ftp.asyncCSock):
-      ftp.asyncCSock.connect(ftp.address, ftp.port)
-  else:
+  when T is PAsyncSocket:
+    blockingOperation(ftp.csock):
+      ftp.csock.connect(ftp.address, ftp.port)
+  elif T is TSocket:
     ftp.csock.connect(ftp.address, ftp.port)
+  else:
+    {.fatal: "Incorrect socket instantiation".}
 
   # TODO: Handle 120? or let user handle it.
   assertReply ftp.expectReply(), "220"
@@ -279,25 +284,27 @@ proc cdup*(ftp: PFTPClient) =
   ## Changes the current directory to the parent of the current directory.
   assertReply ftp.send("CDUP"), "200"
 
-proc getLines(ftp: PFTPClient, async: bool = false): bool =
+proc getLines[T](ftp: PFtpBase[T], async: bool = false): bool =
   ## Downloads text data in ASCII mode
   ## Returns true if the download is complete.
   ## It doesn't if `async` is true, because it doesn't check for 226 then.
   if ftp.dsockConnected:
     var r = TaintedString""
-    if ftp.isAsync:
+    when T is PAsyncSocket:
       if ftp.asyncDSock.readLine(r):
         if r.string == "":
           ftp.dsockConnected = false
         else:
           ftp.job.lines.add(r.string & "\n")
-    else:
+    elif T is TSocket:
       assert(not async)
       ftp.dsock.readLine(r)
       if r.string == "":
         ftp.dsockConnected = false
       else:
         ftp.job.lines.add(r.string & "\n")
+    else:
+      {.fatal: "Incorrect socket instantiation".}
   
   if not async:
     var readSocks: seq[TSocket] = @[ftp.getCSock()]
@@ -307,14 +314,14 @@ proc getLines(ftp: PFTPClient, async: bool = false): bool =
         assertReply ftp.expectReply(), "226"
         return true
 
-proc listDirs*(ftp: PFTPClient, dir: string = "",
+proc listDirs*[T](ftp: PFtpBase[T], dir: string = "",
                async = false): seq[string] =
   ## Returns a list of filenames in the given directory. If ``dir`` is "",
   ## the current directory is used. If ``async`` is true, this
   ## function will return immediately and it will be your job to
   ## use asyncio's ``poll`` to progress this operation.
 
-  ftp.createJob(getLines, JRetrText)
+  ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
 
   assertReply ftp.send("NLST " & dir.normalizePathSep), ["125", "150"]
@@ -384,12 +391,12 @@ proc chmod*(ftp: PFTPClient, path: string,
   assertReply ftp.send("SITE CHMOD " & perm &
                        " " & path.normalizePathSep), "200"
 
-proc list*(ftp: PFTPClient, dir: string = "", async = false): string =
+proc list*[T](ftp: PFtpBase[T], dir: string = "", async = false): string =
   ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current
   ## working directory. If ``async`` is true, this function will return
   ## immediately and it will be your job to call asyncio's 
   ## ``poll`` to progress this operation.
-  ftp.createJob(getLines, JRetrText)
+  ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
 
   assertReply(ftp.send("LIST" & " " & dir.normalizePathSep), ["125", "150"])
@@ -401,11 +408,11 @@ proc list*(ftp: PFTPClient, dir: string = "", async = false): string =
   else:
     return ""
 
-proc retrText*(ftp: PFTPClient, file: string, async = false): string =
+proc retrText*[T](ftp: PFtpBase[T], file: string, async = false): string =
   ## Retrieves ``file``. File must be ASCII text.
   ## If ``async`` is true, this function will return immediately and
   ## it will be your job to call asyncio's ``poll`` to progress this operation.
-  ftp.createJob(getLines, JRetrText)
+  ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
   assertReply ftp.send("RETR " & file.normalizePathSep), ["125", "150"]
   
@@ -416,15 +423,17 @@ proc retrText*(ftp: PFTPClient, file: string, async = false): string =
   else:
     return ""
 
-proc getFile(ftp: PFTPClient, async = false): bool =
+proc getFile[T](ftp: PFtpBase[T], async = false): bool =
   if ftp.dsockConnected:
     var r = "".TaintedString
     var bytesRead = 0
     var returned = false
     if async:
-      if not ftp.isAsync: raise newException(EFTP, "FTPClient must be async.")
-      bytesRead = ftp.AsyncDSock.recvAsync(r, BufferSize)
-      returned = bytesRead != -1
+      when T is TSocket:
+        raise newException(EFTP, "FTPClient must be async.")
+      else:
+        bytesRead = ftp.dsock.recvAsync(r, BufferSize)
+        returned = bytesRead != -1
     else: 
       bytesRead = getDSock(ftp).recv(r, BufferSize)
       returned = true
@@ -443,13 +452,13 @@ proc getFile(ftp: PFTPClient, async = false): bool =
         assertReply ftp.expectReply(), "226"
         return true
 
-proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) =
+proc retrFile*[T](ftp: PFtpBase[T], file, dest: string, async = false) =
   ## Downloads ``file`` and saves it to ``dest``. Usage of this function
   ## asynchronously is recommended to view the progress of the download.
   ## The ``EvRetr`` event is passed to the specified ``handleEvent`` function 
   ## when the download is finished, and the ``filename`` field will be equal
   ## to ``file``.
-  ftp.createJob(getFile, JRetr)
+  ftp.createJob(getFile[T], JRetr)
   ftp.job.file = open(dest, mode = fmWrite)
   ftp.pasv()
   var reply = ftp.send("RETR " & file.normalizePathSep)
@@ -468,11 +477,11 @@ proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) =
     while not ftp.job.prc(ftp, false): discard
     ftp.deleteJob()
 
-proc doUpload(ftp: PFTPClient, async = false): bool =
+proc doUpload[T](ftp: PFtpBase[T], async = false): bool =
   if ftp.dsockConnected:
     if ftp.job.toStore.len() > 0:
       assert(async)
-      let bytesSent = ftp.asyncDSock.sendAsync(ftp.job.toStore)
+      let bytesSent = ftp.dsock.sendAsync(ftp.job.toStore)
       if bytesSent == ftp.job.toStore.len:
         ftp.job.toStore = ""
       elif bytesSent != ftp.job.toStore.len and bytesSent != 0:
@@ -485,7 +494,7 @@ proc doUpload(ftp: PFTPClient, async = false): bool =
       setLen(s, len)
       if len == 0:
         # File finished uploading.
-        if ftp.isAsync: ftp.asyncDSock.close() else: ftp.dsock.close()
+        ftp.dsock.close()
         ftp.dsockConnected = false
   
         if not async:
@@ -496,7 +505,7 @@ proc doUpload(ftp: PFTPClient, async = false): bool =
       if not async:
         getDSock(ftp).send(s)
       else:
-        let bytesSent = ftp.asyncDSock.sendAsync(s)
+        let bytesSent = ftp.dsock.sendAsync(s)
         if bytesSent == 0:
           ftp.job.toStore.add(s)
         elif bytesSent != s.len:
@@ -506,14 +515,14 @@ proc doUpload(ftp: PFTPClient, async = false): bool =
       ftp.job.progress.inc(len)
       ftp.job.oneSecond.inc(len)
 
-proc store*(ftp: PFTPClient, file, dest: string, async = false) =
+proc store*[T](ftp: PFtpBase[T], file, dest: string, async = false) =
   ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this
   ## function asynchronously is recommended to view the progress of
   ## the download.
   ## The ``EvStore`` event is passed to the specified ``handleEvent`` function 
   ## when the upload is finished, and the ``filename`` field will be 
   ## equal to ``file``.
-  ftp.createJob(doUpload, JStore)
+  ftp.createJob(doUpload[T], JStore)
   ftp.job.file = open(file)
   ftp.job.total = ftp.job.file.getFileSize()
   ftp.job.lastProgressReport = epochTime()
@@ -526,16 +535,12 @@ proc store*(ftp: PFTPClient, file, dest: string, async = false) =
     while not ftp.job.prc(ftp, false): discard
     ftp.deleteJob()
 
-proc close*(ftp: PFTPClient) =
+proc close*[T](ftp: PFTPBase[T]) =
   ## Terminates the connection to the server.
   assertReply ftp.send("QUIT"), "221"
   if ftp.jobInProgress: ftp.deleteJob()
-  if ftp.isAsync:
-    ftp.asyncCSock.close()
-    ftp.asyncDSock.close()
-  else:
-    ftp.csock.close()
-    ftp.dsock.close()
+  ftp.csock.close()
+  ftp.dsock.close()
 
 proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   if ftp.jobInProgress:
@@ -572,66 +577,65 @@ proc asyncFTPClient*(address: string, port = TPort(21),
   dres.pass = pass
   dres.address = address
   dres.port = port
-  dres.isAsync = true
   dres.dsockConnected = false
   dres.handleEvent = handleEvent
-  dres.asyncCSock = AsyncSocket()
-  dres.asyncCSock.handleRead =
+  dres.csock = AsyncSocket()
+  dres.csock.handleRead =
     proc (s: PAsyncSocket) =
       csockHandleRead(s, dres)
   result = dres
 
 proc register*(d: PDispatcher, ftp: PAsyncFTPClient): PDelegate {.discardable.} =
   ## Registers ``ftp`` with dispatcher ``d``.
-  assert ftp.isAsync
   ftp.disp = d
-  return ftp.disp.register(ftp.asyncCSock)
+  return ftp.disp.register(ftp.csock)
 
 when isMainModule:
-  var d = newDispatcher()
-  let hev =
-    proc (ftp: PAsyncFTPClient, event: TFTPEvent) =
-      case event.typ
-      of EvStore:
-        echo("Upload finished!")
-        ftp.retrFile("payload.JPG", "payload2.JPG", async = true)
-      of EvTransferProgress:
-        var time: int64 = -1
-        if event.speed != 0:
-          time = (event.bytesTotal - event.bytesFinished) div event.speed
-        echo(event.currentJob)
-        echo(event.speed div 1000, " kb/s. - ",
-             event.bytesFinished, "/", event.bytesTotal,
-             " - ", time, " seconds")
-        echo(d.len)
-      of EvRetr:
-        echo("Download finished!")
-        ftp.close()
-        echo d.len
-      else: assert(false)
-  var ftp = asyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev)
-  
-  d.register(ftp)
-  d.len.echo()
-  ftp.connect()
-  echo "connected"
-  ftp.store("payload.JPG", "payload.JPG", async = true)
-  d.len.echo()
-  echo "uploading..."
-  while true:
-    if not d.poll(): break
-
+  proc main =
+    var d = newDispatcher()
+    let hev =
+      proc (ftp: PAsyncFTPClient, event: TFTPEvent) =
+        case event.typ
+        of EvStore:
+          echo("Upload finished!")
+          ftp.retrFile("payload.jpg", "payload2.jpg", async = true)
+        of EvTransferProgress:
+          var time: int64 = -1
+          if event.speed != 0:
+            time = (event.bytesTotal - event.bytesFinished) div event.speed
+          echo(event.currentJob)
+          echo(event.speed div 1000, " kb/s. - ",
+               event.bytesFinished, "/", event.bytesTotal,
+               " - ", time, " seconds")
+          echo(d.len)
+        of EvRetr:
+          echo("Download finished!")
+          ftp.close()
+          echo d.len
+        else: assert(false)
+    var ftp = asyncFTPClient("example.com", user = "foo", pass = "bar", handleEvent = hev)
+    
+    d.register(ftp)
+    d.len.echo()
+    ftp.connect()
+    echo "connected"
+    ftp.store("payload.jpg", "payload.jpg", async = true)
+    d.len.echo()
+    echo "uploading..."
+    while true:
+      if not d.poll(): break
+  main()
 
 when isMainModule and false:
-  var ftp = ftpClient("picheta.me", user = "asdasd", pass = "asfwq")
+  var ftp = ftpClient("example.com", user = "foo", pass = "bar")
   ftp.connect()
   echo ftp.pwd()
   echo ftp.list()
   echo("uploading")
-  ftp.store("payload.JPG", "payload.JPG", async = false)
+  ftp.store("payload.jpg", "payload.jpg", async = false)
 
   echo("Upload complete")
-  ftp.retrFile("payload.JPG", "payload2.JPG", async = false)
+  ftp.retrFile("payload.jpg", "payload2.jpg", async = false)
 
   echo("Download complete")
   sleep(5000)
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 9bacc80d6..4db6ac6ed 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -654,8 +654,7 @@ when isMainModule:
       resp = await client.request("http://nimrod-lang.org/download.html")
       echo("Got response: ", resp.status)
 
-    asyncCheck main()
-    runForever()
+    waitFor main()
 
   else:
     #downloadFile("http://force7.de/nimrod/index.html", "nimrodindex.html")
diff --git a/lib/pure/irc.nim b/lib/pure/irc.nim
deleted file mode 100644
index 49d9a9a34..000000000
--- a/lib/pure/irc.nim
+++ /dev/null
@@ -1,503 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2012 Dominik Picheta
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module implements an asynchronous IRC client.
-## 
-## Currently this module requires at least some knowledge of the IRC protocol.
-## It provides a function for sending raw messages to the IRC server, together
-## with some basic functions like sending a message to a channel. 
-## It automizes the process of keeping the connection alive, so you don't
-## need to reply to PING messages. In fact, the server is also PING'ed to check 
-## the amount of lag.
-##
-## .. code-block:: Nimrod
-##
-##   var client = irc("picheta.me", joinChans = @["#bots"])
-##   client.connect()
-##   while True:
-##     var event: TIRCEvent
-##     if client.poll(event):
-##       case event.typ
-##       of EvConnected: nil
-##       of EvDisconnected:
-##         client.reconnect()
-##       of EvMsg:
-##         # Write your message reading code here.
-## 
-## **Warning:** The API of this module is unstable, and therefore is subject
-## to change.
-
-include "system/inclrtl"
-
-import sockets, strutils, parseutils, times, asyncio, os
-
-type
-  TIRC* = object of TObject
-    address: string
-    port: TPort
-    nick, user, realname, serverPass: string
-    case isAsync: bool
-    of true:
-      handleEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure, gcsafe.}
-      asyncSock: PAsyncSocket
-      myDispatcher: PDispatcher
-    of false:
-      dummyA: pointer
-      dummyB: pointer # workaround a Nimrod API issue
-      dummyC: pointer
-      sock: TSocket
-    status: TInfo
-    lastPing: float
-    lastPong: float
-    lag: float
-    channelsToJoin: seq[string]
-    msgLimit: bool
-    messageBuffer: seq[tuple[timeToSend: float, m: string]]
-    lastReconnect: float
-
-  PIRC* = ref TIRC
-
-  PAsyncIRC* = ref TAsyncIRC
-  TAsyncIRC* = object of TIRC
-
-  TIRCMType* = enum
-    MUnknown,
-    MNumeric,
-    MPrivMsg,
-    MJoin,
-    MPart,
-    MMode,
-    MTopic,
-    MInvite,
-    MKick,
-    MQuit,
-    MNick,
-    MNotice,
-    MPing,
-    MPong,
-    MError
-  
-  TIRCEventType* = enum
-    EvMsg, EvConnected, EvDisconnected
-  TIRCEvent* = object ## IRC Event
-    case typ*: TIRCEventType
-    of EvConnected:
-      ## Connected to server.
-      ## Only occurs with AsyncIRC.
-      nil
-    of EvDisconnected: 
-      ## Disconnected from the server
-      nil
-    of EvMsg:              ## Message from the server
-      cmd*: TIRCMType      ## Command (e.g. PRIVMSG)
-      nick*, user*, host*, servername*: string
-      numeric*: string     ## Only applies to ``MNumeric``
-      params*: seq[string] ## Parameters of the IRC message
-      origin*: string      ## The channel/user that this msg originated from
-      raw*: string         ## Raw IRC message
-      timestamp*: TTime    ## UNIX epoch time the message was received
-  
-proc send*(irc: PIRC, message: string, sendImmediately = false) =
-  ## Sends ``message`` as a raw command. It adds ``\c\L`` for you.
-  var sendMsg = true
-  if irc.msgLimit and not sendImmediately:
-    var timeToSend = epochTime()
-    if irc.messageBuffer.len() >= 3:
-      timeToSend = (irc.messageBuffer[irc.messageBuffer.len()-1][0] + 2.0)
-
-    irc.messageBuffer.add((timeToSend, message))
-    sendMsg = false
-
-  if sendMsg:
-    try:
-      if irc.isAsync:
-        irc.asyncSock.send(message & "\c\L")
-      else:
-        irc.sock.send(message & "\c\L")
-    except EOS:
-      # Assuming disconnection of every EOS could be bad,
-      # but I can't exactly check for EBrokenPipe.
-      irc.status = SockClosed
-
-proc privmsg*(irc: PIRC, target, message: string) =
-  ## Sends ``message`` to ``target``. ``Target`` can be a channel, or a user.
-  irc.send("PRIVMSG $1 :$2" % [target, message])
-
-proc notice*(irc: PIRC, target, message: string) =
-  ## Sends ``notice`` to ``target``. ``Target`` can be a channel, or a user. 
-  irc.send("NOTICE $1 :$2" % [target, message])
-
-proc join*(irc: PIRC, channel: string, key = "") =
-  ## Joins ``channel``.
-  ## 
-  ## If key is not ``""``, then channel is assumed to be key protected and this
-  ## function will join the channel using ``key``.
-  if key == "":
-    irc.send("JOIN " & channel)
-  else:
-    irc.send("JOIN " & channel & " " & key)
-
-proc part*(irc: PIRC, channel, message: string) =
-  ## Leaves ``channel`` with ``message``.
-  irc.send("PART " & channel & " :" & message)
-
-proc close*(irc: PIRC) =
-  ## Closes connection to an IRC server.
-  ##
-  ## **Warning:** This procedure does not send a ``QUIT`` message to the server.
-  irc.status = SockClosed
-  if irc.isAsync:
-    irc.asyncSock.close()
-  else:
-    irc.sock.close()
-
-proc isNumber(s: string): bool =
-  ## Checks if `s` contains only numbers.
-  var i = 0
-  while s[i] in {'0'..'9'}: inc(i)
-  result = i == s.len and s.len > 0
-
-proc parseMessage(msg: string): TIRCEvent =
-  result.typ       = EvMsg
-  result.cmd       = MUnknown
-  result.raw       = msg
-  result.timestamp = times.getTime()
-  var i = 0
-  # Process the prefix
-  if msg[i] == ':':
-    inc(i) # Skip `:`
-    var nick = ""
-    i.inc msg.parseUntil(nick, {'!', ' '}, i)
-    result.nick = ""
-    result.serverName = ""
-    if msg[i] == '!':
-      result.nick = nick
-      inc(i) # Skip `!`
-      i.inc msg.parseUntil(result.user, {'@'}, i)
-      inc(i) # Skip `@`
-      i.inc msg.parseUntil(result.host, {' '}, i)
-      inc(i) # Skip ` `
-    else:
-      result.serverName = nick
-      inc(i) # Skip ` `
-  
-  # Process command
-  var cmd = ""
-  i.inc msg.parseUntil(cmd, {' '}, i)
-
-  if cmd.isNumber:
-    result.cmd = MNumeric
-    result.numeric = cmd
-  else:
-    case cmd
-    of "PRIVMSG": result.cmd = MPrivMsg
-    of "JOIN": result.cmd = MJoin
-    of "PART": result.cmd = MPart
-    of "PONG": result.cmd = MPong
-    of "PING": result.cmd = MPing
-    of "MODE": result.cmd = MMode
-    of "TOPIC": result.cmd = MTopic
-    of "INVITE": result.cmd = MInvite
-    of "KICK": result.cmd = MKick
-    of "QUIT": result.cmd = MQuit
-    of "NICK": result.cmd = MNick
-    of "NOTICE": result.cmd = MNotice
-    of "ERROR": result.cmd = MError
-    else: result.cmd = MUnknown
-  
-  # Don't skip space here. It is skipped in the following While loop.
-  
-  # Params
-  result.params = @[]
-  var param = ""
-  while msg[i] != '\0' and msg[i] != ':':
-    inc(i) # Skip ` `.
-    i.inc msg.parseUntil(param, {' ', ':', '\0'}, i)
-    if param != "":
-      result.params.add(param)
-      param.setlen(0)
-  
-  if msg[i] == ':':
-    inc(i) # Skip `:`.
-    result.params.add(msg[i..msg.len-1])
-
-proc connect*(irc: PIRC) =
-  ## Connects to an IRC server as specified by ``irc``.
-  assert(irc.address != "")
-  assert(irc.port != TPort(0))
-  
-  irc.sock.connect(irc.address, irc.port)
- 
-  irc.status = SockConnected
-  
-  # Greet the server :)
-  if irc.serverPass != "": irc.send("PASS " & irc.serverPass, true)
-  irc.send("NICK " & irc.nick, true)
-  irc.send("USER $1 * 0 :$2" % [irc.user, irc.realname], true)
-
-proc reconnect*(irc: PIRC, timeout = 5000) =
-  ## Reconnects to an IRC server.
-  ##
-  ## ``Timeout`` specifies the time to wait in miliseconds between multiple
-  ## consecutive reconnections.
-  ##
-  ## This should be used when an ``EvDisconnected`` event occurs.
-  let secSinceReconnect = int(epochTime() - irc.lastReconnect)
-  if secSinceReconnect < timeout:
-    sleep(timeout - secSinceReconnect)
-  irc.sock = socket()
-  if irc.sock == InvalidSocket: osError(osLastError())
-  irc.connect()
-  irc.lastReconnect = epochTime()
-
-proc irc*(address: string, port: TPort = 6667.TPort,
-         nick = "NimrodBot",
-         user = "NimrodBot",
-         realname = "NimrodBot", serverPass = "",
-         joinChans: seq[string] = @[],
-         msgLimit: bool = true): PIRC =
-  ## Creates a ``TIRC`` object.
-  new(result)
-  result.address = address
-  result.port = port
-  result.nick = nick
-  result.user = user
-  result.realname = realname
-  result.serverPass = serverPass
-  result.lastPing = epochTime()
-  result.lastPong = -1.0
-  result.lag = -1.0
-  result.channelsToJoin = joinChans
-  result.msgLimit = msgLimit
-  result.messageBuffer = @[]
-  result.status = SockIdle
-  result.sock = socket()
-  if result.sock == InvalidSocket: osError(osLastError())
-
-proc processLine(irc: PIRC, line: string): TIRCEvent =
-  if line.len == 0:
-    irc.close()
-    result.typ = EvDisconnected
-  else:
-    result = parseMessage(line)
-    # Get the origin
-    result.origin = result.params[0]
-    if result.origin == irc.nick and
-       result.nick != "": result.origin = result.nick
-
-    if result.cmd == MError:
-      irc.close()
-      result.typ = EvDisconnected
-      return
-
-    if result.cmd == MPing:
-      irc.send("PONG " & result.params[0])
-    if result.cmd == MPong:
-      irc.lag = epochTime() - parseFloat(result.params[result.params.high])
-      irc.lastPong = epochTime()
-    if result.cmd == MNumeric:
-      if result.numeric == "001":
-        # Check the nickname.
-        if irc.nick != result.params[0]:
-          assert ' ' notin result.params[0]
-          irc.nick = result.params[0]
-        for chan in items(irc.channelsToJoin):
-          irc.join(chan)
-    if result.cmd == MNick:
-      if result.nick == irc.nick:
-        irc.nick = result.params[0]
-    
-proc processOther(irc: PIRC, ev: var TIRCEvent): bool =
-  result = false
-  if epochTime() - irc.lastPing >= 20.0:
-    irc.lastPing = epochTime()
-    irc.send("PING :" & formatFloat(irc.lastPing), true)
-
-  if epochTime() - irc.lastPong >= 120.0 and irc.lastPong != -1.0:
-    irc.close()
-    ev.typ = EvDisconnected # TODO: EvTimeout?
-    return true
-  
-  for i in 0..irc.messageBuffer.len-1:
-    if epochTime() >= irc.messageBuffer[0][0]:
-      irc.send(irc.messageBuffer[0].m, true)
-      irc.messageBuffer.delete(0)
-    else:
-      break # messageBuffer is guaranteed to be from the quickest to the
-            # later-est.
-
-proc poll*(irc: PIRC, ev: var TIRCEvent,
-           timeout: int = 500): bool =
-  ## This function parses a single message from the IRC server and returns 
-  ## a TIRCEvent.
-  ##
-  ## This function should be called often as it also handles pinging
-  ## the server.
-  ##
-  ## This function provides a somewhat asynchronous IRC implementation, although
-  ## it should only be used for simple things for example an IRC bot which does
-  ## not need to be running many time critical tasks in the background. If you
-  ## require this, use the asyncio implementation.
-  
-  if not (irc.status == SockConnected):
-    # Do not close the socket here, it is already closed!
-    ev.typ = EvDisconnected
-  var line = TaintedString""
-  var socks = @[irc.sock]
-  var ret = socks.select(timeout)
-  if ret == -1: osError(osLastError())
-  if socks.len() != 0 and ret != 0:
-    irc.sock.readLine(line)
-    ev = irc.processLine(line.string)
-    result = true
-
-  if processOther(irc, ev): result = true
-
-proc getLag*(irc: PIRC): float =
-  ## Returns the latency between this client and the IRC server in seconds.
-  ## 
-  ## If latency is unknown, returns -1.0.
-  return irc.lag
-
-proc isConnected*(irc: PIRC): bool =
-  ## Returns whether this IRC client is connected to an IRC server.
-  return irc.status == SockConnected
-
-proc getNick*(irc: PIRC): string =
-  ## Returns the current nickname of the client.
-  return irc.nick
-
-# -- Asyncio dispatcher
-
-proc handleConnect(s: PAsyncSocket, irc: PAsyncIRC) =  
-  # Greet the server :)
-  if irc.serverPass != "": irc.send("PASS " & irc.serverPass, true)
-  irc.send("NICK " & irc.nick, true)
-  irc.send("USER $1 * 0 :$2" % [irc.user, irc.realname], true)
-  irc.status = SockConnected
-  
-  var ev: TIRCEvent
-  ev.typ = EvConnected
-  irc.handleEvent(irc, ev)
-
-proc handleRead(s: PAsyncSocket, irc: PAsyncIRC) =
-  var line = "".TaintedString
-  var ret = s.readLine(line)
-  if ret:
-    if line == "":
-      var ev: TIRCEvent
-      irc.close()
-      ev.typ = EvDisconnected
-      irc.handleEvent(irc, ev)
-    else:
-      var ev = irc.processLine(line.string)
-      irc.handleEvent(irc, ev)
-  
-proc handleTask(s: PAsyncSocket, irc: PAsyncIRC) =
-  var ev: TIRCEvent
-  if irc.processOther(ev):
-    irc.handleEvent(irc, ev)
-
-proc register*(d: PDispatcher, irc: PAsyncIRC) =
-  ## Registers ``irc`` with dispatcher ``d``.
-  irc.asyncSock.handleConnect =
-    proc (s: PAsyncSocket) =
-      handleConnect(s, irc)
-  irc.asyncSock.handleRead =
-    proc (s: PAsyncSocket) =
-      handleRead(s, irc)
-  irc.asyncSock.handleTask =
-    proc (s: PAsyncSocket) =
-      handleTask(s, irc)
-  d.register(irc.asyncSock)
-  irc.myDispatcher = d
-
-proc connect*(irc: PAsyncIRC) =
-  ## Equivalent of connect for ``TIRC`` but specifically created for asyncio.
-  assert(irc.address != "")
-  assert(irc.port != TPort(0))
-  
-  irc.asyncSock.connect(irc.address, irc.port)
-
-proc reconnect*(irc: PAsyncIRC, timeout = 5000) =
-  ## Reconnects to an IRC server.
-  ##
-  ## ``Timeout`` specifies the time to wait in miliseconds between multiple
-  ## consecutive reconnections.
-  ##
-  ## This should be used when an ``EvDisconnected`` event occurs.
-  ##
-  ## When successfully reconnected an ``EvConnected`` event will occur.
-  let secSinceReconnect = int(epochTime() - irc.lastReconnect)
-  if secSinceReconnect < timeout:
-    sleep(timeout - secSinceReconnect)
-  irc.asyncSock = AsyncSocket()
-  irc.myDispatcher.register(irc)
-  irc.connect()
-  irc.lastReconnect = epochTime()
-
-proc asyncIRC*(address: string, port: TPort = 6667.TPort,
-              nick = "NimrodBot",
-              user = "NimrodBot",
-              realname = "NimrodBot", serverPass = "",
-              joinChans: seq[string] = @[],
-              msgLimit: bool = true,
-              ircEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure,gcsafe.}
-              ): PAsyncIRC =
-  ## Use this function if you want to use asyncio's dispatcher.
-  ## 
-  ## **Note:** Do **NOT** use this if you're writing a simple IRC bot which only
-  ## requires one task to be run, i.e. this should not be used if you want a
-  ## synchronous IRC client implementation, use ``irc`` for that.
-  
-  new(result)
-  result.isAsync = true
-  result.address = address
-  result.port = port
-  result.nick = nick
-  result.user = user
-  result.realname = realname
-  result.serverPass = serverPass
-  result.lastPing = epochTime()
-  result.lastPong = -1.0
-  result.lag = -1.0
-  result.channelsToJoin = joinChans
-  result.msgLimit = msgLimit
-  result.messageBuffer = @[]
-  result.handleEvent = ircEvent
-  result.asyncSock = AsyncSocket()
-  
-when isMainModule:
-  #var m = parseMessage("ERROR :Closing Link: dom96.co.cc (Ping timeout: 252 seconds)")
-  #echo(repr(m))
-
-
-  
-  var client = irc("amber.tenthbit.net", nick="TestBot1234",
-                   joinChans = @["#flood"])
-  client.connect()
-  while true:
-    var event: TIRCEvent
-    if client.poll(event):
-      case event.typ
-      of EvConnected:
-        discard
-      of EvDisconnected:
-        break
-      of EvMsg:
-        if event.cmd == MPrivMsg:
-          var msg = event.params[event.params.high]
-          if msg == "|test": client.privmsg(event.origin, "hello")
-          if msg == "|excessFlood":
-            for i in 0..10:
-              client.privmsg(event.origin, "TEST" & $i)
-
-        #echo( repr(event) )
-      #echo("Lag: ", formatFloat(client.getLag()))
-  
-    
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 116671874..97c7b0e05 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -208,7 +208,7 @@ when not defined(JS):
 
   proc randomize(seed: int) =
     srand(cint(seed))
-    when defined(srand48): srand48(seed)
+    when declared(srand48): srand48(seed)
   proc random(max: int): int =
     result = int(rand()) mod max
 
@@ -268,8 +268,13 @@ proc `mod`*(x, y: float): float =
   result = if y == 0.0: x else: x - y * (x/y).floor
 
 proc random*[T](x: TSlice[T]): T =
+  ## For a slice `a .. b` returns a value in the range `a .. b-1`.
   result = random(x.b - x.a) + x.a
-  
+
+proc random[T](a: openarray[T]): T =
+  ## returns a random element from the openarray `a`.
+  result = a[random(a.low..a.len)]
+
 type
   TRunningStat* {.pure,final.} = object  ## an accumulator for statistical data
     n*: int                              ## number of pushed data
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 31fefc6c8..ffeb0beff 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -54,7 +54,7 @@ proc mapMem*(m: var TMemFile, mode: TFileMode = fmRead,
       nil,
       mappedSize,
       if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
-      if readonly: MAP_PRIVATE else: MAP_SHARED,
+      if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE),
       m.handle, offset)
     if result == cast[pointer](MAP_FAILED):
       osError(osLastError())
@@ -207,7 +207,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
       nil,
       result.size,
       if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
-      if readonly: MAP_PRIVATE else: MAP_SHARED,
+      if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE),
       result.handle,
       offset)
 
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index ddc2bbe2d..696527467 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -11,292 +11,10 @@
 
 {.deadCodeElim: on.}
 import rawsockets, os, strutils, unsigned, parseutils, times
-export TPort, `$`
+export TPort, `$`, `==`
 
 const useWinVersion = defined(Windows) or defined(nimdoc)
 
-type
-  IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address
-    IPv6, ## IPv6 address
-    IPv4  ## IPv4 address
-
-  TIpAddress* = object ## stores an arbitrary IP address    
-    case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6)
-    of IpAddressFamily.IPv6:
-      address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in
-                                       ## case of IPv6
-    of IpAddressFamily.IPv4:
-      address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
-                                      ## case of IPv4
-
-proc IPv4_any*(): TIpAddress =
-  ## Returns the IPv4 any address, which can be used to listen on all available
-  ## network adapters
-  result = TIpAddress(
-    family: IpAddressFamily.IPv4,
-    address_v4: [0'u8, 0, 0, 0])
-
-proc IPv4_loopback*(): TIpAddress =
-  ## Returns the IPv4 loopback address (127.0.0.1)
-  result = TIpAddress(
-    family: IpAddressFamily.IPv4,
-    address_v4: [127'u8, 0, 0, 1])
-
-proc IPv4_broadcast*(): TIpAddress =
-  ## Returns the IPv4 broadcast address (255.255.255.255)
-  result = TIpAddress(
-    family: IpAddressFamily.IPv4,
-    address_v4: [255'u8, 255, 255, 255])
-
-proc IPv6_any*(): TIpAddress =
-  ## Returns the IPv6 any address (::0), which can be used
-  ## to listen on all available network adapters 
-  result = TIpAddress(
-    family: IpAddressFamily.IPv6,
-    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
-
-proc IPv6_loopback*(): TIpAddress =
-  ## Returns the IPv6 loopback address (::1)
-  result = TIpAddress(
-    family: IpAddressFamily.IPv6,
-    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
-
-proc `==`*(lhs, rhs: TIpAddress): bool =
-  ## Compares two IpAddresses for Equality. Returns two if the addresses are equal
-  if lhs.family != rhs.family: return false
-  if lhs.family == IpAddressFamily.IPv4:
-    for i in low(lhs.address_v4) .. high(lhs.address_v4):
-      if lhs.address_v4[i] != rhs.address_v4[i]: return false
-  else: # IPv6
-    for i in low(lhs.address_v6) .. high(lhs.address_v6):
-      if lhs.address_v6[i] != rhs.address_v6[i]: return false
-  return true
-
-proc `$`*(address: TIpAddress): string =
-  ## Converts an TIpAddress into the textual representation
-  result = ""
-  case address.family
-  of IpAddressFamily.IPv4:
-    for i in 0 .. 3:
-      if i != 0:
-        result.add('.')
-      result.add($address.address_v4[i])
-  of IpAddressFamily.IPv6:
-    var
-      currentZeroStart = -1
-      currentZeroCount = 0
-      biggestZeroStart = -1
-      biggestZeroCount = 0
-    # Look for the largest block of zeros
-    for i in 0..7:
-      var isZero = address.address_v6[i*2] == 0 and address.address_v6[i*2+1] == 0
-      if isZero:
-        if currentZeroStart == -1:
-          currentZeroStart = i
-          currentZeroCount = 1
-        else:
-          currentZeroCount.inc()
-        if currentZeroCount > biggestZeroCount:
-          biggestZeroCount = currentZeroCount
-          biggestZeroStart = currentZeroStart
-      else:
-        currentZeroStart = -1
-
-    if biggestZeroCount == 8: # Special case ::0
-      result.add("::")
-    else: # Print address
-      var printedLastGroup = false
-      for i in 0..7:
-        var word:uint16 = (cast[uint16](address.address_v6[i*2])) shl 8
-        word = word or cast[uint16](address.address_v6[i*2+1])
-
-        if biggestZeroCount != 0 and # Check if group is in skip group
-          (i >= biggestZeroStart and i < (biggestZeroStart + biggestZeroCount)):
-          if i == biggestZeroStart: # skip start
-            result.add("::")
-          printedLastGroup = false
-        else:
-          if printedLastGroup:
-            result.add(':')
-          var
-            afterLeadingZeros = false
-            mask = 0xF000'u16
-          for j in 0'u16..3'u16:
-            var val = (mask and word) shr (4'u16*(3'u16-j))
-            if val != 0 or afterLeadingZeros:
-              if val < 0xA:
-                result.add(chr(uint16(ord('0'))+val))
-              else: # val >= 0xA
-                result.add(chr(uint16(ord('a'))+val-0xA))
-              afterLeadingZeros = true
-            mask = mask shr 4
-          printedLastGroup = true
-
-proc parseIPv4Address(address_str: string): TIpAddress =
-  ## Parses IPv4 adresses
-  ## Raises EInvalidValue on errors
-  var
-    byteCount = 0
-    currentByte:uint16 = 0
-    seperatorValid = false
-
-  result.family = IpAddressFamily.IPv4
-
-  for i in 0 .. high(address_str):
-    if address_str[i] in strutils.Digits: # Character is a number
-      currentByte = currentByte * 10 +
-        cast[uint16](ord(address_str[i]) - ord('0'))
-      if currentByte > 255'u16:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Value is out of range")
-      seperatorValid = true
-    elif address_str[i] == '.': # IPv4 address separator
-      if not seperatorValid or byteCount >= 3:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. The address consists of too many groups")
-      result.address_v4[byteCount] = cast[uint8](currentByte)
-      currentByte = 0
-      byteCount.inc
-      seperatorValid = false
-    else:
-      raise newException(EInvalidValue,
-        "Invalid IP Address. Address contains an invalid character")
-
-  if byteCount != 3 or not seperatorValid:
-    raise newException(EInvalidValue, "Invalid IP Address")
-  result.address_v4[byteCount] = cast[uint8](currentByte)
-
-proc parseIPv6Address(address_str: string): TIpAddress =
-  ## Parses IPv6 adresses
-  ## Raises EInvalidValue on errors
-  result.family = IpAddressFamily.IPv6
-  if address_str.len < 2:
-    raise newException(EInvalidValue, "Invalid IP Address")
-
-  var
-    groupCount = 0
-    currentGroupStart = 0
-    currentShort:uint32 = 0
-    seperatorValid = true
-    dualColonGroup = -1
-    lastWasColon = false
-    v4StartPos = -1
-    byteCount = 0
-
-  for i,c in address_str:
-    if c == ':':
-      if not seperatorValid:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Address contains an invalid seperator")
-      if lastWasColon:        
-        if dualColonGroup != -1:
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Address contains more than one \"::\" seperator")
-        dualColonGroup = groupCount
-        seperatorValid = false
-      elif i != 0 and i != high(address_str):
-        if groupCount >= 8:
-          raise newException(EInvalidValue,
-            "Invalid IP Address. The address consists of too many groups")
-        result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
-        result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
-        currentShort = 0
-        groupCount.inc()        
-        if dualColonGroup != -1: seperatorValid = false
-      elif i == 0: # only valid if address starts with ::
-        if address_str[1] != ':':
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Address may not start with \":\"")
-      else: # i == high(address_str) - only valid if address ends with ::
-        if address_str[high(address_str)-1] != ':': 
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Address may not end with \":\"")
-      lastWasColon = true
-      currentGroupStart = i + 1
-    elif c == '.': # Switch to parse IPv4 mode
-      if i < 3 or not seperatorValid or groupCount >= 7:
-        raise newException(EInvalidValue, "Invalid IP Address")
-      v4StartPos = currentGroupStart
-      currentShort = 0
-      seperatorValid = false
-      break
-    elif c in strutils.HexDigits:
-      if c in strutils.Digits: # Normal digit
-        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('0'))
-      elif c >= 'a' and c <= 'f': # Lower case hex
-        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10
-      else: # Upper case hex
-        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10
-      if currentShort > 65535'u32:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Value is out of range")
-      lastWasColon = false
-      seperatorValid = true
-    else:
-      raise newException(EInvalidValue,
-        "Invalid IP Address. Address contains an invalid character")
-
-
-  if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff
-    if seperatorValid: # Copy remaining data
-      if groupCount >= 8:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. The address consists of too many groups")
-      result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
-      result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
-      groupCount.inc()
-  else: # Must parse IPv4 address
-    for i,c in address_str[v4StartPos..high(address_str)]:
-      if c in strutils.Digits: # Character is a number
-        currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0'))
-        if currentShort > 255'u32:
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Value is out of range")
-        seperatorValid = true
-      elif c == '.': # IPv4 address separator
-        if not seperatorValid or byteCount >= 3:
-          raise newException(EInvalidValue, "Invalid IP Address")
-        result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
-        currentShort = 0
-        byteCount.inc()
-        seperatorValid = false
-      else: # Invalid character
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Address contains an invalid character")
-
-    if byteCount != 3 or not seperatorValid:
-      raise newException(EInvalidValue, "Invalid IP Address")
-    result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
-    groupCount += 2
-
-  # Shift and fill zeros in case of ::
-  if groupCount > 8:
-    raise newException(EInvalidValue,
-      "Invalid IP Address. The address consists of too many groups")
-  elif groupCount < 8: # must fill
-    if dualColonGroup == -1:
-      raise newException(EInvalidValue,
-        "Invalid IP Address. The address consists of too few groups")
-    var toFill = 8 - groupCount # The number of groups to fill
-    var toShift = groupCount - dualColonGroup # Nr of known groups after ::
-    for i in 0..2*toShift-1: # shift
-      result.address_v6[15-i] = result.address_v6[groupCount*2-i-1]
-    for i in 0..2*toFill-1: # fill with 0s
-      result.address_v6[dualColonGroup*2+i] = 0
-  elif dualColonGroup != -1:
-    raise newException(EInvalidValue,
-      "Invalid IP Address. The address consists of too many groups")
-
-proc parseIpAddress*(address_str: string): TIpAddress =
-  ## Parses an IP address
-  ## Raises EInvalidValue on error
-  if address_str == nil:
-    raise newException(EInvalidValue, "IP Address string is nil")
-  if address_str.contains(':'):
-    return parseIPv6Address(address_str)
-  else:
-    return parseIPv4Address(address_str)
-
 when defined(ssl):
   import openssl
 
@@ -361,7 +79,7 @@ proc isDisconnectionError*(flags: set[TSocketFlags],
   when useWinVersion:
     TSocketFlags.SafeDisconn in flags and
       lastError.int32 in {WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
-                          WSAEDISCON}
+                          WSAEDISCON, ERROR_NETNAME_DELETED}
   else:
     TSocketFlags.SafeDisconn in flags and
       lastError.int32 in {ECONNRESET, EPIPE, ENETRESET} 
@@ -569,8 +287,8 @@ proc bindAddr*(socket: PSocket, port = TPort(0), address = "") {.
       osError(osLastError())
     dealloc(aiList)
 
-proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
-  tags: [FReadIO].} =
+proc acceptAddr*(server: PSocket, client: var PSocket, address: var string,
+                 flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} =
   ## Blocks until a connection is being made from a client. When a connection
   ## is made sets ``client`` to the client socket and ``address`` to the address
   ## of the connecting client.
@@ -581,6 +299,11 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
   ##
   ## **Note**: ``client`` must be initialised (with ``new``), this function 
   ## makes no effort to initialise the ``client`` variable.
+  ##
+  ## The ``accept`` call may result in an error if the connecting socket
+  ## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
+  ## flag is specified then this error will not be raised and instead
+  ## accept will be called again.
   assert(client != nil)
   var sockAddress: Tsockaddr_in
   var addrLen = sizeof(sockAddress).TSocklen
@@ -589,6 +312,8 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
   
   if sock == osInvalidSocket:
     let err = osLastError()
+    if flags.isDisconnectionError(err):
+      acceptAddr(server, client, address, flags)
     osError(err)
   else:
     client.fd = sock
@@ -658,15 +383,20 @@ when false: #defined(ssl):
       acceptAddrPlain(AcceptNoClient, AcceptSuccess):
         doHandshake()
 
-proc accept*(server: PSocket, client: var PSocket) {.tags: [FReadIO].} =
+proc accept*(server: PSocket, client: var PSocket,
+             flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} =
   ## Equivalent to ``acceptAddr`` but doesn't return the address, only the
   ## socket.
   ## 
   ## **Note**: ``client`` must be initialised (with ``new``), this function
   ## makes no effort to initialise the ``client`` variable.
-  
+  ##
+  ## The ``accept`` call may result in an error if the connecting socket
+  ## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
+  ## flag is specified then this error will not be raised and instead
+  ## accept will be called again.
   var addrDummy = ""
-  acceptAddr(server, client, addrDummy)
+  acceptAddr(server, client, addrDummy, flags)
 
 proc close*(socket: PSocket) =
   ## Closes a socket.
@@ -1173,3 +903,285 @@ proc isSSL*(socket: PSocket): bool = return socket.isSSL
 
 proc getFD*(socket: PSocket): TSocketHandle = return socket.fd
   ## Returns the socket's file descriptor
+
+type
+  IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address
+    IPv6, ## IPv6 address
+    IPv4  ## IPv4 address
+
+  TIpAddress* = object ## stores an arbitrary IP address    
+    case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6)
+    of IpAddressFamily.IPv6:
+      address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in
+                                       ## case of IPv6
+    of IpAddressFamily.IPv4:
+      address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
+                                      ## case of IPv4
+
+proc IPv4_any*(): TIpAddress =
+  ## Returns the IPv4 any address, which can be used to listen on all available
+  ## network adapters
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [0'u8, 0, 0, 0])
+
+proc IPv4_loopback*(): TIpAddress =
+  ## Returns the IPv4 loopback address (127.0.0.1)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [127'u8, 0, 0, 1])
+
+proc IPv4_broadcast*(): TIpAddress =
+  ## Returns the IPv4 broadcast address (255.255.255.255)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [255'u8, 255, 255, 255])
+
+proc IPv6_any*(): TIpAddress =
+  ## Returns the IPv6 any address (::0), which can be used
+  ## to listen on all available network adapters 
+  result = TIpAddress(
+    family: IpAddressFamily.IPv6,
+    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+
+proc IPv6_loopback*(): TIpAddress =
+  ## Returns the IPv6 loopback address (::1)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv6,
+    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
+
+proc `==`*(lhs, rhs: TIpAddress): bool =
+  ## Compares two IpAddresses for Equality. Returns two if the addresses are equal
+  if lhs.family != rhs.family: return false
+  if lhs.family == IpAddressFamily.IPv4:
+    for i in low(lhs.address_v4) .. high(lhs.address_v4):
+      if lhs.address_v4[i] != rhs.address_v4[i]: return false
+  else: # IPv6
+    for i in low(lhs.address_v6) .. high(lhs.address_v6):
+      if lhs.address_v6[i] != rhs.address_v6[i]: return false
+  return true
+
+proc `$`*(address: TIpAddress): string =
+  ## Converts an TIpAddress into the textual representation
+  result = ""
+  case address.family
+  of IpAddressFamily.IPv4:
+    for i in 0 .. 3:
+      if i != 0:
+        result.add('.')
+      result.add($address.address_v4[i])
+  of IpAddressFamily.IPv6:
+    var
+      currentZeroStart = -1
+      currentZeroCount = 0
+      biggestZeroStart = -1
+      biggestZeroCount = 0
+    # Look for the largest block of zeros
+    for i in 0..7:
+      var isZero = address.address_v6[i*2] == 0 and address.address_v6[i*2+1] == 0
+      if isZero:
+        if currentZeroStart == -1:
+          currentZeroStart = i
+          currentZeroCount = 1
+        else:
+          currentZeroCount.inc()
+        if currentZeroCount > biggestZeroCount:
+          biggestZeroCount = currentZeroCount
+          biggestZeroStart = currentZeroStart
+      else:
+        currentZeroStart = -1
+
+    if biggestZeroCount == 8: # Special case ::0
+      result.add("::")
+    else: # Print address
+      var printedLastGroup = false
+      for i in 0..7:
+        var word:uint16 = (cast[uint16](address.address_v6[i*2])) shl 8
+        word = word or cast[uint16](address.address_v6[i*2+1])
+
+        if biggestZeroCount != 0 and # Check if group is in skip group
+          (i >= biggestZeroStart and i < (biggestZeroStart + biggestZeroCount)):
+          if i == biggestZeroStart: # skip start
+            result.add("::")
+          printedLastGroup = false
+        else:
+          if printedLastGroup:
+            result.add(':')
+          var
+            afterLeadingZeros = false
+            mask = 0xF000'u16
+          for j in 0'u16..3'u16:
+            var val = (mask and word) shr (4'u16*(3'u16-j))
+            if val != 0 or afterLeadingZeros:
+              if val < 0xA:
+                result.add(chr(uint16(ord('0'))+val))
+              else: # val >= 0xA
+                result.add(chr(uint16(ord('a'))+val-0xA))
+              afterLeadingZeros = true
+            mask = mask shr 4
+          printedLastGroup = true
+
+proc parseIPv4Address(address_str: string): TIpAddress =
+  ## Parses IPv4 adresses
+  ## Raises EInvalidValue on errors
+  var
+    byteCount = 0
+    currentByte:uint16 = 0
+    seperatorValid = false
+
+  result.family = IpAddressFamily.IPv4
+
+  for i in 0 .. high(address_str):
+    if address_str[i] in strutils.Digits: # Character is a number
+      currentByte = currentByte * 10 +
+        cast[uint16](ord(address_str[i]) - ord('0'))
+      if currentByte > 255'u16:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Value is out of range")
+      seperatorValid = true
+    elif address_str[i] == '.': # IPv4 address separator
+      if not seperatorValid or byteCount >= 3:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. The address consists of too many groups")
+      result.address_v4[byteCount] = cast[uint8](currentByte)
+      currentByte = 0
+      byteCount.inc
+      seperatorValid = false
+    else:
+      raise newException(EInvalidValue,
+        "Invalid IP Address. Address contains an invalid character")
+
+  if byteCount != 3 or not seperatorValid:
+    raise newException(EInvalidValue, "Invalid IP Address")
+  result.address_v4[byteCount] = cast[uint8](currentByte)
+
+proc parseIPv6Address(address_str: string): TIpAddress =
+  ## Parses IPv6 adresses
+  ## Raises EInvalidValue on errors
+  result.family = IpAddressFamily.IPv6
+  if address_str.len < 2:
+    raise newException(EInvalidValue, "Invalid IP Address")
+
+  var
+    groupCount = 0
+    currentGroupStart = 0
+    currentShort:uint32 = 0
+    seperatorValid = true
+    dualColonGroup = -1
+    lastWasColon = false
+    v4StartPos = -1
+    byteCount = 0
+
+  for i,c in address_str:
+    if c == ':':
+      if not seperatorValid:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Address contains an invalid seperator")
+      if lastWasColon:        
+        if dualColonGroup != -1:
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Address contains more than one \"::\" seperator")
+        dualColonGroup = groupCount
+        seperatorValid = false
+      elif i != 0 and i != high(address_str):
+        if groupCount >= 8:
+          raise newException(EInvalidValue,
+            "Invalid IP Address. The address consists of too many groups")
+        result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
+        result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
+        currentShort = 0
+        groupCount.inc()        
+        if dualColonGroup != -1: seperatorValid = false
+      elif i == 0: # only valid if address starts with ::
+        if address_str[1] != ':':
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Address may not start with \":\"")
+      else: # i == high(address_str) - only valid if address ends with ::
+        if address_str[high(address_str)-1] != ':': 
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Address may not end with \":\"")
+      lastWasColon = true
+      currentGroupStart = i + 1
+    elif c == '.': # Switch to parse IPv4 mode
+      if i < 3 or not seperatorValid or groupCount >= 7:
+        raise newException(EInvalidValue, "Invalid IP Address")
+      v4StartPos = currentGroupStart
+      currentShort = 0
+      seperatorValid = false
+      break
+    elif c in strutils.HexDigits:
+      if c in strutils.Digits: # Normal digit
+        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('0'))
+      elif c >= 'a' and c <= 'f': # Lower case hex
+        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10
+      else: # Upper case hex
+        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10
+      if currentShort > 65535'u32:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Value is out of range")
+      lastWasColon = false
+      seperatorValid = true
+    else:
+      raise newException(EInvalidValue,
+        "Invalid IP Address. Address contains an invalid character")
+
+
+  if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff
+    if seperatorValid: # Copy remaining data
+      if groupCount >= 8:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. The address consists of too many groups")
+      result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
+      result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
+      groupCount.inc()
+  else: # Must parse IPv4 address
+    for i,c in address_str[v4StartPos..high(address_str)]:
+      if c in strutils.Digits: # Character is a number
+        currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0'))
+        if currentShort > 255'u32:
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Value is out of range")
+        seperatorValid = true
+      elif c == '.': # IPv4 address separator
+        if not seperatorValid or byteCount >= 3:
+          raise newException(EInvalidValue, "Invalid IP Address")
+        result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
+        currentShort = 0
+        byteCount.inc()
+        seperatorValid = false
+      else: # Invalid character
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Address contains an invalid character")
+
+    if byteCount != 3 or not seperatorValid:
+      raise newException(EInvalidValue, "Invalid IP Address")
+    result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
+    groupCount += 2
+
+  # Shift and fill zeros in case of ::
+  if groupCount > 8:
+    raise newException(EInvalidValue,
+      "Invalid IP Address. The address consists of too many groups")
+  elif groupCount < 8: # must fill
+    if dualColonGroup == -1:
+      raise newException(EInvalidValue,
+        "Invalid IP Address. The address consists of too few groups")
+    var toFill = 8 - groupCount # The number of groups to fill
+    var toShift = groupCount - dualColonGroup # Nr of known groups after ::
+    for i in 0..2*toShift-1: # shift
+      result.address_v6[15-i] = result.address_v6[groupCount*2-i-1]
+    for i in 0..2*toFill-1: # fill with 0s
+      result.address_v6[dualColonGroup*2+i] = 0
+  elif dualColonGroup != -1:
+    raise newException(EInvalidValue,
+      "Invalid IP Address. The address consists of too many groups")
+
+proc parseIpAddress*(address_str: string): TIpAddress =
+  ## Parses an IP address
+  ## Raises EInvalidValue on error
+  if address_str == nil:
+    raise newException(EInvalidValue, "IP Address string is nil")
+  if address_str.contains(':'):
+    return parseIPv6Address(address_str)
+  else:
+    return parseIPv4Address(address_str)
diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim
index ab7cd1944..6f94d0656 100644
--- a/lib/pure/nimprof.nim
+++ b/lib/pure/nimprof.nim
@@ -26,7 +26,7 @@ const
   withThreads = compileOption("threads")
   tickCountCorrection = 50_000
 
-when not defined(system.TStackTrace):
+when not declared(system.TStackTrace):
   type TStackTrace = array [0..20, cstring]
 
 # We use a simple hash table of bounded size to keep track of the stack traces:
@@ -146,7 +146,7 @@ proc `//`(a, b: int): string =
   result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2))
 
 proc writeProfile() {.noconv.} =
-  when defined(system.TStackTrace):
+  when declared(system.TStackTrace):
     system.profilerHook = nil
   const filename = "profile_results.txt"
   echo "writing " & filename & "..."
@@ -189,16 +189,16 @@ var
   disabled: int
 
 proc disableProfiling*() =
-  when defined(system.TStackTrace):
+  when declared(system.TStackTrace):
     atomicDec disabled
     system.profilerHook = nil
 
 proc enableProfiling*() =
-  when defined(system.TStackTrace):
+  when declared(system.TStackTrace):
     if atomicInc(disabled) >= 0:
       system.profilerHook = hook
 
-when defined(system.TStackTrace):
+when declared(system.TStackTrace):
   system.profilerHook = hook
   addQuitProc(writeProfile)
 
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index a70bfa7f1..71089494f 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -365,8 +365,9 @@ when defined(windows):
     template getFilename(f: expr): expr = $f.cFilename
 
   proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} =
+    # Note - takes advantage of null delimiter in the cstring
     const dot = ord('.')
-    result = f.cFileName[0].int == dot and(f.cFileName[1].int == 0 or
+    result = f.cFileName[0].int == dot and (f.cFileName[1].int == 0 or
              f.cFileName[1].int == dot and f.cFileName[2].int == 0)
 
 proc existsFile*(filename: string): bool {.rtl, extern: "nos$1",
@@ -997,7 +998,7 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
   if c_rename(source, dest) != 0'i32:
     raise newException(EOS, $strerror(errno))
 
-when not defined(ENOENT) and not defined(Windows):
+when not declared(ENOENT) and not defined(Windows):
   when NoFakeVars:
     const ENOENT = cint(2) # 2 on most systems including Solaris
   else:
@@ -1331,10 +1332,10 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
 
 proc rawCreateDir(dir: string) =
   when defined(solaris):
-    if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST and errno != ENOSYS:
+    if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST and errno != ENOSYS:
       osError(osLastError())
   elif defined(unix):
-    if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST:
+    if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST:
       osError(osLastError())
   else:
     when useWinUnicode:
@@ -1457,7 +1458,8 @@ proc parseCmdLine*(c: string): seq[string] {.
   var a = ""
   while true:
     setLen(a, 0)
-    while c[i] == ' ' or c[i] == '\t': inc(i)
+    # eat all delimiting whitespace
+    while c[i] == ' ' or c[i] == '\t' or c [i] == '\l' or c [i] == '\r' : inc(i)
     when defined(windows):
       # parse a single argument according to the above rules:
       if c[i] == '\0': break
@@ -1614,11 +1616,11 @@ when defined(nimdoc):
     ##
     ## **Availability**: On Posix there is no portable way to get the command
     ## line from a DLL and thus the proc isn't defined in this environment. You
-    ## can test for its availability with `defined() <system.html#defined>`_.
+    ## can test for its availability with `declared() <system.html#declared>`_.
     ## Example:
     ##
     ## .. code-block:: nimrod
-    ##   when defined(paramCount):
+    ##   when declared(paramCount):
     ##     # Use paramCount() here
     ##   else:
     ##     # Do something else!
@@ -1637,11 +1639,11 @@ when defined(nimdoc):
     ##
     ## **Availability**: On Posix there is no portable way to get the command
     ## line from a DLL and thus the proc isn't defined in this environment. You
-    ## can test for its availability with `defined() <system.html#defined>`_.
+    ## can test for its availability with `declared() <system.html#declared>`_.
     ## Example:
     ##
     ## .. code-block:: nimrod
-    ##   when defined(paramStr):
+    ##   when declared(paramStr):
     ##     # Use paramStr() here
     ##   else:
     ##     # Do something else!
@@ -1681,7 +1683,7 @@ elif not defined(createNimRtl):
     # Docstring in nimdoc block.
     result = cmdCount-1
 
-when defined(paramCount) or defined(nimdoc):
+when declared(paramCount) or defined(nimdoc):
   proc commandLineParams*(): seq[TaintedString] =
     ## Convenience proc which returns the command line parameters.
     ##
@@ -1690,11 +1692,11 @@ when defined(paramCount) or defined(nimdoc):
     ##
     ## **Availability**: On Posix there is no portable way to get the command
     ## line from a DLL and thus the proc isn't defined in this environment. You
-    ## can test for its availability with `defined() <system.html#defined>`_.
+    ## can test for its availability with `declared() <system.html#declared>`_.
     ## Example:
     ##
     ## .. code-block:: nimrod
-    ##   when defined(commandLineParams):
+    ##   when declared(commandLineParams):
     ##     # Use commandLineParams() here
     ##   else:
     ##     # Do something else!
@@ -1713,7 +1715,7 @@ when defined(linux) or defined(solaris) or defined(bsd) or defined(aix):
 
 when not (defined(windows) or defined(macosx)):
   proc getApplHeuristic(): string =
-    when defined(paramStr):
+    when declared(paramStr):
       result = string(paramStr(0))
       # POSIX guaranties that this contains the executable
       # as it has been executed by the calling process
@@ -1860,12 +1862,12 @@ proc expandTilde*(path: string): string =
 
 when defined(Windows):
   type
-    DeviceId = int32
-    FileId = int64
+    DeviceId* = int32
+    FileId* = int64
 else:
   type
-    DeviceId = TDev
-    FileId = TIno
+    DeviceId* = TDev
+    FileId* = TIno
 
 type
   FileInfo* = object
@@ -1908,6 +1910,7 @@ template rawToFormalFileInfo(rawInfo, formalInfo): expr =
     if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
       formalInfo.kind = succ(result.kind)
 
+
   else:
     template checkAndIncludeMode(rawMode, formalMode: expr) = 
       if (rawInfo.st_mode and rawMode) != 0'i32:
@@ -1994,4 +1997,26 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo =
         osError(osLastError())
     rawToFormalFileInfo(rawInfo, result)
 
+proc isHidden*(path: string): bool =
+  ## Determines whether a given path is hidden or not. Returns false if the
+  ## file doesn't exist. The given path must be accessible from the current
+  ## working directory of the program.
+  ## 
+  ## On Windows, a file is hidden if the file's 'hidden' attribute is set.
+  ## On Unix-like systems, a file is hidden if it starts with a '.' (period)
+  ## and is not *just* '.' or '..' ' ."
+  when defined(Windows):
+    wrapUnary(attributes, getFileAttributesW, path)
+    if attributes != -1'i32:
+      result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32
+  else:
+    if fileExists(path):
+      let
+        fileName = extractFilename(path)
+        nameLen = len(fileName)
+      if nameLen == 2:
+        result = (fileName[0] == '.') and (fileName[1] != '.')
+      elif nameLen > 2:
+        result = (fileName[0] == '.') and (fileName[3] != '.')
+
 {.pop.}
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index c74fa1ceb..3c181bf53 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -643,7 +643,7 @@ elif not defined(useNimRtl):
     data.workingDir = workingDir
 
 
-    when defined(posix_spawn) and not defined(useFork) and 
+    when declared(posix_spawn) and not defined(useFork) and 
         not defined(useClone) and not defined(linux):
       pid = startProcessAuxSpawn(data)
     else:
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index 68ae537c7..f43853fe6 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -37,7 +37,7 @@ type
                               ## or the argument, ``value`` is not "" if
                               ## the option was given a value
 
-when defined(os.paramCount):
+when declared(os.paramCount):
   # we cannot provide this for NimRtl creation on Posix, because we can't 
   # access the command line arguments then!
 
@@ -127,7 +127,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {.
   ## retrieves the rest of the command line that has not been parsed yet.
   result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString
 
-when defined(initOptParser):
+when declared(initOptParser):
 
   iterator getopt*(): tuple[kind: TCmdLineKind, key, val: TaintedString] =
     ## This is an convenience iterator for iterating over the command line.
diff --git a/lib/pure/parseopt2.nim b/lib/pure/parseopt2.nim
index 5e79d8a18..7638171d1 100644
--- a/lib/pure/parseopt2.nim
+++ b/lib/pure/parseopt2.nim
@@ -119,7 +119,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {.rtl, extern: "npo$1", deprecat
 type
   TGetoptResult* = tuple[kind: TCmdLineKind, key, val: TaintedString]
 
-when defined(paramCount):
+when declared(paramCount):
   iterator getopt*(): TGetoptResult =
     ## This is an convenience iterator for iterating over the command line.
     ## This uses the TOptParser object. Example:
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 68b1ab223..efe169c1d 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -870,7 +870,7 @@ template `=~`*(s: string, pattern: TPeg): bool =
   ##     echo("syntax error")
   ##  
   bind maxSubpatterns
-  when not definedInScope(matches):
+  when not declaredInScope(matches):
     var matches {.inject.}: array[0..MaxSubpatterns-1, string]
   match(s, pattern, matches)
 
diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim
index d96741846..fea09dfa2 100644
--- a/lib/pure/rawsockets.nim
+++ b/lib/pure/rawsockets.nim
@@ -22,7 +22,7 @@ const useWinVersion = defined(Windows) or defined(nimdoc)
 when useWinVersion:
   import winlean
   export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
-         WSAEDISCON
+         WSAEDISCON, ERROR_NETNAME_DELETED
 else:
   import posix
   export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL,
diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim
index 4a6c3f530..eb3792bce 100644
--- a/lib/pure/ropes.nim
+++ b/lib/pure/ropes.nim
@@ -58,8 +58,8 @@ proc newRope(data: string): PRope =
   result.data = data
 
 var 
-  cache: PRope                # the root of the cache tree
-  N: PRope                    # dummy rope needed for splay algorithm
+  cache {.threadvar.}: PRope     # the root of the cache tree
+  N {.threadvar.}: PRope         # dummy rope needed for splay algorithm
 
 when countCacheMisses:
   var misses, hits: int
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 6f8924d83..1d17de233 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -803,6 +803,36 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} =
     if result != -1: return
   return -1
 
+proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect,
+  rtl, extern: "nsuCountString".} =
+  ## Count the occurences of a substring `sub` in the string `s`.
+  ## Overlapping occurences of `sub` only count when `overlapping`
+  ## is set to true.
+  var i = 0
+  while true:
+    i = s.find(sub, i)
+    if i < 0:
+      break
+    if overlapping:
+      inc i
+    else:
+      i += sub.len
+    inc result
+
+proc count*(s: string, sub: char): int {.noSideEffect,
+  rtl, extern: "nsuCountChar".} =
+  ## Count the occurences of the character `sub` in the string `s`.
+  for c in s:
+    if c == sub:
+      inc result
+
+proc count*(s: string, subs: set[char]): int {.noSideEffect,
+  rtl, extern: "nsuCountCharSet".} =
+  ## Count the occurences of the group of character `subs` in the string `s`.
+  for c in s:
+    if c in subs:
+      inc result
+
 proc quoteIfContainsWhite*(s: string): string {.deprecated.} =
   ## Returns ``'"' & s & '"'`` if `s` contains a space and does not
   ## start with a quote, else returns `s`.
@@ -1354,3 +1384,8 @@ when isMainModule:
   doAssert parseEnum[TMyEnum]("enu_D") == enuD
 
   doAssert parseEnum("invalid enum value", enC) == enC
+
+  doAssert count("foofoofoo", "foofoo") == 1
+  doAssert count("foofoofoo", "foofoo", overlapping = true) == 2
+  doAssert count("foofoofoo", 'f') == 3
+  doAssert count("foofoofoobar", {'f','b'}) == 4
diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim
index 92797744a..ed87610d6 100644
--- a/lib/pure/subexes.nim
+++ b/lib/pure/subexes.nim
@@ -84,7 +84,8 @@ proc getFormatArg(p: var TFormatParser, a: openArray[string]): int =
   if result >=% a.len: raiseInvalidFormat("index out of bounds: " & $result)
   p.i = i
 
-proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string)
+proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string) {.
+  noSideEffect.}
 
 proc emitChar(p: var TFormatParser, x: var string, ch: char) {.inline.} =
   x.add(ch)
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 498511899..8b33d2c73 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -63,44 +63,44 @@ elif defined(windows):
 elif defined(JS):
   type
     TTime* {.final, importc.} = object
-      getDay: proc (): int {.tags: [], raises: [].}
-      getFullYear: proc (): int {.tags: [], raises: [].}
-      getHours: proc (): int {.tags: [], raises: [].}
-      getMilliseconds: proc (): int {.tags: [], raises: [].}
-      getMinutes: proc (): int {.tags: [], raises: [].}
-      getMonth: proc (): int {.tags: [], raises: [].}
-      getSeconds: proc (): int {.tags: [], raises: [].}
-      getTime: proc (): int {.tags: [], raises: [].}
-      getTimezoneOffset: proc (): int {.tags: [], raises: [].}
-      getDate: proc (): int {.tags: [], raises: [].}
-      getUTCDate: proc (): int {.tags: [], raises: [].}
-      getUTCFullYear: proc (): int {.tags: [], raises: [].}
-      getUTCHours: proc (): int {.tags: [], raises: [].}
-      getUTCMilliseconds: proc (): int {.tags: [], raises: [].}
-      getUTCMinutes: proc (): int {.tags: [], raises: [].}
-      getUTCMonth: proc (): int {.tags: [], raises: [].}
-      getUTCSeconds: proc (): int {.tags: [], raises: [].}
-      getUTCDay: proc (): int {.tags: [], raises: [].}
-      getYear: proc (): int {.tags: [], raises: [].}
-      parse: proc (s: cstring): TTime {.tags: [], raises: [].}
-      setDate: proc (x: int) {.tags: [], raises: [].}
-      setFullYear: proc (x: int) {.tags: [], raises: [].}
-      setHours: proc (x: int) {.tags: [], raises: [].}
-      setMilliseconds: proc (x: int) {.tags: [], raises: [].}
-      setMinutes: proc (x: int) {.tags: [], raises: [].}
-      setMonth: proc (x: int) {.tags: [], raises: [].}
-      setSeconds: proc (x: int) {.tags: [], raises: [].}
-      setTime: proc (x: int) {.tags: [], raises: [].}
-      setUTCDate: proc (x: int) {.tags: [], raises: [].}
-      setUTCFullYear: proc (x: int) {.tags: [], raises: [].}
-      setUTCHours: proc (x: int) {.tags: [], raises: [].}
-      setUTCMilliseconds: proc (x: int) {.tags: [], raises: [].}
-      setUTCMinutes: proc (x: int) {.tags: [], raises: [].}
-      setUTCMonth: proc (x: int) {.tags: [], raises: [].}
-      setUTCSeconds: proc (x: int) {.tags: [], raises: [].}
-      setYear: proc (x: int) {.tags: [], raises: [].}
-      toGMTString: proc (): cstring {.tags: [], raises: [].}
-      toLocaleString: proc (): cstring {.tags: [], raises: [].}
+      getDay: proc (): int {.tags: [], raises: [], gcsafe.}
+      getFullYear: proc (): int {.tags: [], raises: [], gcsafe.}
+      getHours: proc (): int {.tags: [], raises: [], gcsafe.}
+      getMilliseconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getMinutes: proc (): int {.tags: [], raises: [], gcsafe.}
+      getMonth: proc (): int {.tags: [], raises: [], gcsafe.}
+      getSeconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getTime: proc (): int {.tags: [], raises: [], gcsafe.}
+      getTimezoneOffset: proc (): int {.tags: [], raises: [], gcsafe.}
+      getDate: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCDate: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCFullYear: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCHours: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCMilliseconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCMinutes: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCMonth: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCSeconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCDay: proc (): int {.tags: [], raises: [], gcsafe.}
+      getYear: proc (): int {.tags: [], raises: [], gcsafe.}
+      parse: proc (s: cstring): TTime {.tags: [], raises: [], gcsafe.}
+      setDate: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setFullYear: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setHours: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setMilliseconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setMinutes: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setMonth: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setSeconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setTime: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCDate: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCFullYear: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCHours: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCMilliseconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCMinutes: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCMonth: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCSeconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setYear: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      toGMTString: proc (): cstring {.tags: [], raises: [], gcsafe.}
+      toLocaleString: proc (): cstring {.tags: [], raises: [], gcsafe.}
 
 type
   TTimeInfo* = object of TObject ## represents a time in different parts
@@ -513,7 +513,7 @@ elif defined(JS):
     result.setFullYear(timeInfo.year)
     result.setDate(timeInfo.monthday)
   
-  proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo))
+  proc `$`(timeInfo: TTimeInfo): string = return $(timeInfoToTime(timeInfo))
   proc `$`(time: TTime): string = return $time.toLocaleString()
     
   proc `-` (a, b: TTime): int64 = 
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index e7bd363cf..3203ee699 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -11,7 +11,26 @@
 ## working with types
 
 proc name*(t: typedesc): string {.magic: "TypeTrait".}
-  ## Returns the name of the given type
+  ## Returns the name of the given type.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##
+  ##   import typetraits
+  ##
+  ##   proc `$`*[T](some:typedesc[T]): string = name(T)
+  ##
+  ##   template test(x): stmt =
+  ##     echo "type: ", type(x), ", value: ", x
+  ##
+  ##   test 42
+  ##   # --> type: int, value: 42
+  ##   test "Foo"
+  ##   # --> type: string, value: Foo
+  ##   test(@['A','B'])
+  ##   # --> type: seq[char], value: @[A, B]
+
 
 proc arity*(t: typedesc): int {.magic: "TypeTrait".}
-  ## Returns the arity of the given type
\ No newline at end of file
+  ## Returns the arity of the given type
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index f5640a1b4..7cc95f0ad 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -19,7 +19,7 @@
 import
   macros
 
-when defined(stdout):
+when declared(stdout):
   import os
 
 when not defined(ECMAScript):
@@ -99,7 +99,7 @@ template fail* =
   when not defined(ECMAScript):
     if AbortOnError: quit(1)
  
-  when defined(TestStatusIMPL):
+  when declared(TestStatusIMPL):
     TestStatusIMPL = FAILED
   else:
     program_result += 1
@@ -188,7 +188,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
   result = getAst(expectBody(errorTypes, exp.lineinfo, body))
 
 
-when defined(stdout):
+when declared(stdout):
   ## Reading settings
   var envOutLvl = os.getEnv("NIMTEST_OUTPUT_LVL").string
 
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 95b48a850..1af7db7d5 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -151,6 +151,8 @@ proc addEscaped*(result: var string, s: string) =
     of '>': result.add("&gt;")
     of '&': result.add("&amp;")
     of '"': result.add("&quot;")
+    of '\'': result.add("&#x27;")
+    of '/': result.add("&#x2F;")
     else: result.add(c)
 
 proc escape*(s: string): string = 
@@ -164,6 +166,8 @@ proc escape*(s: string): string =
   ##  ``>``          ``&gt;``
   ##  ``&``          ``&amp;``
   ##  ``"``          ``&quot;``
+  ##  ``'``          ``&#x27;``
+  ##  ``/``          ``&#x2F;``
   ## ------------    -------------------
   result = newStringOfCap(s.len)
   addEscaped(result, s)
diff --git a/lib/system.nim b/lib/system.nim
index d77b4fdee..0df8849f5 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -13,6 +13,21 @@
 ## Each module implicitly imports the System module; it must not be listed
 ## explicitly. Because of this there cannot be a user-defined module named
 ## ``system``.
+##
+## Exception hierarchy
+## ===================
+##
+## For visual convenience here is the exception inheritance hierarchy
+## represented as a tree:
+##
+## .. include:: ../doc/exception_hierarchy_fragment.txt
+##
+## Module system
+## =============
+##
+
+# That lonesome header above is to prevent :idx: entries from being mentioned
+# in the global index as part of the previous header (Exception hierarchy).
 
 type
   int* {.magic: Int.} ## default integer type; bitwidth depends on
@@ -83,16 +98,8 @@ type
 
 proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
   ## Special compile-time procedure that checks whether `x` is
-  ## defined. `x` has to be an identifier or a qualified identifier.
-  ## This can be used to check whether a library provides a certain
-  ## feature or not:
-  ##
-  ## .. code-block:: Nimrod
-  ##   when not defined(strutils.toUpper):
-  ##     # provide our own toUpper proc here, because strutils is
-  ##     # missing it.
-  ##
-  ## You can also check external symbols introduced through the compiler's
+  ## defined.
+  ## `x` is an external symbol introduced through the compiler's
   ## `-d:x switch <nimrodc.html#compile-time-symbols>`_ to enable build time
   ## conditionals:
   ##
@@ -101,13 +108,28 @@ proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
   ##     # Do here programmer friendly expensive sanity checks.
   ##   # Put here the normal code
 
+proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
+  ## Special compile-time procedure that checks whether `x` is
+  ## declared. `x` has to be an identifier or a qualified identifier.
+  ## This can be used to check whether a library provides a certain
+  ## feature or not:
+  ##
+  ## .. code-block:: Nimrod
+  ##   when not defined(strutils.toUpper):
+  ##     # provide our own toUpper proc here, because strutils is
+  ##     # missing it.
+
 when defined(useNimRtl):
   {.deadCodeElim: on.}
 
 proc definedInScope*(x: expr): bool {.
+  magic: "DefinedInScope", noSideEffect, deprecated.}
+  ## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
+
+proc declaredInScope*(x: expr): bool {.
   magic: "DefinedInScope", noSideEffect.}
   ## Special compile-time procedure that checks whether `x` is
-  ## defined in the current scope. `x` has to be an identifier.
+  ## declared in the current scope. `x` has to be an identifier.
 
 proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
   ## Boolean not; returns true iff ``x == false``.
@@ -301,9 +323,11 @@ type
   FWriteIO* = object of FIO    ## Effect describing a write IO operation.
   FExecIO* = object of FIO     ## Effect describing an executing IO operation.
 
-  E_Base* {.compilerproc.} = object of TObject ## base exception class;
-                                               ## each exception has to
-                                               ## inherit from `E_Base`.
+  E_Base* {.compilerproc.} = object of TObject ## \
+    ## Base exception class.
+    ##
+    ## Each exception has to inherit from `E_Base`. See the full `exception
+    ## hierarchy`_.
     parent: ref E_Base        ## parent exception (can be used as a stack)
     name: cstring             ## The exception's name is its Nimrod identifier.
                               ## This field is filled automatically in the
@@ -313,99 +337,142 @@ type
                                         ## is bad style.
     trace: string
 
-  EAsynch* = object of E_Base ## Abstract exception class for
-                              ## *asynchronous exceptions* (interrupts).
-                              ## This is rarely needed: Most
-                              ## exception types inherit from `ESynch`
-  ESynch* = object of E_Base  ## Abstract exception class for
-                              ## *synchronous exceptions*. Most exceptions
-                              ## should be inherited (directly or indirectly)
-                              ## from ESynch.
-  ESystem* = object of ESynch ## Abstract class for exceptions that the runtime
-                              ## system raises.
-  EIO* = object of ESystem    ## raised if an IO error occured.
-  EOS* = object of ESystem    ## raised if an operating system service failed.
+  EAsynch* = object of E_Base ## \
+    ## Abstract exception class for *asynchronous exceptions* (interrupts).
+    ##
+    ## This is rarely needed: most exception types inherit from `ESynch
+    ## <#ESynch>`_. See the full `exception hierarchy`_.
+  EControlC* = object of EAsynch ## \
+    ## Raised for Ctrl+C key presses in console applications.
+    ##
+    ## See the full `exception hierarchy`_.
+  ESynch* = object of E_Base ## \
+    ## Abstract exception class for *synchronous exceptions*.
+    ##
+    ## Most exceptions should be inherited (directly or indirectly) from
+    ## `ESynch` instead of from `EAsynch <#EAsynch>`_. See the full `exception
+    ## hierarchy`_.
+  ESystem* = object of ESynch ## \
+    ## Abstract class for exceptions that the runtime system raises.
+    ##
+    ## See the full `exception hierarchy`_.
+  EIO* = object of ESystem ## \
+    ## Raised if an IO error occured.
+    ##
+    ## See the full `exception hierarchy`_.
+  EOS* = object of ESystem ## \
+    ## Raised if an operating system service failed.
+    ##
+    ## See the full `exception hierarchy`_.
     errorCode*: int32 ## OS-defined error code describing this error.
-  EInvalidLibrary* = object of EOS ## raised if a dynamic library
-                                   ## could not be loaded.
-  EResourceExhausted* = object of ESystem ## raised if a resource request
-                                          ## could not be fullfilled.
-  EArithmetic* = object of ESynch       ## raised if any kind of arithmetic
-                                        ## error occured.
-  EDivByZero* {.compilerproc.} =
-    object of EArithmetic ## is the exception class for integer divide-by-zero
-                          ## errors.
-  EOverflow* {.compilerproc.} =
-    object of EArithmetic  ## is the exception class for integer calculations
-                           ## whose results are too large to fit in the
-                           ## provided bits.
-
-  EAccessViolation* {.compilerproc.} =
-    object of ESynch ## the exception class for invalid memory access errors
-
-  EAssertionFailed* {.compilerproc.} =
-    object of ESynch  ## is the exception class for Assert
-                      ## procedures that is raised if the
-                      ## assertion proves wrong
-
-  EControlC* = object of EAsynch        ## is the exception class for Ctrl+C
-                                        ## key presses in console applications.
-
-  EInvalidValue* = object of ESynch     ## is the exception class for string
-                                        ## and object conversion errors.
-  EInvalidKey* = object of EInvalidValue ## is the exception class if a key
-                                         ## cannot be found in a table.
-
-  EOutOfMemory* = object of ESystem     ## is the exception class for
-                                        ## unsuccessful attempts to allocate
-                                        ## memory.
-
-  EInvalidIndex* = object of ESynch     ## is raised if an array index is out
-                                        ## of bounds.
-  EInvalidField* = object of ESynch     ## is raised if a record field is not
-                                        ## accessible because its dicriminant's
-                                        ## value does not fit.
-
-  EOutOfRange* = object of ESynch       ## is raised if a range check error
-                                        ## occurred.
-
-  EStackOverflow* = object of ESystem   ## is raised if the hardware stack
-                                        ## used for subroutine calls overflowed.
-
-  ENoExceptionToReraise* = object of ESynch ## is raised if there is no
-                                            ## exception to reraise.
-
-  EInvalidObjectAssignment* =
-    object of ESynch ## is raised if an object gets assigned to its
-                     ## parent's object.
-
-  EInvalidObjectConversion* =
-    object of ESynch ## is raised if an object is converted to an incompatible
-                     ## object type.
-
-  EFloatingPoint* = object of ESynch ## base class for floating point exceptions
-  EFloatInvalidOp* {.compilerproc.} = 
-    object of EFloatingPoint ## Invalid operation according to IEEE: Raised by 
-                             ## 0.0/0.0, for example.
-  EFloatDivByZero* {.compilerproc.} = 
-    object of EFloatingPoint ## Division by zero. Divisor is zero and dividend 
-                             ## is a finite nonzero number.
-  EFloatOverflow* {.compilerproc.} = 
-    object of EFloatingPoint ## Overflow. Operation produces a result 
-                             ## that exceeds the range of the exponent
-  EFloatUnderflow* {.compilerproc.} = 
-    object of EFloatingPoint ## Underflow. Operation produces a result 
-                             ## that is too small to be represented as 
-                             ## a normal number
-  EFloatInexact* {.compilerproc.} = 
-    object of EFloatingPoint ## Inexact. Operation produces a result
-                             ## that cannot be represented with infinite
-                             ## precision -- for example, 2.0 / 3.0, log(1.1) 
-                             ## NOTE: Nimrod currently does not detect these!
-  EDeadThread* =
-    object of ESynch ## is raised if it is attempted to send a message to a
-                     ## dead thread.
-                     
+  EInvalidLibrary* = object of EOS ## \
+    ## Raised if a dynamic library could not be loaded.
+    ##
+    ## See the full `exception hierarchy`_.
+  EResourceExhausted* = object of ESystem ## \
+    ## Raised if a resource request could not be fullfilled.
+    ##
+    ## See the full `exception hierarchy`_.
+  EArithmetic* = object of ESynch ## \
+    ## Raised if any kind of arithmetic error occured.
+    ##
+    ## See the full `exception hierarchy`_.
+  EDivByZero* {.compilerproc.} = object of EArithmetic ## \
+    ## Raised for runtime integer divide-by-zero errors.
+    ##
+    ## See the full `exception hierarchy`_.
+  EOverflow* {.compilerproc.} = object of EArithmetic ## \
+    ## Raised for runtime integer overflows.
+    ##
+    ## This happens for calculations whose results are too large to fit in the
+    ## provided bits.  See the full `exception hierarchy`_.
+  EAccessViolation* {.compilerproc.} = object of ESynch ## \
+    ## Raised for invalid memory access errors
+    ##
+    ## See the full `exception hierarchy`_.
+  EAssertionFailed* {.compilerproc.} = object of ESynch ## \
+    ## Raised when assertion is proved wrong.
+    ##
+    ## Usually the result of using the `assert() template <#assert>`_.  See the
+    ## full `exception hierarchy`_.
+  EInvalidValue* = object of ESynch ## \
+    ## Raised for string and object conversion errors.
+  EInvalidKey* = object of EInvalidValue ## \
+    ## Raised if a key cannot be found in a table.
+    ##
+    ## Mostly used by the `tables <tables.html>`_ module, it can also be raised
+    ## by other collection modules like `sets <sets.html>`_ or `strtabs
+    ## <strtabs.html>`_. See the full `exception hierarchy`_.
+  EOutOfMemory* = object of ESystem ## \
+    ## Raised for unsuccessful attempts to allocate memory.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidIndex* = object of ESynch ## \
+    ## Raised if an array index is out of bounds.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidField* = object of ESynch ## \
+    ## Raised if a record field is not accessible because its dicriminant's
+    ## value does not fit.
+    ##
+    ## See the full `exception hierarchy`_.
+  EOutOfRange* = object of ESynch ## \
+    ## Raised if a range check error occurred.
+    ##
+    ## See the full `exception hierarchy`_.
+  EStackOverflow* = object of ESystem ## \
+    ## Raised if the hardware stack used for subroutine calls overflowed.
+    ##
+    ## See the full `exception hierarchy`_.
+  ENoExceptionToReraise* = object of ESynch ## \
+    ## Raised if there is no exception to reraise.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidObjectAssignment* = object of ESynch ## \
+    ## Raised if an object gets assigned to its parent's object.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidObjectConversion* = object of ESynch ## \
+    ## Raised if an object is converted to an incompatible object type.
+    ##
+    ## See the full `exception hierarchy`_.
+  EFloatingPoint* = object of ESynch ## \
+    ## Base class for floating point exceptions.
+    ##
+    ## See the full `exception hierarchy`_.
+  EFloatInvalidOp* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised by invalid operations according to IEEE.
+    ##
+    ## Raised by ``0.0/0.0``, for example.  See the full `exception
+    ## hierarchy`_.
+  EFloatDivByZero* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised by division by zero.
+    ##
+    ## Divisor is zero and dividend is a finite nonzero number.  See the full
+    ## `exception hierarchy`_.
+  EFloatOverflow* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised for overflows.
+    ##
+    ## The operation produced a result that exceeds the range of the exponent.
+    ## See the full `exception hierarchy`_.
+  EFloatUnderflow* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised for underflows.
+    ##
+    ## The operation produced a result that is too small to be represented as a
+    ## normal number. See the full `exception hierarchy`_.
+  EFloatInexact* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised for inexact results.
+    ##
+    ## The operation produced a result that cannot be represented with infinite
+    ## precision -- for example: ``2.0 / 3.0, log(1.1)``
+    ##
+    ## **NOTE**: Nimrod currently does not detect these!  See the full
+    ## `exception hierarchy`_.
+  EDeadThread* = object of ESynch ## \
+    ## Raised if it is attempted to send a message to a dead thread.
+    ##
+    ## See the full `exception hierarchy`_.
+
   TResult* = enum Failure, Success
 
 proc sizeof*[T](x: T): Natural {.magic: "SizeOf", noSideEffect.}
@@ -782,13 +849,13 @@ proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
   ##   assert((1..3).contains(4) == false)
   result = s.a <= value and value <= s.b
 
-template `in` * (x, y: expr): expr {.immediate.} = contains(y, x)
+template `in` * (x, y: expr): expr {.immediate, dirty.} = contains(y, x)
   ## Sugar for contains
   ##
   ## .. code-block:: Nimrod
   ##   assert(1 in (1..3) == true)
   ##   assert(5 in (1..3) == false)
-template `notin` * (x, y: expr): expr {.immediate.} = not contains(y, x)
+template `notin` * (x, y: expr): expr {.immediate, dirty.} = not contains(y, x)
   ## Sugar for not containing
   ##
   ## .. code-block:: Nimrod
@@ -1930,16 +1997,16 @@ when not defined(nimrodVM) and hostOS != "standalone":
     ## returns an informative string about the GC's activity. This may be useful
     ## for tweaking.
     
-  proc GC_ref*[T](x: ref T) {.magic: "GCref".}
-  proc GC_ref*[T](x: seq[T]) {.magic: "GCref".}
-  proc GC_ref*(x: string) {.magic: "GCref".}
+  proc GC_ref*[T](x: ref T) {.magic: "GCref", gcsafe.}
+  proc GC_ref*[T](x: seq[T]) {.magic: "GCref", gcsafe.}
+  proc GC_ref*(x: string) {.magic: "GCref", gcsafe.}
     ## marks the object `x` as referenced, so that it will not be freed until
     ## it is unmarked via `GC_unref`. If called n-times for the same object `x`,
     ## n calls to `GC_unref` are needed to unmark `x`. 
     
-  proc GC_unref*[T](x: ref T) {.magic: "GCunref".}
-  proc GC_unref*[T](x: seq[T]) {.magic: "GCunref".}
-  proc GC_unref*(x: string) {.magic: "GCunref".}
+  proc GC_unref*[T](x: ref T) {.magic: "GCunref", gcsafe.}
+  proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", gcsafe.}
+  proc GC_unref*(x: string) {.magic: "GCunref", gcsafe.}
     ## see the documentation of `GC_ref`.
 
 template accumulateResult*(iter: expr) =
@@ -2058,7 +2125,7 @@ template newException*(exceptn: typedesc, message: string): expr =
 when hostOS == "standalone":
   include panicoverride
 
-when not defined(sysFatal):
+when not declared(sysFatal):
   template sysFatal(exceptn: typedesc, message: string) =
     when hostOS == "standalone":
       panic(message)
@@ -2110,11 +2177,17 @@ when not defined(JS): #and not defined(NimrodVM):
       # WARNING: This is very fragile! An array size of 8 does not work on my
       # Linux 64bit system. -- That's because the stack direction is the other
       # way round.
-      when defined(setStackBottom):
+      when declared(setStackBottom):
         var locals {.volatile.}: pointer
         locals = addr(locals)
         setStackBottom(locals)
 
+    proc initStackBottomWith(locals: pointer) {.inline, compilerproc.} =
+      # We need to keep initStackBottom around for now to avoid
+      # bootstrapping problems.
+      when declared(setStackBottom):
+        setStackBottom(locals)
+
     var
       strDesc: TNimType
 
@@ -2383,7 +2456,7 @@ when not defined(JS): #and not defined(NimrodVM):
       hasRaiseAction: bool
       raiseAction: proc (e: ref E_Base): bool {.closure.}
   
-  when defined(initAllocator):
+  when declared(initAllocator):
     initAllocator()
   when hasThreadSupport:
     include "system/syslocks"
@@ -2500,11 +2573,11 @@ when not defined(JS): #and not defined(NimrodVM):
     include "system/assign"
     include "system/repr"
 
-    proc getCurrentException*(): ref E_Base {.compilerRtl, inl.} =
+    proc getCurrentException*(): ref E_Base {.compilerRtl, inl, gcsafe.} =
       ## retrieves the current exception; if there is none, nil is returned.
       result = currException
 
-    proc getCurrentExceptionMsg*(): string {.inline.} =
+    proc getCurrentExceptionMsg*(): string {.inline, gcsafe.} =
       ## retrieves the error message that was attached to the current
       ## exception; if there is none, "" is returned.
       var e = getCurrentException()
@@ -2956,7 +3029,7 @@ proc compiles*(x): bool {.magic: "Compiles", noSideEffect.} =
   ##     echo "'+' for integers is available"
   discard
 
-when defined(initDebugger):
+when declared(initDebugger):
   initDebugger()
 
 when hostOS != "standalone":
@@ -2997,18 +3070,12 @@ proc locals*(): TObject {.magic: "Locals", noSideEffect.} =
   ##   # -> B is 1
   discard
 
-proc deepCopy*[T](x: T): T {.magic: "DeepCopy", noSideEffect.} =
-  ## performs a deep copy of `x`. This is also used by the code generator
-  ## for the implementation of ``spawn``.
-  discard
+when hostOS != "standalone" and not defined(NimrodVM) and not defined(JS):
+  proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
+    ## performs a deep copy of `x`. This is also used by the code generator
+    ## for the implementation of ``spawn``.
+    discard
 
-{.pop.} #{.push warning[GcMem]: off.}
+  include "system/deepcopy"
 
-when not defined(booting):
-  type
-    semistatic*[T] = static[T] | T
-    # indicates a param of proc specialized for each static value,
-    # but also accepting run-time values
-
-  template isStatic*(x): expr = compiles(static(x))
-    # checks whether `x` is a value known at compile-time
+{.pop.} #{.push warning[GcMem]: off.}
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index 511a006d3..673d55582 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -39,7 +39,7 @@ var
   c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar
 
 # constants faked as variables:
-when not defined(SIGINT):
+when not declared(SIGINT):
   when NoFakeVars:
     when defined(windows):
       const
@@ -78,10 +78,23 @@ when defined(macosx):
 else:
   template SIGBUS: expr = SIGSEGV
 
-proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
-  header: "<setjmp.h>", importc: "longjmp".}
-proc c_setjmp(jmpb: C_JmpBuf): cint {.
-  header: "<setjmp.h>", importc: "setjmp".}
+when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
+  proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
+    header: "<setjmp.h>", importc: "siglongjmp".}
+  template c_setjmp(jmpb: C_JmpBuf): cint =
+    proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {.
+      header: "<setjmp.h>", importc: "sigsetjmp".}
+    c_sigsetjmp(jmpb, 0)
+elif defined(nimRawSetjmp) and not defined(nimStdSetjmp):
+  proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
+    header: "<setjmp.h>", importc: "_longjmp".}
+  proc c_setjmp(jmpb: C_JmpBuf): cint {.
+    header: "<setjmp.h>", importc: "_setjmp".}
+else:
+  proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
+    header: "<setjmp.h>", importc: "longjmp".}
+  proc c_setjmp(jmpb: C_JmpBuf): cint {.
+    header: "<setjmp.h>", importc: "setjmp".}
 
 proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
   importc: "signal", header: "<signal.h>".}
@@ -132,7 +145,7 @@ proc c_realloc(p: pointer, newsize: int): pointer {.
   importc: "realloc", header: "<stdlib.h>".}
 
 when hostOS != "standalone":
-  when not defined(errno):
+  when not declared(errno):
     when defined(NimrodVM):
       var vmErrnoWrapper {.importc.}: ptr cint
       template errno: expr = 
diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim
index d9b3aebac..7672947cd 100644
--- a/lib/system/arithm.nim
+++ b/lib/system/arithm.nim
@@ -114,63 +114,69 @@ when asmVersion and not defined(gcc) and not defined(llvm_gcc):
   proc addInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     # a in eax, and b in edx
     asm """
-        mov eax, `a`
-        add eax, `b`
+        mov eax, ecx
+        add eax, edx
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc subInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        sub eax, `b`
+        mov eax, ecx
+        sub eax, edx
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc negInt(a: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
+        mov eax, ecx
         neg eax
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc divInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        mov ecx, `b`
+        mov eax, ecx
+        mov ecx, edx
         xor edx, edx
         idiv ecx
         jno  theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc modInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        mov ecx, `b`
+        mov eax, ecx
+        mov ecx, edx
         xor edx, edx
         idiv ecx
         jno theEnd
         call `raiseOverflow`
       theEnd:
         mov eax, edx
+        ret
     """
 
   proc mulInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        mov ecx, `b`
+        mov eax, ecx
+        mov ecx, edx
         xor edx, edx
         imul ecx
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
 elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
@@ -241,26 +247,26 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
     """
 
 # Platform independent versions of the above (slower!)
-when not defined(addInt):
+when not declared(addInt):
   proc addInt(a, b: int): int {.compilerProc, inline.} =
     result = a +% b
     if (result xor a) >= 0 or (result xor b) >= 0:
       return result
     raiseOverflow()
 
-when not defined(subInt):
+when not declared(subInt):
   proc subInt(a, b: int): int {.compilerProc, inline.} =
     result = a -% b
     if (result xor a) >= 0 or (result xor not b) >= 0:
       return result
     raiseOverflow()
 
-when not defined(negInt):
+when not declared(negInt):
   proc negInt(a: int): int {.compilerProc, inline.} =
     if a != low(int): return -a
     raiseOverflow()
 
-when not defined(divInt):
+when not declared(divInt):
   proc divInt(a, b: int): int {.compilerProc, inline.} =
     if b == 0:
       raiseDivByZero()
@@ -268,13 +274,13 @@ when not defined(divInt):
       raiseOverflow()
     return a div b
 
-when not defined(modInt):
+when not declared(modInt):
   proc modInt(a, b: int): int {.compilerProc, inline.} =
     if b == 0:
       raiseDivByZero()
     return a mod b
 
-when not defined(mulInt):
+when not declared(mulInt):
   #
   # This code has been inspired by Python's source code.
   # The native int product x*y is either exactly right or *way* off, being
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index 2ae945fb1..0e27eb57f 100644
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -89,14 +89,10 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
     copyMem(dest, src, mt.size) # copy raw bits
 
 proc genericAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
-  GC_disable()
   genericAssignAux(dest, src, mt, false)
-  GC_enable()
 
 proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
-  GC_disable()
   genericAssignAux(dest, src, mt, true)
-  GC_enable()
 
 when false:
   proc debugNimType(t: PNimType) =
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 43b3f0438..3ef9d00ec 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -7,30 +7,36 @@
 #    distribution, for details about the copyright.
 #
 
-## Atomic operations for Nimrod.
+# Atomic operations for Nimrod.
 {.push stackTrace:off.}
 
 const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang)
 
 when someGcc and hasThreadSupport:
-  type 
-    AtomMemModel* = enum
-      ATOMIC_RELAXED,  ## No barriers or synchronization. 
-      ATOMIC_CONSUME,  ## Data dependency only for both barrier and
-                       ## synchronization with another thread.
-      ATOMIC_ACQUIRE,  ## Barrier to hoisting of code and synchronizes with
-                       ## release (or stronger) 
-                       ## semantic stores from another thread.
-      ATOMIC_RELEASE,  ## Barrier to sinking of code and synchronizes with
-                       ## acquire (or stronger) 
-                       ## semantic loads from another thread. 
-      ATOMIC_ACQ_REL,  ## Full barrier in both directions and synchronizes
-                       ## with acquire loads 
-                       ## and release stores in another thread.
-      ATOMIC_SEQ_CST   ## Full barrier in both directions and synchronizes
-                       ## with acquire loads 
-                       ## and release stores in all threads.
-
+  type AtomMemModel* = distinct cint
+  var ATOMIC_RELAXED* {.importc: "__ATOMIC_RELAXED", nodecl.}: AtomMemModel
+    ## No barriers or synchronization.
+  var ATOMIC_CONSUME* {.importc: "__ATOMIC_CONSUME", nodecl.}: AtomMemModel
+    ## Data dependency only for both barrier and
+    ## synchronization with another thread.
+  var ATOMIC_ACQUIRE* {.importc: "__ATOMIC_ACQUIRE", nodecl.}: AtomMemModel
+    ## Barrier to hoisting of code and synchronizes with
+    ## release (or stronger) 
+    ## semantic stores from another thread.
+  var ATOMIC_RELEASE* {.importc: "__ATOMIC_RELEASE", nodecl.}: AtomMemModel
+    ## Barrier to sinking of code and synchronizes with
+    ## acquire (or stronger) 
+    ## semantic loads from another thread. 
+  var ATOMIC_ACQ_REL* {.importc: "__ATOMIC_ACQ_REL", nodecl.}: AtomMemModel
+    ## Full barrier in both directions and synchronizes
+    ## with acquire loads 
+    ## and release stores in another thread.
+  var ATOMIC_SEQ_CST* {.importc: "__ATOMIC_SEQ_CST", nodecl.}: AtomMemModel
+    ## Full barrier in both directions and synchronizes
+    ## with acquire loads 
+    ## and release stores in all threads.
+
+  type
     TAtomType* = TNumber|pointer|ptr|char
       ## Type Class representing valid types for use with atomic procs
 
@@ -166,15 +172,15 @@ else:
     result = p[]
 
 proc atomicInc*(memLoc: var int, x: int = 1): int =
-  when defined(gcc) and hasThreadSupport:
+  when someGcc and hasThreadSupport:
     result = atomic_add_fetch(memLoc.addr, x, ATOMIC_RELAXED)
   else:
     inc(memLoc, x)
     result = memLoc
   
 proc atomicDec*(memLoc: var int, x: int = 1): int =
-  when defined(gcc) and hasThreadSupport:
-    when defined(atomic_sub_fetch):
+  when someGcc and hasThreadSupport:
+    when declared(atomic_sub_fetch):
       result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED)
     else:
       result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED)
@@ -196,19 +202,19 @@ else:
   # XXX is this valid for 'int'?
 
 
-when (defined(x86) or defined(amd64)) and (defined(gcc) or defined(llvm_gcc)):
+when (defined(x86) or defined(amd64)) and someGcc:
   proc cpuRelax {.inline.} =
     {.emit: """asm volatile("pause" ::: "memory");""".}
 elif (defined(x86) or defined(amd64)) and defined(vcc):
   proc cpuRelax {.importc: "YieldProcessor", header: "<windows.h>".}
-elif defined(intelc):
+elif defined(icl):
   proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".}
 elif false:
   from os import sleep
 
   proc cpuRelax {.inline.} = os.sleep(1)
 
-when not defined(fence) and hasThreadSupport:
+when not declared(fence) and hasThreadSupport:
   # XXX fixme
   proc fence*() {.inline.} =
     var dummy: bool
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index e5535dbdc..a5d5c0802 100644
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -14,7 +14,7 @@
 ## **Note:** The current implementation of message passing is slow and does

 ## not work with cyclic data structures.

   
-when not defined(NimString): 
+when not declared(NimString):
   {.error: "You must not import this module explicitly".}
 

 type

@@ -226,15 +226,16 @@ proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =
   llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))

   releaseSys(q.lock)

 
-proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvaliable: bool,
+proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,
                                                   msg: TMsg] =
   ## try to receives a message from the channel `c` if available. Otherwise
   ## it returns ``(false, default(msg))``.
   var q = cast[PRawChannel](addr(c))

-  if q.mask != ChannelDeadMask:

-    lockChannel(q):

+  if q.mask != ChannelDeadMask:
+    if tryAcquireSys(q.lock):

       llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
-      result.dataAvaliable = true

+      result.dataAvailable = true

+      releaseSys(q.lock)

 

 proc peek*[TMsg](c: var TChannel[TMsg]): int =

   ## returns the current number of messages in the channel `c`. Returns -1

diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
new file mode 100644
index 000000000..e7eb1cdb4
--- /dev/null
+++ b/lib/system/deepcopy.nim
@@ -0,0 +1,141 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) {.gcsafe.}
+proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  case n.kind
+  of nkSlot:
+    genericDeepCopyAux(cast[pointer](d +% n.offset), 
+                       cast[pointer](s +% n.offset), n.typ)
+  of nkList:
+    for i in 0..n.len-1:
+      genericDeepCopyAux(dest, src, n.sons[i])
+  of nkCase:
+    var dd = selectBranch(dest, n)
+    var m = selectBranch(src, n)
+    # reset if different branches are in use; note different branches also
+    # imply that's not self-assignment (``x = x``)!
+    if m != dd and dd != nil: 
+      genericResetAux(dest, dd)
+    copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
+            n.typ.size)
+    if m != nil:
+      genericDeepCopyAux(dest, src, m)
+  of nkNone: sysAssert(false, "genericDeepCopyAux")
+
+proc copyDeepString(src: NimString): NimString {.inline.} =
+  if src != nil:
+    result = rawNewString(src.space)
+    result.len = src.len
+    c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
+
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  sysAssert(mt != nil, "genericDeepCopyAux 2")
+  case mt.kind
+  of tyString:
+    var x = cast[PPointer](dest)
+    var s2 = cast[PPointer](s)[]
+    if s2 == nil:
+      unsureAsgnRef(x, s2)
+    else:
+      unsureAsgnRef(x, copyDeepString(cast[NimString](s2)))
+  of tySequence:
+    var s2 = cast[PPointer](src)[]
+    var seq = cast[PGenericSeq](s2)
+    var x = cast[PPointer](dest)
+    if s2 == nil:
+      unsureAsgnRef(x, s2)
+      return
+    sysAssert(dest != nil, "genericDeepCopyAux 3")
+    unsureAsgnRef(x, newSeq(mt, seq.len))
+    var dst = cast[TAddress](cast[PPointer](dest)[])
+    for i in 0..seq.len-1:
+      genericDeepCopyAux(
+        cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
+        cast[pointer](cast[TAddress](s2) +% i *% mt.base.size +%
+                     GenericSeqSize),
+        mt.base)
+  of tyObject:
+    # we need to copy m_type field for tyObject, as it could be empty for
+    # sequence reallocations:
+    var pint = cast[ptr PNimType](dest)
+    pint[] = cast[ptr PNimType](src)[]
+    if mt.base != nil:
+      genericDeepCopyAux(dest, src, mt.base)
+    genericDeepCopyAux(dest, src, mt.node)
+  of tyTuple:
+    genericDeepCopyAux(dest, src, mt.node)
+  of tyArray, tyArrayConstr:
+    for i in 0..(mt.size div mt.base.size)-1:
+      genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size),
+                         cast[pointer](s +% i*% mt.base.size), mt.base)
+  of tyRef:
+    if mt.base.deepCopy != nil:
+      let z = mt.base.deepCopy(cast[PPointer](src)[])
+      unsureAsgnRef(cast[PPointer](dest), z)
+    else:
+      # we modify the header of the cell temporarily; instead of the type
+      # field we store a forwarding pointer. XXX This is bad when the cloning
+      # fails due to OOM etc.
+      let s2 = cast[PPointer](src)[]
+      if s2 == nil:
+        unsureAsgnRef(cast[PPointer](dest), s2)
+        return
+      when declared(usrToCell):
+        # unfortunately we only have cycle detection for our native GCs.
+        let x = usrToCell(s2)
+        let forw = cast[int](x.typ)
+        if (forw and 1) == 1:
+          # we stored a forwarding pointer, so let's use that:
+          let z = cast[pointer](forw and not 1)
+          unsureAsgnRef(cast[PPointer](dest), z)
+        else:
+          let realType = x.typ
+          let z = newObj(realType, realType.base.size)
+          
+          unsureAsgnRef(cast[PPointer](dest), z)
+          x.typ = cast[PNimType](cast[int](z) or 1)
+          genericDeepCopyAux(z, s2, realType.base)
+          x.typ = realType
+      else:
+        let realType = mt
+        let z = newObj(realType, realType.base.size)        
+        unsureAsgnRef(cast[PPointer](dest), z)
+        genericDeepCopyAux(z, s2, realType.base)        
+  of tyPtr:
+    # no cycle check here, but also not really required
+    if mt.base.deepCopy != nil:
+      cast[PPointer](dest)[] = mt.base.deepCopy(cast[PPointer](s)[])
+    else:
+      cast[PPointer](dest)[] = cast[PPointer](s)[]
+  else:
+    copyMem(dest, src, mt.size)
+
+proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
+  genericDeepCopyAux(dest, src, mt)
+
+proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
+  # also invoked for 'string'
+  var src = src
+  genericDeepCopy(dest, addr(src), mt)
+
+proc genericDeepCopyOpenArray(dest, src: pointer, len: int,
+                            mt: PNimType) {.compilerproc.} =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  for i in 0..len-1:
+    genericDeepCopy(cast[pointer](d +% i*% mt.base.size),
+                    cast[pointer](s +% i*% mt.base.size), mt.base)
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index e1a5a958f..3c5436afb 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -38,11 +38,11 @@ proc chckRangeF(x, a, b: float): float {.inline, compilerproc, gcsafe.}
 proc chckNil(p: pointer) {.noinline, compilerproc, gcsafe.}
 
 var
-  framePtr {.rtlThreadVar.}: PFrame
-  excHandler {.rtlThreadVar.}: PSafePoint
+  framePtr {.threadvar.}: PFrame
+  excHandler {.threadvar.}: PSafePoint
     # list of exception handlers
     # a global variable for the root of all try blocks
-  currException {.rtlThreadVar.}: ref E_Base
+  currException {.threadvar.}: ref E_Base
 
 proc popFrame {.compilerRtl, inl.} =
   framePtr = framePtr.prev
@@ -307,7 +307,7 @@ when not defined(noSignalHandler):
         action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
       else:
         block platformSpecificSignal:
-          when defined(SIGPIPE):
+          when declared(SIGPIPE):
             if s == SIGPIPE:
               action("SIGPIPE: Pipe closed.\n")
               break platformSpecificSignal
@@ -336,7 +336,7 @@ when not defined(noSignalHandler):
     c_signal(SIGFPE, signalHandler)
     c_signal(SIGILL, signalHandler)
     c_signal(SIGBUS, signalHandler)
-    when defined(SIGPIPE):
+    when declared(SIGPIPE):
       c_signal(SIGPIPE, signalHandler)
 
   registerSignalHandler() # call it in initialization section
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 3b85fe600..0c1fc7748 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -30,7 +30,7 @@ const
                                           # cycles instead of the complex
                                           # algorithm
 
-when withRealTime and not defined(getTicks):
+when withRealTime and not declared(getTicks):
   include "system/timers"
 when defined(memProfiler):
   proc nimProfile(requestedSize: int)
@@ -413,7 +413,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
 {.push stackTrace: off, profiler:off.}
 proc gcInvariant*() =
   sysAssert(allocInv(gch.region), "injected")
-  when defined(markForDebug):
+  when declared(markForDebug):
     markForDebug(gch)
 {.pop.}
 
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index 31c99a601..132da9885 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -26,7 +26,7 @@ const
                       # this seems to be a good value
   withRealTime = defined(useRealtimeGC)
 
-when withRealTime and not defined(getTicks):
+when withRealTime and not declared(getTicks):
   include "system/timers"
 when defined(memProfiler):
   proc nimProfile(requestedSize: int)
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index 64174e60f..ef8f50831 100644
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-when defined(NimString): 
+when declared(NimString): 
   # we are in system module:
   {.pragma: codegenType, compilerproc.}
 else:
@@ -86,6 +86,7 @@ type
     node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum
     finalizer: pointer # the finalizer for the type
     marker: proc (p: pointer, op: int) {.nimcall, gcsafe.} # marker proc for GC
+    deepcopy: proc (p: pointer): pointer {.nimcall, gcsafe.}
   PNimType = ptr TNimType
   
 # node.len may be the ``first`` element of a set
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 8766906e3..423f63e2a 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -515,7 +515,7 @@ proc isFatPointer(ti: PNimType): bool =
 
 proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
 
-proc nimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.compilerproc.} =
+proc nimCopyAux(dest, src: pointer, n: ptr TNimNode) {.compilerproc.} =
   case n.kind
   of nkNone: sysAssert(false, "nimCopyAux")
   of nkSlot:
@@ -566,7 +566,7 @@ proc nimCopy(x: pointer, ti: PNimType): pointer =
   else:
     result = x
 
-proc genericReset(x: Pointer, ti: PNimType): pointer {.compilerproc.} =
+proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} =
   case ti.kind
   of tyPtr, tyRef, tyVar, tyNil:
     if not isFatPointer(ti):
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index a09b6cf93..606743f51 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -131,6 +131,14 @@ when defined(boehmgc):
       if result == nil: raiseOutOfMem()
     proc deallocShared(p: pointer) = boehmDealloc(p)
 
+    when hasThreadSupport:
+      proc getFreeSharedMem(): int =
+        boehmGetFreeBytes()
+      proc getTotalSharedMem(): int =
+        boehmGetHeapSize()
+      proc getOccupiedSharedMem(): int =
+        getTotalSharedMem() - getFreeSharedMem()
+
     #boehmGCincremental()
 
     proc GC_disable() = boehmGC_disable()
@@ -164,11 +172,11 @@ when defined(boehmgc):
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
   
-  proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
   type
@@ -180,7 +188,7 @@ when defined(boehmgc):
   proc alloc0(r: var TMemRegion, size: int): pointer =
     result = alloc(size)
     zeroMem(result, size)
-  proc dealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p)  
+  proc dealloc(r: var TMemRegion, p: pointer) = boehmDealloc(p)  
   proc deallocOsPages(r: var TMemRegion) {.inline.} = discard
   proc deallocOsPages() {.inline.} = discard
 
@@ -239,11 +247,11 @@ elif defined(nogc) and defined(useMalloc):
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
   
-  proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
   type
@@ -292,11 +300,11 @@ elif defined(nogc):
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
   
-  proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
   var allocator {.rtlThreadVar.}: TMemRegion
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index f8f949668..8e1bc5f26 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -121,7 +121,7 @@ proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
 type
   TReprClosure {.final.} = object # we cannot use a global variable here
                                   # as this wouldn't be thread-safe
-    when defined(TCellSet):
+    when declared(TCellSet):
       marked: TCellSet
     recdepth: int       # do not recurse endlessly
     indent: int         # indentation
@@ -130,16 +130,16 @@ when not defined(useNimRtl):
   proc initReprClosure(cl: var TReprClosure) =
     # Important: cellsets does not lock the heap when doing allocations! We
     # have to do it here ...
-    when hasThreadSupport and hasSharedHeap and defined(heapLock):
+    when hasThreadSupport and hasSharedHeap and declared(heapLock):
       AcquireSys(HeapLock)
-    when defined(TCellSet):
+    when declared(TCellSet):
       init(cl.marked)
     cl.recdepth = -1      # default is to display everything!
     cl.indent = 0
 
   proc deinitReprClosure(cl: var TReprClosure) =
-    when defined(TCellSet): deinit(cl.marked)
-    when hasThreadSupport and hasSharedHeap and defined(heapLock): 
+    when declared(TCellSet): deinit(cl.marked)
+    when hasThreadSupport and hasSharedHeap and declared(heapLock): 
       ReleaseSys(HeapLock)
 
   proc reprBreak(result: var string, cl: TReprClosure) =
@@ -201,7 +201,7 @@ when not defined(useNimRtl):
   proc reprRef(result: var string, p: pointer, typ: PNimType,
                cl: var TReprClosure) =
     # we know that p is not nil here:
-    when defined(TCellSet):
+    when declared(TCellSet):
       when defined(boehmGC) or defined(nogc):
         var cell = cast[PCell](p)
       else:
@@ -221,7 +221,7 @@ when not defined(useNimRtl):
     dec(cl.recdepth)
     case typ.kind
     of tySet: reprSetAux(result, p, typ)
-    of tyArray: reprArray(result, p, typ, cl)
+    of tyArray, tyArrayConstr: reprArray(result, p, typ, cl)
     of tyTuple: reprRecord(result, p, typ, cl)
     of tyObject: 
       var t = cast[ptr PNimType](p)[]
@@ -275,7 +275,7 @@ when not defined(useNimRtl):
       cl: TReprClosure
     initReprClosure(cl)
     result = ""
-    if typ.kind in {tyObject, tyTuple, tyArray, tySet}:
+    if typ.kind in {tyObject, tyTuple, tyArray, tyArrayConstr, tySet}:
       reprAux(result, p, typ, cl)
     else:
       var p = p
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index 95cdba65d..5161104a9 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -9,7 +9,7 @@
 
 ## Implements Nimrod's 'spawn'.
 
-when not defined(NimString): 
+when not declared(NimString): 
   {.error: "You must not import this module explicitly".}
 
 {.push stackTrace:off.}
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 9db8ce378..bc79bb254 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -32,7 +32,7 @@ proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
   return a.len == b.len and
     c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32
 
-when defined(allocAtomic):
+when declared(allocAtomic):
   template allocStr(size: expr): expr =
     cast[NimString](allocAtomic(size))
 else:
@@ -85,7 +85,7 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
   if src != nil:
     var s = src.space
     if s < 8: s = 7
-    when defined(newObjRC1):
+    when declared(newObjRC1):
       result = cast[NimString](newObjRC1(addr(strDesc), sizeof(TGenericSeq) +
                                s+1))
     else:
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index d3b3aa457..c30c57fb9 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -1,17 +1,17 @@
 #
 #
-#            Nimrod's Runtime Library
+#            Nim's Runtime Library
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## Thread support for Nimrod. **Note**: This is part of the system module.
+## Thread support for Nim. **Note**: This is part of the system module.
 ## Do not import it directly. To activate thread support you need to compile
 ## with the ``--threads:on`` command line switch.
 ##
-## Nimrod's memory model for threads is quite different from other common 
+## Nim's memory model for threads is quite different from other common 
 ## programming languages (C, Pascal): Each thread has its own
 ## (garbage collected) heap and sharing of memory is restricted. This helps
 ## to prevent race conditions and improves efficiency. See `the manual for
@@ -19,7 +19,7 @@
 ##
 ## Example:
 ##
-## .. code-block:: nimrod
+## .. code-block:: Nim
 ##
 ##  import locks
 ##
@@ -39,7 +39,7 @@
 ##    createThread(thr[i], threadFunc, (i*10, i*10+5))
 ##  joinThreads(thr)
   
-when not defined(NimString): 
+when not declared(NimString): 
   {.error: "You must not import this module explicitly".}
 
 const
@@ -190,7 +190,7 @@ var globalsSlot = threadVarAlloc()
 
 when emulatedThreadVars:
   proc GetThreadLocalVars(): pointer {.compilerRtl, inl.} =
-    result = addr(cast[PGcThread](ThreadVarGetValue(globalsSlot)).tls)
+    result = addr(cast[PGcThread](threadVarGetValue(globalsSlot)).tls)
 
 when useStackMaskHack:
   proc maskStackPointer(offset: int): pointer {.compilerRtl, inl.} =
@@ -210,7 +210,7 @@ when not defined(useNimRtl):
     initGC()
     
   when emulatedThreadVars:
-    if NimThreadVarsSize() > sizeof(TThreadLocalStorage):
+    if nimThreadVarsSize() > sizeof(TThreadLocalStorage):
       echo "too large thread local storage size requested"
       quit 1
   
@@ -245,14 +245,14 @@ when not defined(useNimRtl):
     # the GC can examine the stacks?
     proc stopTheWord() = discard
     
-# We jump through some hops here to ensure that Nimrod thread procs can have
-# the Nimrod calling convention. This is needed because thread procs are 
+# We jump through some hops here to ensure that Nim thread procs can have
+# the Nim calling convention. This is needed because thread procs are 
 # ``stdcall`` on Windows and ``noconv`` on UNIX. Alternative would be to just
 # use ``stdcall`` since it is mapped to ``noconv`` on UNIX anyway.
 
 type
   TThread* {.pure, final.}[TArg] =
-      object of TGcThread ## Nimrod thread. A thread is a heavy object (~14K)
+      object of TGcThread ## Nim thread. A thread is a heavy object (~14K)
                           ## that **must not** be part of a message! Use
                           ## a ``TThreadId`` for that.
     when TArg is void:
@@ -267,7 +267,7 @@ when not defined(boehmgc) and not hasSharedHeap:
   proc deallocOsPages()
 
 template threadProcWrapperBody(closure: expr) {.immediate.} =
-  when defined(globalsSlot): ThreadVarSetValue(globalsSlot, closure)
+  when declared(globalsSlot): threadVarSetValue(globalsSlot, closure)
   var t = cast[ptr TThread[TArg]](closure)
   when useStackMaskHack:
     var tls: TThreadLocalStorage
@@ -275,13 +275,13 @@ template threadProcWrapperBody(closure: expr) {.immediate.} =
     # init the GC for this thread:
     setStackBottom(addr(t))
     initGC()
-  when defined(registerThread):
+  when declared(registerThread):
     t.stackBottom = addr(t)
     registerThread(t)
   when TArg is void: t.dataFn()
   else: t.dataFn(t.data)
-  when defined(registerThread): unregisterThread(t)
-  when defined(deallocOsPages): deallocOsPages()
+  when declared(registerThread): unregisterThread(t)
+  when declared(deallocOsPages): deallocOsPages()
   # Since an unhandled exception terminates the whole process (!), there is
   # no need for a ``try finally`` here, nor would it be correct: The current
   # exception is tried to be re-raised by the code-gen after the ``finally``!
@@ -305,22 +305,26 @@ proc running*[TArg](t: TThread[TArg]): bool {.inline.} =
   ## returns true if `t` is running.
   result = t.dataFn != nil
 
-proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = 
-  ## waits for the thread `t` to finish.
-  when hostOS == "windows":
+when hostOS == "windows":
+  proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = 
+    ## waits for the thread `t` to finish.
     discard waitForSingleObject(t.sys, -1'i32)
-  else:
-    discard pthread_join(t.sys, nil)
 
-proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = 
-  ## waits for every thread in `t` to finish.
-  when hostOS == "windows":
+  proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = 
+    ## waits for every thread in `t` to finish.
     var a: array[0..255, TSysThread]
     sysAssert a.len >= t.len, "a.len >= t.len"
     for i in 0..t.high: a[i] = t[i].sys
-    discard waitForMultipleObjects(t.len.int32, 
+    discard waitForMultipleObjects(t.len.int32,
                                    cast[ptr TSysThread](addr(a)), 1, -1)
-  else:
+
+else:
+  proc joinThread*[TArg](t: TThread[TArg]) {.inline.} =
+    ## waits for the thread `t` to finish.
+    discard pthread_join(t.sys, nil)
+
+  proc joinThreads*[TArg](t: varargs[TThread[TArg]]) =
+    ## waits for every thread in `t` to finish.
     for i in 0..t.high: joinThread(t[i])
 
 when false:
@@ -332,25 +336,35 @@ when false:
       discard TerminateThread(t.sys, 1'i32)
     else:
       discard pthread_cancel(t.sys)
-    when defined(registerThread): unregisterThread(addr(t))
+    when declared(registerThread): unregisterThread(addr(t))
     t.dataFn = nil
 
-proc createThread*[TArg](t: var TThread[TArg], 
-                         tp: proc (arg: TArg) {.thread.}, 
-                         param: TArg) =
-  ## creates a new thread `t` and starts its execution. Entry point is the
-  ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
-  ## don't need to pass any data to the thread.
-  when TArg isnot void: t.data = param
-  t.dataFn = tp
-  when hasSharedHeap: t.stackSize = ThreadStackSize
-  when hostOS == "windows":
+when hostOS == "windows":
+  proc createThread*[TArg](t: var TThread[TArg],
+                           tp: proc (arg: TArg) {.thread.}, 
+                           param: TArg) =
+    ## creates a new thread `t` and starts its execution. Entry point is the
+    ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
+    ## don't need to pass any data to the thread.
+    when TArg isnot void: t.data = param
+    t.dataFn = tp
+    when hasSharedHeap: t.stackSize = ThreadStackSize
     var dummyThreadId: int32
     t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg],
                          addr(t), 0'i32, dummyThreadId)
     if t.sys <= 0:
       raise newException(EResourceExhausted, "cannot create thread")
-  else:
+
+else:
+  proc createThread*[TArg](t: var TThread[TArg], 
+                           tp: proc (arg: TArg) {.thread.}, 
+                           param: TArg) =
+    ## creates a new thread `t` and starts its execution. Entry point is the
+    ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
+    ## don't need to pass any data to the thread.
+    when TArg isnot void: t.data = param
+    t.dataFn = tp
+    when hasSharedHeap: t.stackSize = ThreadStackSize
     var a {.noinit.}: Tpthread_attr
     pthread_attr_init(a)
     pthread_attr_setstacksize(a, ThreadStackSize)
@@ -364,7 +378,7 @@ proc threadId*[TArg](t: var TThread[TArg]): TThreadId[TArg] {.inline.} =
 proc myThreadId*[TArg](): TThreadId[TArg] =
   ## returns the thread ID of the thread that calls this proc. This is unsafe
   ## because the type ``TArg`` is not checked for consistency!
-  result = cast[TThreadId[TArg]](ThreadVarGetValue(globalsSlot))
+  result = cast[TThreadId[TArg]](threadVarGetValue(globalsSlot))
 
 when false:
   proc mainThreadId*[TArg](): TThreadId[TArg] =
diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim
index e2a5d87e9..cd64ff410 100644
--- a/lib/system/widestrs.nim
+++ b/lib/system/widestrs.nim
@@ -7,10 +7,10 @@
 #    distribution, for details about the copyright.
 #
 
-## Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system
-## module! Do not import it directly!
+# Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system
+# module! Do not import it directly!
 
-when not defined(NimString):
+when not declared(NimString):
   {.error: "You must not import this module explicitly".}
 
 type
@@ -103,7 +103,7 @@ proc newWideCString*(source: cstring, L: int): WideCString =
 proc newWideCString*(s: cstring): WideCString =
   if s.isNil: return nil
 
-  when not defined(c_strlen):
+  when not declared(c_strlen):
     proc c_strlen(a: cstring): int {.
       header: "<string.h>", noSideEffect, importc: "strlen".}
 
diff --git a/lib/windows/ole2.nim b/lib/windows/ole2.nim
deleted file mode 100644
index ec0ab8f5d..000000000
--- a/lib/windows/ole2.nim
+++ /dev/null
@@ -1,208 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2006 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-import 
-  windows
-
-const 
-  GUID_NULL*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000000])
-  IID_IUnknown*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IClassFactory*: TGUID = (D1: 0x00000001, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IMarshal*: TGUID = (D1: 0x00000003, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IMalloc*: TGUID = (D1: 0x00000002, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IStdMarshalInfo*: TGUID = (D1: 0x00000018, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IExternalConnection*: TGUID = (D1: 0x00000019, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IEnumUnknown*: TGUID = (D1: 0x00000100, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IBindCtx*: TGUID = (D1: 0x0000000E, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumMoniker*: TGUID = (D1: 0x00000102, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRunnableObject*: TGUID = (D1: 0x00000126, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRunningObjectTable*: TGUID = (D1: 0x00000010, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IPersist*: TGUID = (D1: 0x0000010C, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IPersistStream*: TGUID = (D1: 0x00000109, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IMoniker*: TGUID = (D1: 0x0000000F, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumString*: TGUID = (D1: 0x00000101, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IStream*: TGUID = (D1: 0x0000000C, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumStatStg*: TGUID = (D1: 0x0000000D, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IStorage*: TGUID = (D1: 0x0000000B, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IPersistFile*: TGUID = (D1: 0x0000010B, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IPersistStorage*: TGUID = (D1: 0x0000010A, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ILockBytes*: TGUID = (D1: 0x0000000A, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumFormatEtc*: TGUID = (D1: 0x00000103, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumStatData*: TGUID = (D1: 0x00000105, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRootStorage*: TGUID = (D1: 0x00000012, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IAdviseSink*: TGUID = (D1: 0x0000010F, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IAdviseSink2*: TGUID = (D1: 0x00000125, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDataObject*: TGUID = (D1: 0x0000010E, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDataAdviseHolder*: TGUID = (D1: 0x00000110, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IMessageFilter*: TGUID = (D1: 0x00000016, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRpcChannelBuffer*: TGUID = (D1: 0xD5F56B60, D2: 0x0000593B, 
-    D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
-  IID_IRpcProxyBuffer*: TGUID = (D1: 0xD5F56A34, D2: 0x0000593B, D3: 0x0000101A, D4: [
-      0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D, 
-      0x000000BF, 0x0000007A])
-  IID_IRpcStubBuffer*: TGUID = (D1: 0xD5F56AFC, D2: 0x0000593B, D3: 0x0000101A, D4: [
-      0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D, 
-      0x000000BF, 0x0000007A])
-  IID_IPSFactoryBuffer*: TGUID = (D1: 0xD5F569D0, D2: 0x0000593B, 
-    D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
-  IID_ICreateTypeInfo*: TGUID = (D1: 0x00020405, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ICreateTypeLib*: TGUID = (D1: 0x00020406, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDispatch*: TGUID = (D1: 0x00020400, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumVariant*: TGUID = (D1: 0x00020404, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ITypeComp*: TGUID = (D1: 0x00020403, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ITypeInfo*: TGUID = (D1: 0x00020401, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ITypeLib*: TGUID = (D1: 0x00020402, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IErrorInfo*: TGUID = (D1: 0x1CF2B120, D2: 0x0000547D, D3: 0x0000101B, D4: [
-      0x0000008E, 0x00000065, 0x00000008, 0x00000000, 0x0000002B, 0x0000002B, 
-      0x000000D1, 0x00000019])
-  IID_ICreateErrorInfo*: TGUID = (D1: 0x22F03340, D2: 0x0000547D, 
-    D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
-  IID_ISupportErrorInfo*: TGUID = (D1: 0xDF0B3D60, D2: 0x0000548F, 
-    D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
-  IID_IOleAdviseHolder*: TGUID = (D1: 0x00000111, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleCache*: TGUID = (D1: 0x0000011E, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleCache2*: TGUID = (D1: 0x00000128, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleCacheControl*: TGUID = (D1: 0x00000129, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IParseDisplayName*: TGUID = (D1: 0x0000011A, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleContainer*: TGUID = (D1: 0x0000011B, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleClientSite*: TGUID = (D1: 0x00000118, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleObject*: TGUID = (D1: 0x00000112, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleWindow*: TGUID = (D1: 0x00000114, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleLink*: TGUID = (D1: 0x0000011D, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleItemContainer*: TGUID = (D1: 0x0000011C, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceUIWindow*: TGUID = (D1: 0x00000115, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceActiveObject*: TGUID = (D1: 0x00000117, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceFrame*: TGUID = (D1: 0x00000116, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceObject*: TGUID = (D1: 0x00000113, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceSite*: TGUID = (D1: 0x00000119, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IViewObject*: TGUID = (D1: 0x0000010D, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IViewObject2*: TGUID = (D1: 0x00000127, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDropSource*: TGUID = (D1: 0x00000121, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDropTarget*: TGUID = (D1: 0x00000122, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumOleVerb*: TGUID = (D1: 0x00000104, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index dcae6ffaf..09696b67f 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -664,6 +664,7 @@ const
   WSAEDISCON* = 10101
   WSAENETRESET* = 10052
   WSAETIMEDOUT* = 10060
+  ERROR_NETNAME_DELETED* = 64
 
 proc CreateIoCompletionPort*(FileHandle: THANDLE, ExistingCompletionPort: THANDLE,
                              CompletionKey: DWORD,
diff --git a/lib/wrappers/postgres.nim b/lib/wrappers/postgres.nim
index d99e5651c..ce78d3435 100644
--- a/lib/wrappers/postgres.nim
+++ b/lib/wrappers/postgres.nim
@@ -213,6 +213,8 @@ proc PQexecParams*(conn: PPGconn, command: cstring, nParams: int32,
                    paramTypes: POid, paramValues: cstringArray, 
                    paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
     cdecl, dynlib: dllName, importc: "PQexecParams".}
+proc PQprepare*(conn: PPGconn, stmtName, query: cstring, nParams: int32,
+    paramTypes: POid): PPGresult{.cdecl, dynlib: dllName, importc: "PQprepare".}
 proc PQexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32, 
                      paramValues: cstringArray, 
                      paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
diff --git a/lib/wrappers/sdl/sdl_ttf.nim b/lib/wrappers/sdl/sdl_ttf.nim
index f501e31d8..45247df4d 100644
--- a/lib/wrappers/sdl/sdl_ttf.nim
+++ b/lib/wrappers/sdl/sdl_ttf.nim
@@ -333,11 +333,5 @@ proc VERSION*(X: var sdl.Tversion) =
   X.patch = PATCHLEVEL
 
 
-when not (defined(Workaround_RenderText_Solid)): 
-  proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{.
-      cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.}
-else: 
-  proc RenderText_Solid(font: PFont, text: cstring, fg: TColor): PSurface = 
-    var Black: TColor         # initialized to zero
-    result = RenderText_Shaded(font, text, fg, Black)
-
+proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{.
+    cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.}
diff --git a/lib/wrappers/zmq.nim b/lib/wrappers/zmq.nim
deleted file mode 100644
index 9826ab813..000000000
--- a/lib/wrappers/zmq.nim
+++ /dev/null
@@ -1,322 +0,0 @@
-# Nimrod wrapper of 0mq
-# Generated by c2nim with modifications and enhancement from Andreas Rumpf
-# Original licence follows:
-
-#
-#    Copyright (c) 2007-2011 iMatix Corporation
-#    Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
-#
-#    This file is part of 0MQ.
-#
-#    0MQ is free software; you can redistribute it and/or modify it under
-#    the terms of the GNU Lesser General Public License as published by
-#    the Free Software Foundation; either version 3 of the License, or
-#    (at your option) any later version.
-#
-#    0MQ is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU Lesser General Public License for more details.
-#
-#    You should have received a copy of the GNU Lesser General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-
-# Generated from zmq version 2.1.5
-
-## Nimrod 0mq wrapper. This file contains the low level C wrappers as well as
-## some higher level constructs. The higher level constructs are easily
-## recognizable because they are the only ones that have documentation.
-##
-## Example of a client:
-## 
-## .. code-block:: nimrod
-##   import zmq
-##   
-##   var connection = zmq.open("tcp://localhost:5555", server=false)
-##   echo("Connecting...")
-##   for i in 0..10:
-##     echo("Sending hello...", i)
-##     send(connection, "Hello")
-##     var reply = receive(connection)
-##     echo("Received ...", reply)
-##   close(connection)
-##
-## Example of a server:
-##
-## .. code-block:: nimrod
-##   
-##   import zmq
-##   var connection = zmq.open("tcp://*:5555", server=true)
-##   while True:
-##     var request = receive(connection)
-##     echo("Received: ", request)
-##     send(connection, "World")
-##   close(connection)
-
-{.deadCodeElim: on.}
-when defined(windows): 
-  const 
-    zmqdll* = "zmq.dll"
-elif defined(macosx): 
-  const 
-    zmqdll* = "libzmq.dylib"
-else:
-  const 
-    zmqdll* = "libzmq.so"
-
-# A number random enough not to collide with different errno ranges on      
-# different OSes. The assumption is that error_t is at least 32-bit type.  
-const 
-  HAUSNUMERO* = 156384712
-  # On Windows platform some of the standard POSIX errnos are not defined.    
-  ENOTSUP* = (HAUSNUMERO + 1)
-  EPROTONOSUPPORT* = (HAUSNUMERO + 2)
-  ENOBUFS* = (HAUSNUMERO + 3)
-  ENETDOWN* = (HAUSNUMERO + 4)
-  EADDRINUSE* = (HAUSNUMERO + 5)
-  EADDRNOTAVAIL* = (HAUSNUMERO + 6)
-  ECONNREFUSED* = (HAUSNUMERO + 7)
-  EINPROGRESS* = (HAUSNUMERO + 8)
-  # Native 0MQ error codes.  
-  EFSM* = (HAUSNUMERO + 51)
-  ENOCOMPATPROTO* = (HAUSNUMERO + 52)
-  ETERM* = (HAUSNUMERO + 53)
-  EMTHREAD* = (HAUSNUMERO + 54)
-  #  Maximal size of "Very Small Message". VSMs are passed by value            
-  #  to avoid excessive memory allocation/deallocation.                        
-  #  If VMSs larger than 255 bytes are required, type of 'vsm_size'            
-  #  field in msg_t structure should be modified accordingly.
-  MAX_VSM_SIZE* = 30
-
-  POLLIN* = 1
-  POLLOUT* = 2
-  POLLERR* = 4
-
-  STREAMER* = 1
-  FORWARDER* = 2
-  QUEUE* = 3
-
-  PAIR* = 0
-  PUB* = 1
-  SUB* = 2
-  REQ* = 3
-  REP* = 4
-  DEALER* = 5
-  ROUTER* = 6
-  PULL* = 7
-  PUSH* = 8
-  XPUB* = 9
-  XSUB* = 10
-  XREQ* = DEALER      #  Old alias, remove in 3.x               
-  XREP* = ROUTER      #  Old alias, remove in 3.x               
-  UPSTREAM* = PULL    #  Old alias, remove in 3.x               
-  DOWNSTREAM* = PUSH  #  Old alias, remove in 3.x        
-
-type
-  #  Message types. These integers may be stored in 'content' member of the    
-  #  message instead of regular pointer to the data. 
-  TMsgTypes* = enum
-    DELIMITER = 31,
-    VSM = 32
-  #  Message flags. MSG_SHARED is strictly speaking not a message flag     
-  #  (it has no equivalent in the wire format), however, making  it a flag     
-  #  allows us to pack the stucture tighter and thus improve performance.   
-  TMsgFlags* = enum 
-    MSG_MORE = 1,
-    MSG_SHARED = 128,
-    MSG_MASK = 129         # Merges all the flags 
-  #  A message. Note that 'content' is not a pointer to the raw data.          
-  #  Rather it is pointer to zmq::msg_content_t structure                      
-  #  (see src/msg_content.hpp for its definition).    
-  TMsg*{.pure, final.} = object 
-    content*: pointer
-    flags*: char
-    vsm_size*: char
-    vsm_data*: array[0..MAX_VSM_SIZE - 1, char]
-
-  TFreeFn = proc (data, hint: pointer) {.noconv.}
-
-  TContext {.final, pure.} = object
-  PContext* = ptr TContext
-  
-  # Socket Types
-  TSocket {.final, pure.} = object
-  PSocket* = ptr TSocket       
-
-  #  Socket options.                                                           
-  TSockOptions* = enum
-    HWM = 1,
-    SWAP = 3,
-    AFFINITY = 4,
-    IDENTITY = 5,
-    SUBSCRIBE = 6,
-    UNSUBSCRIBE = 7,
-    RATE = 8,
-    RECOVERY_IVL = 9,
-    MCAST_LOOP = 10,
-    SNDBUF = 11,
-    RCVBUF = 12,
-    RCVMORE = 13,
-    FD = 14,
-    EVENTS = 15,
-    theTYPE = 16,
-    LINGER = 17,
-    RECONNECT_IVL = 18,
-    BACKLOG = 19,
-    RECOVERY_IVL_MSEC = 20, #  opt. recovery time, reconcile in 3.x   
-    RECONNECT_IVL_MAX = 21
-
-  #  Send/recv options.                                                        
-  TSendRecvOptions* = enum
-    NOBLOCK, SNDMORE
-  
-  TPollItem*{.pure, final.} = object 
-    socket*: PSocket
-    fd*: cint
-    events*: cshort
-    revents*: cshort
-  
-#  Run-time API version detection                                            
-
-proc version*(major: var cint, minor: var cint, patch: var cint){.cdecl, 
-    importc: "zmq_version", dynlib: zmqdll.}
-#****************************************************************************
-#  0MQ errors.                                                               
-#****************************************************************************
-
-#  This function retrieves the errno as it is known to 0MQ library. The goal 
-#  of this function is to make the code 100% portable, including where 0MQ   
-#  compiled with certain CRT library (on Windows) is linked to an            
-#  application that uses different CRT library.                              
-
-proc errno*(): cint{.cdecl, importc: "zmq_errno", dynlib: zmqdll.}
-#  Resolves system errors and 0MQ errors to human-readable string.
-
-proc strerror*(errnum: cint): cstring {.cdecl, importc: "zmq_strerror", 
-    dynlib: zmqdll.}
-#****************************************************************************
-#  0MQ message definition.                                                   
-#****************************************************************************
-
-proc msg_init*(msg: var TMsg): cint{.cdecl, importc: "zmq_msg_init", 
-    dynlib: zmqdll.}
-proc msg_init*(msg: var TMsg, size: int): cint{.cdecl, 
-    importc: "zmq_msg_init_size", dynlib: zmqdll.}
-proc msg_init*(msg: var TMsg, data: cstring, size: int, 
-               ffn: TFreeFn, hint: pointer): cint{.cdecl, 
-    importc: "zmq_msg_init_data", dynlib: zmqdll.}
-proc msg_close*(msg: var TMsg): cint {.cdecl, importc: "zmq_msg_close", 
-    dynlib: zmqdll.}
-proc msg_move*(dest, src: var TMsg): cint{.cdecl, 
-    importc: "zmq_msg_move", dynlib: zmqdll.}
-proc msg_copy*(dest, src: var TMsg): cint{.cdecl, 
-    importc: "zmq_msg_copy", dynlib: zmqdll.}
-proc msg_data*(msg: var TMsg): cstring {.cdecl, importc: "zmq_msg_data", 
-    dynlib: zmqdll.}
-proc msg_size*(msg: var TMsg): int {.cdecl, importc: "zmq_msg_size", 
-    dynlib: zmqdll.}
-    
-#****************************************************************************
-#  0MQ infrastructure (a.k.a. context) initialisation & termination.         
-#****************************************************************************
-
-proc init*(io_threads: cint): PContext {.cdecl, importc: "zmq_init", 
-    dynlib: zmqdll.}
-proc term*(context: PContext): cint {.cdecl, importc: "zmq_term", 
-                                        dynlib: zmqdll.}
-#****************************************************************************
-#  0MQ socket definition.                                                    
-#****************************************************************************                                                         
-
-proc socket*(context: PContext, theType: cint): PSocket {.cdecl, 
-    importc: "zmq_socket", dynlib: zmqdll.}
-proc close*(s: PSocket): cint{.cdecl, importc: "zmq_close", dynlib: zmqdll.}
-proc setsockopt*(s: PSocket, option: cint, optval: pointer, 
-                     optvallen: int): cint {.cdecl, importc: "zmq_setsockopt", 
-    dynlib: zmqdll.}
-proc getsockopt*(s: PSocket, option: cint, optval: pointer, 
-                 optvallen: ptr int): cint{.cdecl, 
-    importc: "zmq_getsockopt", dynlib: zmqdll.}
-proc bindAddr*(s: PSocket, address: cstring): cint{.cdecl, importc: "zmq_bind", 
-    dynlib: zmqdll.}
-proc connect*(s: PSocket, address: cstring): cint{.cdecl, 
-    importc: "zmq_connect", dynlib: zmqdll.}
-proc send*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, 
-    importc: "zmq_send", dynlib: zmqdll.}
-proc recv*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, 
-    importc: "zmq_recv", dynlib: zmqdll.}
-#****************************************************************************
-#  I/O multiplexing.                                                         
-#****************************************************************************
-
-proc poll*(items: ptr TPollItem, nitems: cint, timeout: int): cint{.
-    cdecl, importc: "zmq_poll", dynlib: zmqdll.}
-    
-#****************************************************************************
-#  Built-in devices                                                          
-#****************************************************************************
-
-proc device*(device: cint, insocket, outsocket: PSocket): cint{.
-    cdecl, importc: "zmq_device", dynlib: zmqdll.}
-    
-type
-  EZmq* = object of ESynch ## exception that is raised if something fails
-  TConnection* {.pure, final.} = object ## a connection
-    c*: PContext  ## the embedded context
-    s*: PSocket   ## the embedded socket
-  
-  TConnectionMode* = enum ## connection mode
-    conPAIR = 0,
-    conPUB = 1,
-    conSUB = 2,
-    conREQ = 3,
-    conREP = 4,
-    conDEALER = 5,
-    conROUTER = 6,
-    conPULL = 7,
-    conPUSH = 8,
-    conXPUB = 9,
-    conXSUB = 10
-  
-proc zmqError*() {.noinline, noreturn.} =
-  ## raises EZmq with error message from `zmq.strerror`.
-  var e: ref EZmq
-  new(e)
-  e.msg = $strerror(errno())
-  raise e
-  
-proc open*(address: string, server: bool, mode: TConnectionMode = conDEALER,
-           numthreads = 4): TConnection =
-  ## opens a new connection. If `server` is true, it uses `bindAddr` for the
-  ## underlying socket, otherwise it opens the socket with `connect`.
-  result.c = init(cint(numthreads))
-  if result.c == nil: zmqError()
-  result.s = socket(result.c, cint(ord(mode)))
-  if result.s == nil: zmqError()
-  if server:
-    if bindAddr(result.s, address) != 0'i32: zmqError()
-  else:
-    if connect(result.s, address) != 0'i32: zmqError()
-  
-proc close*(c: TConnection) =
-  ## closes the connection.
-  if close(c.s) != 0'i32: zmqError()
-  if term(c.c) != 0'i32: zmqError()
-  
-proc send*(c: TConnection, msg: string) =
-  ## sends a message over the connection.
-  var m: TMsg
-  if msg_init(m, msg.len) != 0'i32: zmqError()
-  copyMem(msg_data(m), cstring(msg), msg.len)
-  if send(c.s, m, 0'i32) != 0'i32: zmqError()
-  discard msg_close(m)
-  
-proc receive*(c: TConnection): string =
-  ## receives a message from a connection.
-  var m: TMsg
-  if msg_init(m) != 0'i32: zmqError()
-  if recv(c.s, m, 0'i32) != 0'i32: zmqError()
-  result = newString(msg_size(m))
-  copyMem(addr(result[0]), msg_data(m), result.len)
-  discard msg_close(m)