summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/core/locks.nim2
-rw-r--r--lib/core/macros.nim419
-rw-r--r--lib/core/typeinfo.nim4
-rw-r--r--lib/core/unsigned.nim32
-rw-r--r--lib/impure/db_mysql.nim10
-rw-r--r--lib/impure/db_postgres.nim8
-rw-r--r--lib/impure/db_sqlite.nim19
-rw-r--r--lib/impure/graphics.nim2
-rw-r--r--lib/impure/osinfo_posix.nim79
-rw-r--r--lib/impure/osinfo_win.nim414
-rw-r--r--lib/impure/rdstdin.nim102
-rw-r--r--lib/impure/re.nim204
-rw-r--r--lib/impure/ssl.nim2
-rw-r--r--lib/js/dom.nim219
-rw-r--r--lib/nimbase.h43
-rw-r--r--lib/nimrtl.nim.cfg (renamed from lib/nimrtl.nimrod.cfg)0
-rw-r--r--lib/packages/docutils/highlite.nim446
-rw-r--r--lib/packages/docutils/rst.nim916
-rw-r--r--lib/packages/docutils/rstast.nim93
-rw-r--r--lib/packages/docutils/rstgen.nim294
-rw-r--r--lib/posix/posix.nim59
-rw-r--r--lib/posix/termios.nim261
-rw-r--r--lib/pure/actors.nim4
-rw-r--r--lib/pure/algorithm.nim142
-rw-r--r--lib/pure/asyncdispatch.nim279
-rw-r--r--lib/pure/asyncdispatch.nim.cfg (renamed from lib/pure/asyncdispatch.nimrod.cfg)0
-rw-r--r--lib/pure/asyncfile.nim44
-rw-r--r--lib/pure/asyncftpclient.nim14
-rw-r--r--lib/pure/asynchttpserver.nim96
-rw-r--r--lib/pure/asyncio.nim104
-rw-r--r--lib/pure/asyncnet.nim122
-rw-r--r--lib/pure/basic2d.nim6
-rw-r--r--lib/pure/basic3d.nim266
-rw-r--r--lib/pure/browsers.nim2
-rw-r--r--lib/pure/collections/LockFreeHash.nim4
-rw-r--r--lib/pure/collections/critbits.nim26
-rw-r--r--lib/pure/collections/intsets.nim86
-rw-r--r--lib/pure/collections/lists.nim44
-rw-r--r--lib/pure/collections/queues.nim11
-rw-r--r--lib/pure/collections/rtarrays.nim2
-rw-r--r--lib/pure/collections/sequtils.nim83
-rw-r--r--lib/pure/collections/sets.nim513
-rw-r--r--lib/pure/collections/tables.nim423
-rw-r--r--lib/pure/colors.nim4
-rw-r--r--lib/pure/complex.nim156
-rw-r--r--lib/pure/concurrency/cpuinfo.nim2
-rw-r--r--lib/pure/concurrency/cpuload.nim4
-rw-r--r--lib/pure/concurrency/threadpool.nim4
-rw-r--r--lib/pure/cookies.nim10
-rw-r--r--lib/pure/encodings.nim6
-rw-r--r--lib/pure/events.nim2
-rw-r--r--lib/pure/fenv.nim80
-rw-r--r--lib/pure/fsmonitor.nim36
-rw-r--r--lib/pure/ftpclient.nim138
-rw-r--r--lib/pure/future.nim13
-rw-r--r--lib/pure/gentabs.nim53
-rw-r--r--lib/pure/hashes.nim4
-rw-r--r--lib/pure/htmlgen.nim189
-rw-r--r--lib/pure/htmlparser.nim6
-rw-r--r--lib/pure/httpclient.nim254
-rw-r--r--lib/pure/httpserver.nim4
-rw-r--r--lib/pure/json.nim429
-rw-r--r--lib/pure/lexbase.nim2
-rw-r--r--lib/pure/logging.nim114
-rw-r--r--lib/pure/marshal.nim57
-rw-r--r--lib/pure/matchers.nim4
-rw-r--r--lib/pure/math.nim52
-rw-r--r--lib/pure/md5.nim274
-rw-r--r--lib/pure/memfiles.nim2
-rw-r--r--lib/pure/mersenne.nim2
-rw-r--r--lib/pure/mimetypes.nim4
-rw-r--r--lib/pure/net.nim96
-rw-r--r--lib/pure/nimprof.nim2
-rw-r--r--lib/pure/nimprof.nim.cfg (renamed from lib/pure/nimprof.nimrod.cfg)0
-rw-r--r--lib/pure/oids.nim2
-rw-r--r--lib/pure/os.nim65
-rw-r--r--lib/pure/osproc.nim45
-rw-r--r--lib/pure/parsecfg.nim2
-rw-r--r--lib/pure/parsecsv.nim2
-rw-r--r--lib/pure/parseopt.nim11
-rw-r--r--lib/pure/parseopt2.nim4
-rw-r--r--lib/pure/parsesql.nim2
-rw-r--r--lib/pure/parseurl.nim2
-rw-r--r--lib/pure/parseutils.nim21
-rw-r--r--lib/pure/parsexml.nim35
-rw-r--r--lib/pure/pegs.nim356
-rw-r--r--lib/pure/pegs.nimfix1770
-rw-r--r--lib/pure/poly.nim2
-rw-r--r--lib/pure/rationals.nim289
-rw-r--r--lib/pure/rawsockets.nim5
-rw-r--r--lib/pure/rawsockets.pretty.nim426
-rw-r--r--lib/pure/redis.nim42
-rw-r--r--lib/pure/romans.nim9
-rw-r--r--lib/pure/ropes.nim170
-rw-r--r--lib/pure/selectors.nim30
-rw-r--r--lib/pure/smtp.nim4
-rw-r--r--lib/pure/smtp.nim.cfg (renamed from lib/pure/smtp.nimrod.cfg)0
-rw-r--r--lib/pure/sockets.nim8
-rw-r--r--lib/pure/streams.nim32
-rw-r--r--lib/pure/strtabs.nim12
-rw-r--r--lib/pure/strutils.nim122
-rw-r--r--lib/pure/subexes.nim22
-rw-r--r--lib/pure/terminal.nim43
-rw-r--r--lib/pure/times.nim597
-rw-r--r--lib/pure/unicode.nim2028
-rw-r--r--lib/pure/unidecode/unidecode.nim2
-rw-r--r--lib/pure/unittest.nim48
-rw-r--r--lib/pure/uri.nim104
-rw-r--r--lib/pure/xmldom.nim30
-rw-r--r--lib/pure/xmldomparser.nim2
-rw-r--r--lib/pure/xmlparser.nim6
-rw-r--r--lib/pure/xmltree.nim105
-rw-r--r--lib/system.nim654
-rw-r--r--lib/system/alloc.nim208
-rw-r--r--lib/system/arithm.nim2
-rw-r--r--lib/system/assign.nim10
-rw-r--r--lib/system/atomics.nim113
-rw-r--r--lib/system/cgprocs.nim2
-rw-r--r--lib/system/channels.nim9
-rw-r--r--lib/system/chcks.nim4
-rw-r--r--lib/system/deepcopy.nim6
-rw-r--r--lib/system/dyncalls.nim17
-rw-r--r--lib/system/embedded.nim6
-rw-r--r--lib/system/excpt.nim108
-rw-r--r--lib/system/gc.nim166
-rw-r--r--lib/system/gc2.nim168
-rw-r--r--lib/system/gc_ms.nim56
-rw-r--r--lib/system/hti.nim8
-rw-r--r--lib/system/inclrtl.nim2
-rw-r--r--lib/system/jssys.nim20
-rw-r--r--lib/system/mmdisp.nim90
-rw-r--r--lib/system/platforms.nim2
-rw-r--r--lib/system/profiler.nim2
-rw-r--r--lib/system/repr.nim12
-rw-r--r--lib/system/sysio.nim129
-rw-r--r--lib/system/sysspawn.nim2
-rw-r--r--lib/system/sysstr.nim72
-rw-r--r--lib/system/threads.nim20
-rw-r--r--lib/system/timers.nim4
-rw-r--r--lib/windows/windows.nim12
-rw-r--r--lib/windows/winlean.nim52
-rw-r--r--lib/wrappers/claro.nim16
-rw-r--r--lib/wrappers/iup.nim228
-rw-r--r--lib/wrappers/libffi/msvc/win32.c2
-rw-r--r--lib/wrappers/libuv.nim58
-rw-r--r--lib/wrappers/mysql.nim24
-rw-r--r--lib/wrappers/openssl.nim46
-rw-r--r--lib/wrappers/pcre.nim762
-rw-r--r--lib/wrappers/readline/history.nim2
-rw-r--r--lib/wrappers/readline/tweaked/history.h2
-rw-r--r--lib/wrappers/sdl/sdl.nim10
-rw-r--r--lib/wrappers/sdl/sdl_mixer.nim2
-rw-r--r--lib/wrappers/zip/zlib.nim2
153 files changed, 9055 insertions, 8412 deletions
diff --git a/lib/core/locks.nim b/lib/core/locks.nim
index 766b7b536..8a809fc84 100644
--- a/lib/core/locks.nim
+++ b/lib/core/locks.nim
@@ -21,7 +21,7 @@ type
     ## is performed. Deprecated, do not use anymore!
   AquireEffect* {.deprecated.} = object of LockEffect  ## \
     ## effect that denotes that some lock is
-    ## aquired. Deprecated, do not use anymore!
+    ## acquired. Deprecated, do not use anymore!
   ReleaseEffect* {.deprecated.} = object of LockEffect ## \
     ## effect that denotes that some lock is
     ## released. Deprecated, do not use anymore!
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 353254d49..35f0f61c1 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -15,7 +15,7 @@ include "system/inclrtl"
 ## .. include:: ../doc/astspec.txt
 
 type
-  TNimrodNodeKind* = enum
+  NimNodeKind* = enum
     nnkNone, nnkEmpty, nnkIdent, nnkSym,
     nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit,
     nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkUIntLit, nnkUInt8Lit,
@@ -23,9 +23,9 @@ type
     nnkFloat32Lit, nnkFloat64Lit, nnkFloat128Lit, nnkStrLit, nnkRStrLit,
     nnkTripleStrLit, nnkNilLit, nnkMetaNode, nnkDotCall,
     nnkCommand, nnkCall, nnkCallStrLit, nnkInfix,
-    nnkPrefix, nnkPostfix, nnkHiddenCallConv, 
+    nnkPrefix, nnkPostfix, nnkHiddenCallConv,
     nnkExprEqExpr,
-    nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, 
+    nnkExprColonExpr, nnkIdentDefs, nnkVarTuple,
     nnkPar, nnkObjConstr, nnkCurly, nnkCurlyExpr,
     nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
     nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
@@ -48,7 +48,7 @@ type
     nnkConstDef, nnkTypeDef,
     nnkYieldStmt, nnkDefer, nnkTryStmt, nnkFinally, nnkRaiseStmt,
     nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt,
-    nnkDiscardStmt, nnkStmtList, 
+    nnkDiscardStmt, nnkStmtList,
     nnkImportStmt,
     nnkImportExceptStmt,
     nnkExportStmt,
@@ -60,159 +60,184 @@ type
     nnkStmtListType, nnkBlockType,
     nnkWith, nnkWithout,
     nnkTypeOfExpr, nnkObjectTy,
-    nnkTupleTy, nnkTypeClassTy, nnkStaticTy,
+    nnkTupleTy, nnkTupleClassTy, nnkTypeClassTy, nnkStaticTy,
     nnkRecList, nnkRecCase, nnkRecWhen,
     nnkRefTy, nnkPtrTy, nnkVarTy,
     nnkConstTy, nnkMutableTy,
     nnkDistinctTy,
-    nnkProcTy, 
+    nnkProcTy,
     nnkIteratorTy,         # iterator type
     nnkSharedTy,           # 'shared T'
     nnkEnumTy,
     nnkEnumFieldDef,
     nnkArglist, nnkPattern
     nnkReturnToken
-  TNimNodeKinds* = set[TNimrodNodeKind]
-  TNimrodTypeKind* = enum
+  NimNodeKinds* = set[NimNodeKind]
+  NimTypeKind* = enum
     ntyNone, ntyBool, ntyChar, ntyEmpty,
     ntyArrayConstr, ntyNil, ntyExpr, ntyStmt,
-    ntyTypeDesc, ntyGenericInvokation, ntyGenericBody, ntyGenericInst,
+    ntyTypeDesc, ntyGenericInvocation, ntyGenericBody, ntyGenericInst,
     ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal,
     ntyArray, ntyObject, ntyTuple, ntySet,
     ntyRange, ntyPtr, ntyRef, ntyVar,
     ntySequence, ntyProc, ntyPointer, ntyOpenArray,
     ntyString, ntyCString, ntyForward, ntyInt,
     ntyInt8, ntyInt16, ntyInt32, ntyInt64,
-    ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128
-  TNimTypeKinds* = set[TNimrodTypeKind]
-  TNimrodSymKind* = enum
+    ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128,
+    ntyUInt, ntyUInt8, ntyUInt16, ntyUInt32, ntyUInt64,
+    ntyBigNum,
+    ntyConst, ntyMutable, ntyVarargs,
+    ntyIter,
+    ntyError,
+    ntyBuiltinTypeClass, ntyConcept, ntyConceptInst, ntyComposite,
+    ntyAnd, ntyOr, ntyNot
+
+  TNimTypeKinds* {.deprecated.} = set[NimTypeKind]
+  NimSymKind* = enum
     nskUnknown, nskConditional, nskDynLib, nskParam,
-    nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet, 
+    nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet,
     nskConst, nskResult,
     nskProc, nskMethod, nskIterator, nskClosureIterator,
     nskConverter, nskMacro, nskTemplate, nskField,
     nskEnumField, nskForVar, nskLabel,
     nskStub
-    
-  TNimSymKinds* = set[TNimrodSymKind]
+
+  TNimSymKinds* {.deprecated.} = set[NimSymKind]
 
 type
-  TNimrodIdent* = object of RootObj
-    ## represents a Nimrod identifier in the AST
+  NimIdent* = object of RootObj
+    ## represents a Nim identifier in the AST
 
-  TNimrodSymbol {.final.} = object # hidden
-  PNimrodSymbol* {.compilerproc.} = ref TNimrodSymbol
-    ## represents a Nimrod *symbol* in the compiler; a *symbol* is a looked-up
+  NimSymObj = object # hidden
+  NimSym* = ref NimSymObj
+    ## represents a Nim *symbol* in the compiler; a *symbol* is a looked-up
     ## *ident*.
 
+{.deprecated: [TNimrodNodeKind: NimNodeKind, TNimNodeKinds: NimNodeKinds,
+    TNimrodTypeKind: NimTypeKind, TNimrodSymKind: NimSymKind,
+    TNimrodIdent: NimIdent, PNimrodSymbol: NimSym].}
+
 const
   nnkLiterals* = {nnkCharLit..nnkNilLit}
   nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
                    nnkCallStrLit}
 
-proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild", noSideEffect.}
+proc `[]`*(n: NimNode, i: int): NimNode {.magic: "NChild", noSideEffect.}
   ## get `n`'s `i`'th child.
 
-proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild",
+proc `[]=`*(n: NimNode, i: int, child: NimNode) {.magic: "NSetChild",
   noSideEffect.}
   ## set `n`'s `i`'th child to `child`.
 
-proc `!`*(s: string): TNimrodIdent {.magic: "StrToIdent", noSideEffect.}
+proc `!`*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect.}
   ## constructs an identifier from the string `s`
 
-proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr", noSideEffect.}
-  ## converts a Nimrod identifier to a string
+proc `$`*(i: NimIdent): string {.magic: "IdentToStr", noSideEffect.}
+  ## converts a Nim identifier to a string
 
-proc `$`*(s: PNimrodSymbol): string {.magic: "IdentToStr", noSideEffect.}
-  ## converts a Nimrod symbol to a string
+proc `$`*(s: NimSym): string {.magic: "IdentToStr", noSideEffect.}
+  ## converts a Nim symbol to a string
 
-proc `==`*(a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
-  ## compares two Nimrod identifiers
+proc `==`*(a, b: NimIdent): bool {.magic: "EqIdent", noSideEffect.}
+  ## compares two Nim identifiers
 
-proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
-  ## compares two Nimrod nodes
+proc `==`*(a, b: NimNode): bool {.magic: "EqNimrodNode", noSideEffect.}
+  ## compares two Nim nodes
 
-proc len*(n: PNimrodNode): int {.magic: "NLen", noSideEffect.}
+proc len*(n: NimNode): int {.magic: "NLen", noSideEffect.}
   ## returns the number of children of `n`.
 
-proc add*(father, child: PNimrodNode): PNimrodNode {.magic: "NAdd", discardable,
-  noSideEffect.}
+proc add*(father, child: NimNode): NimNode {.magic: "NAdd", discardable,
+  noSideEffect, locks: 0.}
   ## Adds the `child` to the `father` node. Returns the
   ## father node so that calls can be nested.
 
-proc add*(father: PNimrodNode, children: varargs[PNimrodNode]): PNimrodNode {.
-  magic: "NAddMultiple", discardable, noSideEffect.}
+proc add*(father: NimNode, children: varargs[NimNode]): NimNode {.
+  magic: "NAddMultiple", discardable, noSideEffect, locks: 0.}
   ## Adds each child of `children` to the `father` node.
   ## Returns the `father` node so that calls can be nested.
 
-proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel", noSideEffect.}
+proc del*(father: NimNode, idx = 0, n = 1) {.magic: "NDel", noSideEffect.}
   ## deletes `n` children of `father` starting at index `idx`.
 
-proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind", noSideEffect.}
+proc kind*(n: NimNode): NimNodeKind {.magic: "NKind", noSideEffect.}
   ## returns the `kind` of the node `n`.
 
-proc intVal*(n: PNimrodNode): BiggestInt {.magic: "NIntVal", noSideEffect.}
-proc floatVal*(n: PNimrodNode): BiggestFloat {.magic: "NFloatVal", noSideEffect.}
-proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol", noSideEffect.}
-proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent", noSideEffect.}
-proc typ*(n: PNimrodNode): typedesc {.magic: "NGetType", noSideEffect.}
-proc strVal*(n: PNimrodNode): string  {.magic: "NStrVal", noSideEffect.}
-
-proc `intVal=`*(n: PNimrodNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.}
-proc `floatVal=`*(n: PNimrodNode, val: BiggestFloat) {.magic: "NSetFloatVal", noSideEffect.}
-proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol", noSideEffect.}
-proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent", noSideEffect.}
-#proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
+proc intVal*(n: NimNode): BiggestInt {.magic: "NIntVal", noSideEffect.}
+proc boolVal*(n: NimNode): bool {.compileTime, noSideEffect.} = n.intVal != 0
+proc floatVal*(n: NimNode): BiggestFloat {.magic: "NFloatVal", noSideEffect.}
+proc symbol*(n: NimNode): NimSym {.magic: "NSymbol", noSideEffect.}
+proc ident*(n: NimNode): NimIdent {.magic: "NIdent", noSideEffect.}
+
+proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
+  ## with 'getType' you can access the node's `type`:idx:. A Nim type is
+  ## mapped to a Nim AST too, so it's slightly confusing but it means the same
+  ## API can be used to traverse types. Recursive types are flattened for you
+  ## so there is no danger of infinite recursions during traversal. To
+  ## resolve recursive types, you have to call 'getType' again. To see what
+  ## kind of type it is, call `typeKind` on getType's result.
+
+proc typeKind*(n: NimNode): NimTypeKind {.magic: "NGetType", noSideEffect.}
+  ## Returns the type kind of the node 'n' that should represent a type, that
+  ## means the node should have been obtained via `getType`.
+
+proc strVal*(n: NimNode): string  {.magic: "NStrVal", noSideEffect.}
+
+proc `intVal=`*(n: NimNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.}
+proc `floatVal=`*(n: NimNode, val: BiggestFloat) {.magic: "NSetFloatVal", noSideEffect.}
+proc `symbol=`*(n: NimNode, val: NimSym) {.magic: "NSetSymbol", noSideEffect.}
+proc `ident=`*(n: NimNode, val: NimIdent) {.magic: "NSetIdent", noSideEffect.}
+#proc `typ=`*(n: NimNode, typ: typedesc) {.magic: "NSetType".}
 # this is not sound! Unfortunately forbidding 'typ=' is not enough, as you
 # can easily do:
 #   let bracket = semCheck([1, 2])
 #   let fake = semCheck(2.0)
 #   bracket[0] = fake  # constructs a mixed array with ints and floats!
 
-proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
+proc `strVal=`*(n: NimNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
 
-proc newNimNode*(kind: TNimrodNodeKind,
-                 n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode", noSideEffect.}
+proc newNimNode*(kind: NimNodeKind,
+                 n: NimNode=nil): NimNode {.magic: "NNewNimNode", noSideEffect.}
 
-proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode", noSideEffect.}
-proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree", noSideEffect.}
+proc copyNimNode*(n: NimNode): NimNode {.magic: "NCopyNimNode", noSideEffect.}
+proc copyNimTree*(n: NimNode): NimNode {.magic: "NCopyNimTree", noSideEffect.}
 
-proc error*(msg: string) {.magic: "NError", gcsafe.}
+proc error*(msg: string) {.magic: "NError", benign.}
   ## writes an error message at compile time
 
-proc warning*(msg: string) {.magic: "NWarning", gcsafe.}
+proc warning*(msg: string) {.magic: "NWarning", benign.}
   ## writes a warning message at compile time
 
-proc hint*(msg: string) {.magic: "NHint", gcsafe.}
+proc hint*(msg: string) {.magic: "NHint", benign.}
   ## writes a hint message at compile time
 
-proc newStrLitNode*(s: string): PNimrodNode {.compileTime, noSideEffect.} =
+proc newStrLitNode*(s: string): NimNode {.compileTime, noSideEffect.} =
   ## creates a string literal node from `s`
   result = newNimNode(nnkStrLit)
   result.strVal = s
 
-proc newIntLitNode*(i: BiggestInt): PNimrodNode {.compileTime.} =
+proc newIntLitNode*(i: BiggestInt): NimNode {.compileTime.} =
   ## creates a int literal node from `i`
   result = newNimNode(nnkIntLit)
   result.intVal = i
 
-proc newFloatLitNode*(f: BiggestFloat): PNimrodNode {.compileTime.} =
+proc newFloatLitNode*(f: BiggestFloat): NimNode {.compileTime.} =
   ## creates a float literal node from `f`
   result = newNimNode(nnkFloatLit)
   result.floatVal = f
 
-proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.compileTime.} =
+proc newIdentNode*(i: NimIdent): NimNode {.compileTime.} =
   ## creates an identifier node from `i`
   result = newNimNode(nnkIdent)
   result.ident = i
 
-proc newIdentNode*(i: string): PNimrodNode {.compileTime.} =
+proc newIdentNode*(i: string): NimNode {.compileTime.} =
   ## creates an identifier node from `i`
   result = newNimNode(nnkIdent)
   result.ident = !i
 
 type
-  TBindSymRule* = enum   ## specifies how ``bindSym`` behaves
+  BindSymRule* = enum    ## specifies how ``bindSym`` behaves
     brClosed,            ## only the symbols in current scope are bound
     brOpen,              ## open wrt overloaded symbols, but may be a single
                          ## symbol if not ambiguous (the rules match that of
@@ -221,7 +246,9 @@ type
                          ## if not ambiguous (this cannot be achieved with
                          ## any other means in the language currently)
 
-proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
+{.deprecated: [TBindSymRule: BindSymRule].}
+
+proc bindSym*(ident: string, rule: BindSymRule = brClosed): NimNode {.
               magic: "NBindSym", noSideEffect.}
   ## creates a node that binds `ident` to a symbol node. The bound symbol
   ## may be an overloaded symbol.
@@ -232,48 +259,48 @@ proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
   ## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is
   ## returned even if the symbol is not ambiguous.
 
-proc genSym*(kind: TNimrodSymKind = nskLet; ident = ""): PNimrodNode {.
+proc genSym*(kind: NimSymKind = nskLet; ident = ""): NimNode {.
   magic: "NGenSym", noSideEffect.}
   ## generates a fresh symbol that is guaranteed to be unique. The symbol
   ## needs to occur in a declaration context.
 
-proc callsite*(): PNimrodNode {.magic: "NCallSite", gcsafe.}
-  ## returns the AST if the invokation expression that invoked this macro.
+proc callsite*(): NimNode {.magic: "NCallSite", benign.}
+  ## returns the AST of the invocation expression that invoked this macro.
 
-proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
-  ## converts the AST `n` to the concrete Nimrod code and wraps that
+proc toStrLit*(n: NimNode): NimNode {.compileTime.} =
+  ## converts the AST `n` to the concrete Nim code and wraps that
   ## in a string literal node
   return newStrLitNode(repr(n))
 
-proc lineinfo*(n: PNimrodNode): string {.magic: "NLineInfo", noSideEffect.}
+proc lineinfo*(n: NimNode): string {.magic: "NLineInfo", noSideEffect.}
   ## returns the position the node appears in the original source file
   ## in the form filename(line, col)
 
-proc internalParseExpr(s: string): PNimrodNode {.
+proc internalParseExpr(s: string): NimNode {.
   magic: "ParseExprToAst", noSideEffect.}
 
-proc internalParseStmt(s: string): PNimrodNode {.
+proc internalParseStmt(s: string): NimNode {.
   magic: "ParseStmtToAst", noSideEffect.}
 
 proc internalErrorFlag*(): string {.magic: "NError", noSideEffect.}
   ## Some builtins set an error flag. This is then turned into a proper
   ## exception. **Note**: Ordinary application code should not call this.
 
-proc parseExpr*(s: string): PNimrodNode {.noSideEffect, compileTime.} =
+proc parseExpr*(s: string): NimNode {.noSideEffect, compileTime.} =
   ## Compiles the passed string to its AST representation.
   ## Expects a single expression. Raises ``ValueError`` for parsing errors.
   result = internalParseExpr(s)
   let x = internalErrorFlag()
   if x.len > 0: raise newException(ValueError, x)
 
-proc parseStmt*(s: string): PNimrodNode {.noSideEffect, compileTime.} =
+proc parseStmt*(s: string): NimNode {.noSideEffect, compileTime.} =
   ## Compiles the passed string to its AST representation.
   ## Expects one or more statements. Raises ``ValueError`` for parsing errors.
   result = internalParseStmt(s)
   let x = internalErrorFlag()
   if x.len > 0: raise newException(ValueError, x)
 
-proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst", noSideEffect.}
+proc getAst*(macroOrTemplate: expr): NimNode {.magic: "ExpandToAst", noSideEffect.}
   ## Obtains the AST nodes returned from a macro or template invocation.
   ## Example:
   ##
@@ -282,10 +309,10 @@ proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst", noSideE
   ##   macro FooMacro() =
   ##     var ast = getAst(BarTemplate())
 
-proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst", noSideEffect.}
+proc quote*(bl: stmt, op = "``"): NimNode {.magic: "QuoteAst", noSideEffect.}
   ## Quasi-quoting operator.
   ## Accepts an expression or a block and returns the AST that represents it.
-  ## Within the quoted AST, you are able to interpolate PNimrodNode expressions
+  ## Within the quoted AST, you are able to interpolate NimNode expressions
   ## from the surrounding scope. If no operator is given, quoting is done using
   ## backticks. Otherwise, the given operator must be used as a prefix operator
   ## for any interpolated expression. The original meaning of the interpolation
@@ -293,7 +320,7 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst", noSideEffect.
   ## e.g. `@` is escaped as `@@`, `@@` is escaped as `@@@` and so on.
   ##
   ## Example:
-  ##   
+  ##
   ## .. code-block:: nim
   ##
   ##   macro check(ex: expr): stmt =
@@ -312,35 +339,41 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst", noSideEffect.
   ##     result = quote do:
   ##       if not `ex`:
   ##         echo `info` & ": Check failed: " & `expString`
-  
-proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
+
+proc expectKind*(n: NimNode, k: NimNodeKind) {.compileTime.} =
   ## checks that `n` is of kind `k`. If this is not the case,
   ## compilation aborts with an error message. This is useful for writing
   ## macros that check the AST that is passed to them.
-  if n.kind != k: error("macro expects a node of kind: " & $k)
+  if n.kind != k: error("Expected a node of kind " & $k & ", got " & $n.kind)
 
-proc expectMinLen*(n: PNimrodNode, min: int) {.compileTime.} =
+proc expectMinLen*(n: NimNode, min: int) {.compileTime.} =
   ## checks that `n` has at least `min` children. If this is not the case,
   ## compilation aborts with an error message. This is useful for writing
   ## macros that check its number of arguments.
   if n.len < min: error("macro expects a node with " & $min & " children")
 
-proc expectLen*(n: PNimrodNode, len: int) {.compileTime.} =
+proc expectLen*(n: NimNode, len: int) {.compileTime.} =
   ## checks that `n` has exactly `len` children. If this is not the case,
   ## compilation aborts with an error message. This is useful for writing
   ## macros that check its number of arguments.
   if n.len != len: error("macro expects a node with " & $len & " children")
 
-proc newCall*(theProc: PNimrodNode,
-              args: varargs[PNimrodNode]): PNimrodNode {.compileTime.} =
+proc newTree*(kind: NimNodeKind,
+              children: varargs[NimNode]): NimNode {.compileTime.} =
+  ## produces a new node with children.
+  result = newNimNode(kind)
+  result.add(children)
+
+proc newCall*(theProc: NimNode,
+              args: varargs[NimNode]): NimNode {.compileTime.} =
   ## produces a new call node. `theProc` is the proc that is called with
   ## the arguments ``args[0..]``.
   result = newNimNode(nnkCall)
   result.add(theProc)
   result.add(args)
 
-proc newCall*(theProc: TNimrodIdent,
-              args: varargs[PNimrodNode]): PNimrodNode {.compileTime.} =
+proc newCall*(theProc: NimIdent,
+              args: varargs[NimNode]): NimNode {.compileTime.} =
   ## produces a new call node. `theProc` is the proc that is called with
   ## the arguments ``args[0..]``.
   result = newNimNode(nnkCall)
@@ -348,35 +381,40 @@ proc newCall*(theProc: TNimrodIdent,
   result.add(args)
 
 proc newCall*(theProc: string,
-              args: varargs[PNimrodNode]): PNimrodNode {.compileTime.} =
+              args: varargs[NimNode]): NimNode {.compileTime.} =
   ## produces a new call node. `theProc` is the proc that is called with
   ## the arguments ``args[0..]``.
   result = newNimNode(nnkCall)
   result.add(newIdentNode(theProc))
   result.add(args)
 
-proc newLit*(c: char): PNimrodNode {.compileTime.} =
+proc newLit*(c: char): NimNode {.compileTime.} =
   ## produces a new character literal node.
   result = newNimNode(nnkCharLit)
   result.intVal = ord(c)
 
-proc newLit*(i: BiggestInt): PNimrodNode {.compileTime.} =
+proc newLit*(i: BiggestInt): NimNode {.compileTime.} =
   ## produces a new integer literal node.
   result = newNimNode(nnkIntLit)
   result.intVal = i
 
-proc newLit*(f: BiggestFloat): PNimrodNode {.compileTime.} =
+proc newLit*(b: bool): NimNode {.compileTime.} =
+  ## produces a new boolean literal node.
+  result = newNimNode(nnkIntLit)
+  result.intVal = ord(b)
+
+proc newLit*(f: BiggestFloat): NimNode {.compileTime.} =
   ## produces a new float literal node.
   result = newNimNode(nnkFloatLit)
   result.floatVal = f
 
-proc newLit*(s: string): PNimrodNode {.compileTime.} =
+proc newLit*(s: string): NimNode {.compileTime.} =
   ## produces a new string literal node.
   result = newNimNode(nnkStrLit)
   result.strVal = s
 
-proc nestList*(theProc: TNimrodIdent,
-               x: PNimrodNode): PNimrodNode {.compileTime.} =
+proc nestList*(theProc: NimIdent,
+               x: NimNode): NimNode {.compileTime.} =
   ## nests the list `x` into a tree of call expressions:
   ## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``.
   var L = x.len
@@ -387,11 +425,11 @@ proc nestList*(theProc: TNimrodIdent,
     # This could easily user code and so should be fixed in evals.nim somehow.
     result = newCall(theProc, x[i], copyNimTree(result))
 
-proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
+proc treeRepr*(n: NimNode): string {.compileTime, benign.} =
   ## Convert the AST `n` to a human-readable tree-like string.
   ##
   ## See also `repr` and `lispRepr`.
-  proc traverse(res: var string, level: int, n: PNimrodNode) =
+  proc traverse(res: var string, level: int, n: NimNode) {.benign.} =
     for i in 0..level-1: res.add "  "
     res.add(($n.kind).substr(3))
 
@@ -412,7 +450,7 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
   result = ""
   traverse(result, 0, n)
 
-proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
+proc lispRepr*(n: NimNode): string {.compileTime, benign.} =
   ## Convert the AST `n` to a human-readable lisp-like string,
   ##
   ## See also `repr` and `treeRepr`.
@@ -430,10 +468,11 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
   of nnkSym: add(result, $n.symbol)
   of nnkNone: assert false
   else:
-    add(result, lispRepr(n[0]))
-    for j in 1..n.len-1:
-      add(result, ", ")
-      add(result, lispRepr(n[j]))
+    if n.len > 0:
+      add(result, lispRepr(n[0]))
+      for j in 1..n.len-1:
+        add(result, ", ")
+        add(result, lispRepr(n[j]))
 
   add(result, ")")
 
@@ -458,42 +497,56 @@ macro dumpLispImm*(s: stmt): stmt {.immediate, deprecated.} = echo s.lispRepr
   ## The ``immediate`` version of `dumpLisp`.
 
 
-proc newEmptyNode*(): PNimrodNode {.compileTime, noSideEffect.} =
-  ## Create a new empty node 
+proc newEmptyNode*(): NimNode {.compileTime, noSideEffect.} =
+  ## Create a new empty node
   result = newNimNode(nnkEmpty)
 
-proc newStmtList*(stmts: varargs[PNimrodNode]): PNimrodNode {.compileTime.}=
+proc newStmtList*(stmts: varargs[NimNode]): NimNode {.compileTime.}=
   ## Create a new statement list
   result = newNimNode(nnkStmtList).add(stmts)
 
-proc newBlockStmt*(label, body: PNimrodNode): PNimrodNode {.compileTime.} =
+proc newPar*(exprs: varargs[NimNode]): NimNode {.compileTime.}=
+  ## Create a new parentheses-enclosed expression
+  newNimNode(nnkPar).add(exprs)
+
+proc newBlockStmt*(label, body: NimNode): NimNode {.compileTime.} =
   ## Create a new block statement with label
   return newNimNode(nnkBlockStmt).add(label, body)
 
-proc newBlockStmt*(body: PNimrodNode): PNimrodNode {.compiletime.} =
+proc newBlockStmt*(body: NimNode): NimNode {.compiletime.} =
   ## Create a new block: stmt
   return newNimNode(nnkBlockStmt).add(newEmptyNode(), body)
 
-proc newVarStmt*(name, value: PNimrodNode): PNimrodNode {.compiletime.} =
-  ## Create a new var stmt 
+proc newVarStmt*(name, value: NimNode): NimNode {.compiletime.} =
+  ## Create a new var stmt
   return newNimNode(nnkVarSection).add(
     newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value))
 
-proc newLetStmt*(name, value: PNimrodNode): PNimrodNode {.compiletime.} =
-  ## Create a new let stmt 
+proc newLetStmt*(name, value: NimNode): NimNode {.compiletime.} =
+  ## Create a new let stmt
   return newNimNode(nnkLetSection).add(
     newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value))
 
-proc newAssignment*(lhs, rhs: PNimrodNode): PNimrodNode {.compileTime.} =
+proc newConstStmt*(name, value: NimNode): NimNode {.compileTime.} =
+  ## Create a new const stmt
+  newNimNode(nnkConstSection).add(
+    newNimNode(nnkConstDef).add(name, newNimNode(nnkEmpty), value))
+
+proc newAssignment*(lhs, rhs: NimNode): NimNode {.compileTime.} =
   return newNimNode(nnkAsgn).add(lhs, rhs)
 
-proc newDotExpr*(a, b: PNimrodNode): PNimrodNode {.compileTime.} = 
+proc newDotExpr*(a, b: NimNode): NimNode {.compileTime.} =
   ## Create new dot expression
   ## a.dot(b) ->  `a.b`
   return newNimNode(nnkDotExpr).add(a, b)
 
-proc newIdentDefs*(name, kind: PNimrodNode; 
-                   default = newEmptyNode()): PNimrodNode {.compileTime.} = 
+proc newColonExpr*(a, b: NimNode): NimNode {.compileTime.} =
+  ## Create new colon expression
+  ## newColonExpr(a, b) ->  `a: b`
+  newNimNode(nnkExprColonExpr).add(a, b)
+
+proc newIdentDefs*(name, kind: NimNode;
+                   default = newEmptyNode()): NimNode {.compileTime.} =
   ## Creates a new ``nnkIdentDefs`` node of a specific kind and value.
   ##
   ## ``nnkIdentDefs`` need to have at least three children, but they can have
@@ -524,32 +577,30 @@ proc newIdentDefs*(name, kind: PNimrodNode;
   ##       newStrLitNode("Hello"))
   newNimNode(nnkIdentDefs).add(name, kind, default)
 
-proc newNilLit*(): PNimrodNode {.compileTime.} =
+proc newNilLit*(): NimNode {.compileTime.} =
   ## New nil literal shortcut
   result = newNimNode(nnkNilLit)
 
-proc high*(node: PNimrodNode): int {.compileTime.} = len(node) - 1
+proc high*(node: NimNode): int {.compileTime.} = len(node) - 1
   ## Return the highest index available for a node
-proc last*(node: PNimrodNode): PNimrodNode {.compileTime.} = node[node.high]
-  ## Return the last item in nodes children. Same as `node[node.high()]` 
+proc last*(node: NimNode): NimNode {.compileTime.} = node[node.high]
+  ## Return the last item in nodes children. Same as `node[node.high()]`
 
 
 const
   RoutineNodes* = {nnkProcDef, nnkMethodDef, nnkDo, nnkLambda, nnkIteratorDef}
   AtomicNodes* = {nnkNone..nnkNilLit}
-  CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, 
+  CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
     nnkCallStrLit, nnkHiddenCallConv}
 
-from strutils import cmpIgnoreStyle, format
+proc expectKind*(n: NimNode; k: set[NimNodeKind]) {.compileTime.} =
+  assert n.kind in k, "Expected one of " & $k & ", got " & $n.kind
 
-proc expectKind*(n: PNimrodNode; k: set[TNimrodNodeKind]) {.compileTime.} =
-  assert n.kind in k, "Expected one of $1, got $2".format(k, n.kind)
-
-proc newProc*(name = newEmptyNode(); params: openArray[PNimrodNode] = [newEmptyNode()];  
-    body: PNimrodNode = newStmtList(), procType = nnkProcDef): PNimrodNode {.compileTime.} =
+proc newProc*(name = newEmptyNode(); params: openArray[NimNode] = [newEmptyNode()];
+    body: NimNode = newStmtList(), procType = nnkProcDef): NimNode {.compileTime.} =
   ## shortcut for creating a new proc
   ##
-  ## The ``params`` array must start with the return type of the proc, 
+  ## The ``params`` array must start with the return type of the proc,
   ## followed by a list of IdentDefs which specify the params.
   assert procType in RoutineNodes
   result = newNimNode(procType).add(
@@ -561,12 +612,12 @@ proc newProc*(name = newEmptyNode(); params: openArray[PNimrodNode] = [newEmptyN
     newEmptyNode(),
     body)
 
-proc newIfStmt*(branches: varargs[tuple[cond, body: PNimrodNode]]): 
-                PNimrodNode {.compiletime.} =
+proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]):
+                NimNode {.compiletime.} =
   ## Constructor for ``if`` statements.
   ##
   ## .. code-block:: nim
-  ##    
+  ##
   ##    newIfStmt(
   ##      (Ident, StmtList),
   ##      ...
@@ -575,37 +626,37 @@ proc newIfStmt*(branches: varargs[tuple[cond, body: PNimrodNode]]):
   result = newNimNode(nnkIfStmt)
   for i in branches:
     result.add(newNimNode(nnkElifBranch).add(i.cond, i.body))
-    
 
-proc copyChildrenTo*(src, dest: PNimrodNode) {.compileTime.}=
+
+proc copyChildrenTo*(src, dest: NimNode) {.compileTime.}=
   ## Copy all children from `src` to `dest`
   for i in 0 .. < src.len:
     dest.add src[i].copyNimTree
 
-template expectRoutine(node: PNimrodNode): stmt =
+template expectRoutine(node: NimNode): stmt =
   expectKind(node, RoutineNodes)
-  
-proc name*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
+
+proc name*(someProc: NimNode): NimNode {.compileTime.} =
   someProc.expectRoutine
   result = someProc[0]
-proc `name=`*(someProc: PNimrodNode; val: PNimrodNode) {.compileTime.} =
+proc `name=`*(someProc: NimNode; val: NimNode) {.compileTime.} =
   someProc.expectRoutine
   someProc[0] = val
 
-proc params*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
+proc params*(someProc: NimNode): NimNode {.compileTime.} =
   someProc.expectRoutine
   result = someProc[3]
-proc `params=`* (someProc: PNimrodNode; params: PNimrodNode) {.compileTime.}=
+proc `params=`* (someProc: NimNode; params: NimNode) {.compileTime.}=
   someProc.expectRoutine
   assert params.kind == nnkFormalParams
   someProc[3] = params
 
-proc pragma*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
+proc pragma*(someProc: NimNode): NimNode {.compileTime.} =
   ## Get the pragma of a proc type
   ## These will be expanded
   someProc.expectRoutine
   result = someProc[4]
-proc `pragma=`*(someProc: PNimrodNode; val: PNimrodNode){.compileTime.}=
+proc `pragma=`*(someProc: NimNode; val: NimNode){.compileTime.}=
   ## Set the pragma of a proc type
   someProc.expectRoutine
   assert val.kind in {nnkEmpty, nnkPragma}
@@ -613,9 +664,9 @@ proc `pragma=`*(someProc: PNimrodNode; val: PNimrodNode){.compileTime.}=
 
 
 template badNodeKind(k; f): stmt{.immediate.} =
-  assert false, "Invalid node kind $# for macros.`$2`".format(k, f)
+  assert false, "Invalid node kind " & $k & " for macros.`" & $f & "`"
 
-proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
+proc body*(someProc: NimNode): NimNode {.compileTime.} =
   case someProc.kind:
   of RoutineNodes:
     return someProc[6]
@@ -623,11 +674,11 @@ proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
     return someProc[1]
   of nnkForStmt:
     return someProc.last
-  else: 
+  else:
     badNodeKind someProc.kind, "body"
 
-proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} =
-  case someProc.kind 
+proc `body=`*(someProc: NimNode, val: NimNode) {.compileTime.} =
+  case someProc.kind
   of RoutineNodes:
     someProc[6] = val
   of nnkBlockStmt, nnkWhileStmt:
@@ -635,12 +686,12 @@ proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} =
   of nnkForStmt:
     someProc[high(someProc)] = val
   else:
-    badNodeKind someProc.kind, "body=" 
+    badNodeKind someProc.kind, "body="
+
+proc basename*(a: NimNode): NimNode {.compiletime, benign.}
 
-proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.}
-  
 
-proc `$`*(node: PNimrodNode): string {.compileTime.} =
+proc `$`*(node: NimNode): string {.compileTime.} =
   ## Get the string of an identifier node
   case node.kind
   of nnkIdent:
@@ -651,32 +702,32 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
     result = node.strVal
   of nnkSym:
     result = $node.symbol
-  else: 
+  else:
     badNodeKind node.kind, "$"
 
-proc ident*(name: string): PNimrodNode {.compileTime,inline.} = newIdentNode(name)
+proc ident*(name: string): NimNode {.compileTime,inline.} = newIdentNode(name)
   ## Create a new ident node from a string
 
-iterator children*(n: PNimrodNode): PNimrodNode {.inline.}=
+iterator children*(n: NimNode): NimNode {.inline.}=
   for i in 0 .. high(n):
     yield n[i]
 
-template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.
+template findChild*(n: NimNode; cond: expr): NimNode {.
   immediate, dirty.} =
   ## Find the first child node matching condition (or nil).
-  ## 
+  ##
   ## .. code-block:: nim
   ##   var res = findChild(n, it.kind == nnkPostfix and
   ##                          it.basename.ident == !"foo")
   block:
-    var result: PNimrodNode
+    var result: NimNode
     for it in n.children:
-      if cond: 
+      if cond:
         result = it
         break
     result
 
-proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} =
+proc insert*(a: NimNode; pos: int; b: NimNode) {.compileTime.} =
   ## Insert node B into A at pos
   if high(a) < pos:
     ## add some empty nodes first
@@ -691,62 +742,78 @@ proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} =
       a[i + 1] = a[i]
     a[pos] = b
 
-proc basename*(a: PNimrodNode): PNimrodNode =
+proc basename*(a: NimNode): NimNode =
   ## Pull an identifier from prefix/postfix expressions
   case a.kind
   of nnkIdent: return a
   of nnkPostfix, nnkPrefix: return a[1]
-  else: 
-    quit "Do not know how to get basename of ("& treeRepr(a) &")\n"& repr(a)
-    
-proc `basename=`*(a: PNimrodNode; val: string) {.compileTime.}=
+  else:
+    quit "Do not know how to get basename of (" & treeRepr(a) & ")\n" & repr(a)
+
+proc `basename=`*(a: NimNode; val: string) {.compileTime.}=
   case a.kind
   of nnkIdent: macros.`ident=`(a,  !val)
   of nnkPostfix, nnkPrefix: a[1] = ident(val)
   else:
-    quit "Do not know how to get basename of ("& treeRepr(a)& ")\n"& repr(a)
+    quit "Do not know how to get basename of (" & treeRepr(a) & ")\n" & repr(a)
 
-proc postfix*(node: PNimrodNode; op: string): PNimrodNode {.compileTime.} = 
+proc postfix*(node: NimNode; op: string): NimNode {.compileTime.} =
   newNimNode(nnkPostfix).add(ident(op), node)
 
-proc prefix*(node: PNimrodNode; op: string): PNimrodNode {.compileTime.} = 
+proc prefix*(node: NimNode; op: string): NimNode {.compileTime.} =
   newNimNode(nnkPrefix).add(ident(op), node)
 
-proc infix*(a: PNimrodNode; op: string; 
-            b: PNimrodNode): PNimrodNode {.compileTime.} = 
+proc infix*(a: NimNode; op: string;
+            b: NimNode): NimNode {.compileTime.} =
   newNimNode(nnkInfix).add(ident(op), a, b)
 
-proc unpackPostfix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {.
+proc unpackPostfix*(node: NimNode): tuple[node: NimNode; op: string] {.
   compileTime.} =
   node.expectKind nnkPostfix
   result = (node[0], $node[1])
 
-proc unpackPrefix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {.
+proc unpackPrefix*(node: NimNode): tuple[node: NimNode; op: string] {.
   compileTime.} =
   node.expectKind nnkPrefix
   result = (node[0], $node[1])
 
-proc unpackInfix*(node: PNimrodNode): tuple[left: PNimrodNode; op: string; 
-                                        right: PNimrodNode] {.compileTime.} =
+proc unpackInfix*(node: NimNode): tuple[left: NimNode; op: string;
+                                        right: NimNode] {.compileTime.} =
   assert node.kind == nnkInfix
   result = (node[0], $node[1], node[2])
 
-proc copy*(node: PNimrodNode): PNimrodNode {.compileTime.} =
+proc copy*(node: NimNode): NimNode {.compileTime.} =
   ## An alias for copyNimTree().
   return node.copyNimTree()
 
+proc cmpIgnoreStyle(a, b: cstring): int {.noSideEffect.} =
+  proc toLower(c: char): char {.inline.} =
+    if c in {'A'..'Z'}: result = chr(ord(c) + (ord('a') - ord('A')))
+    else: result = c
+  var i = 0
+  var j = 0
+  while true:
+    while a[i] == '_': inc(i)
+    while b[j] == '_': inc(j) # BUGFIX: typo
+    var aa = toLower(a[i])
+    var bb = toLower(b[j])
+    result = ord(aa) - ord(bb)
+    if result != 0 or aa == '\0': break
+    inc(i)
+    inc(j)
+
 proc eqIdent* (a, b: string): bool = cmpIgnoreStyle(a, b) == 0
   ## Check if two idents are identical.
 
-proc hasArgOfName* (params: PNimrodNode; name: string): bool {.compiletime.}=
+proc hasArgOfName* (params: NimNode; name: string): bool {.compiletime.}=
   ## Search nnkFormalParams for an argument.
   assert params.kind == nnkFormalParams
-  for i in 1 .. <params.len: 
+  for i in 1 .. <params.len:
     template node: expr = params[i]
     if name.eqIdent( $ node[0]):
       return true
 
-proc addIdentIfAbsent*(dest: PNimrodNode, ident: string) {.compiletime.} =
+proc addIdentIfAbsent*(dest: NimNode, ident: string) {.compiletime.} =
   ## Add ident to dest if it is not present. This is intended for use
   ## with pragmas.
   for node in dest.children:
diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim
index 0046924a1..c3ff66591 100644
--- a/lib/core/typeinfo.nim
+++ b/lib/core/typeinfo.nim
@@ -66,9 +66,9 @@ type
   ppointer = ptr pointer
   pbyteArray = ptr array[0.. 0xffff, int8]
 
-  TGenSeq = object
+  TGenericSeq {.importc.} = object
     len, space: int
-  PGenSeq = ptr TGenSeq
+  PGenSeq = ptr TGenericSeq
 
 const
   GenericSeqSize = (2 * sizeof(int))
diff --git a/lib/core/unsigned.nim b/lib/core/unsigned.nim
index 7acdf1439..20fcd03aa 100644
--- a/lib/core/unsigned.nim
+++ b/lib/core/unsigned.nim
@@ -11,49 +11,47 @@
 ## To discourage users from using ``unsigned``, it's not part of ``system``,
 ## but an extra import.
 
-type
-  SomeUInt = uint|uint8|uint16|uint32|uint64
-
-proc `not`*[T: SomeUInt](x: T): T {.magic: "BitnotI", noSideEffect.}
+proc `not`*[T: SomeUnsignedInt](x: T): T {.magic: "BitnotI", noSideEffect.}
   ## computes the `bitwise complement` of the integer `x`.
 
-proc `shr`*[T: SomeUInt](x, y: T): T {.magic: "ShrI", noSideEffect.}
+proc `shr`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShrI", noSideEffect.}
   ## computes the `shift right` operation of `x` and `y`.
 
-proc `shl`*[T: SomeUInt](x, y: T): T {.magic: "ShlI", noSideEffect.}
+proc `shl`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShlI", noSideEffect.}
   ## computes the `shift left` operation of `x` and `y`.
 
-proc `and`*[T: SomeUInt](x, y: T): T {.magic: "BitandI", noSideEffect.}
+proc `and`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitandI", noSideEffect.}
   ## computes the `bitwise and` of numbers `x` and `y`.
 
-proc `or`*[T: SomeUInt](x, y: T): T {.magic: "BitorI", noSideEffect.}
+proc `or`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitorI", noSideEffect.}
   ## computes the `bitwise or` of numbers `x` and `y`.
 
-proc `xor`*[T: SomeUInt](x, y: T): T {.magic: "BitxorI", noSideEffect.}
+proc `xor`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitxorI", noSideEffect.}
   ## computes the `bitwise xor` of numbers `x` and `y`.
 
-proc `==`*[T: SomeUInt](x, y: T): bool {.magic: "EqI", noSideEffect.}
+proc `==`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "EqI", noSideEffect.}
   ## Compares two unsigned integers for equality.
 
-proc `+`*[T: SomeUInt](x, y: T): T {.magic: "AddU", noSideEffect.}
+proc `+`*[T: SomeUnsignedInt](x, y: T): T {.magic: "AddU", noSideEffect.}
   ## Binary `+` operator for unsigned integers.
 
-proc `-`*[T: SomeUInt](x, y: T): T {.magic: "SubU", noSideEffect.}
+proc `-`*[T: SomeUnsignedInt](x, y: T): T {.magic: "SubU", noSideEffect.}
   ## Binary `-` operator for unsigned integers.
 
-proc `*`*[T: SomeUInt](x, y: T): T {.magic: "MulU", noSideEffect.}
+proc `*`*[T: SomeUnsignedInt](x, y: T): T {.magic: "MulU", noSideEffect.}
   ## Binary `*` operator for unsigned integers.
 
-proc `div`*[T: SomeUInt](x, y: T): T {.magic: "DivU", noSideEffect.}
+proc `div`*[T: SomeUnsignedInt](x, y: T): T {.magic: "DivU", noSideEffect.}
   ## computes the integer division. This is roughly the same as
   ## ``floor(x/y)``.
 
-proc `mod`*[T: SomeUInt](x, y: T): T {.magic: "ModU", noSideEffect.}
+proc `mod`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ModU", noSideEffect.}
   ## computes the integer modulo operation. This is the same as
   ## ``x - (x div y) * y``.
 
-proc `<=`*[T: SomeUInt](x, y: T): bool {.magic: "LeU", noSideEffect.}
+proc `<=`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LeU", noSideEffect.}
   ## Returns true iff ``x <= y``.
 
-proc `<`*[T: SomeUInt](x, y: T): bool {.magic: "LtU", noSideEffect.}
+proc `<`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LtU", noSideEffect.}
   ## Returns true iff ``unsigned(x) < unsigned(y)``.
+
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim
index 968a2923a..b8180cd87 100644
--- a/lib/impure/db_mysql.nim
+++ b/lib/impure/db_mysql.nim
@@ -16,11 +16,11 @@ type
   TDbConn* = PMySQL    ## encapsulates a database connection
   TRow* = seq[string]  ## a row of a dataset. NULL database values will be
                        ## transformed always to the empty string.
-  EDb* = object of EIO ## exception that is raised if a database error occurs
+  EDb* = object of IOError ## exception that is raised if a database error occurs
 
   TSqlQuery* = distinct string ## an SQL query string
 
-  FDb* = object of FIO ## effect that denotes a database operation
+  FDb* = object of IOEffect ## 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
 
@@ -229,3 +229,9 @@ proc open*(connection, user, password, database: string): TDbConn {.
     var errmsg = $mysql.error(result)
     db_mysql.close(result)
     dbError(errmsg)
+
+proc setEncoding*(connection: TDbConn, encoding: string): bool {.
+  tags: [FDb].} =
+  ## sets the encoding of a database connection, returns true for 
+  ## success, false for failure.
+  result = mysql.set_character_set(connection, encoding) == 0
\ No newline at end of file
diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim
index 6691c5703..ffb8bbcda 100644
--- a/lib/impure/db_postgres.nim
+++ b/lib/impure/db_postgres.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -260,3 +260,9 @@ proc open*(connection, user, password, database: string): TDbConn {.
   ## the nim db api.
   result = pqsetdbLogin(nil, nil, nil, nil, database, user, password)
   if pqStatus(result) != CONNECTION_OK: dbError(result) # result = nil
+
+proc setEncoding*(connection: TDbConn, encoding: string): bool {.
+  tags: [FDb].} =
+  ## sets the encoding of a database connection, returns true for 
+  ## success, false for failure.
+  return pqsetClientEncoding(connection, encoding) == 0
\ No newline at end of file
diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim
index bc9e0b591..8536ab6f2 100644
--- a/lib/impure/db_sqlite.nim
+++ b/lib/impure/db_sqlite.nim
@@ -48,6 +48,7 @@ proc dbError*(msg: string) {.noreturn.} =
   raise e
 
 proc dbQuote(s: string): string =
+  if s.isNil: return "NULL"
   result = "'"
   for c in items(s):
     if c == '\'': add(result, "''")
@@ -61,7 +62,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
     if c == '?':
       add(result, dbQuote(args[a]))
       inc(a)
-    else: 
+    else:
       add(result, c)
   
 proc tryExec*(db: TDbConn, query: TSqlQuery, 
@@ -191,8 +192,20 @@ proc open*(connection, user, password, database: string): TDbConn {.
     result = db
   else:
     dbError(db)
-   
-when isMainModule:
+
+proc setEncoding*(connection: TDbConn, encoding: string): bool {.
+  tags: [FDb].} =
+  ## sets the encoding of a database connection, returns true for 
+  ## success, false for failure.
+  ##
+  ## Note that the encoding cannot be changed once it's been set.
+  ## According to SQLite3 documentation, any attempt to change 
+  ## the encoding after the database is created will be silently 
+  ## ignored.
+  exec(connection, sql"PRAGMA encoding = ?", [encoding])
+  result = connection.getValue(sql"PRAGMA encoding") == encoding
+
+when not defined(testing) and isMainModule:
   var db = open("db.sql", "", "", "")
   exec(db, sql"create table tbl1(one varchar(10), two smallint)", [])
   exec(db, sql"insert into tbl1 values('hello!',10)", [])
diff --git a/lib/impure/graphics.nim b/lib/impure/graphics.nim
index dfadb46ee..814c0ebe1 100644
--- a/lib/impure/graphics.nim
+++ b/lib/impure/graphics.nim
@@ -499,7 +499,7 @@ template withEvents*(surf: PSurface, event: expr, actions: stmt): stmt {.
 if sdl.init(sdl.INIT_VIDEO) < 0: raiseEGraphics()
 if sdl_ttf.init() < 0: raiseEGraphics()
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   var surf = newScreenSurface(800, 600)
 
   surf.fillSurface(colWhite)
diff --git a/lib/impure/osinfo_posix.nim b/lib/impure/osinfo_posix.nim
index 1baff8c55..0362fca12 100644
--- a/lib/impure/osinfo_posix.nim
+++ b/lib/impure/osinfo_posix.nim
@@ -1,69 +1,10 @@
-import posix, strutils, os
-
-when false:
-  type
-    Tstatfs {.importc: "struct statfs64", 
-              header: "<sys/statfs.h>", final, pure.} = object
-      f_type: int
-      f_bsize: int
-      f_blocks: int
-      f_bfree: int
-      f_bavail: int
-      f_files: int
-      f_ffree: int
-      f_fsid: int
-      f_namelen: int
-
-  proc statfs(path: string, buf: var Tstatfs): int {.
-    importc, header: "<sys/vfs.h>".}
-
-
-proc getSystemVersion*(): string =
-  result = ""
-  
-  var unix_info: TUtsname
-  
-  if uname(unix_info) != 0:
-    os.raiseOSError(osLastError())
-  
-  if $unix_info.sysname == "Linux":
-    # Linux
-    result.add("Linux ")
-
-    result.add($unix_info.release & " ")
-    result.add($unix_info.machine)
-  elif $unix_info.sysname == "Darwin":
-    # Darwin
-    result.add("Mac OS X ")
-    if "10" in $unix_info.release:
-      result.add("v10.6 Snow Leopard")
-    elif "9" in $unix_info.release:
-      result.add("v10.5 Leopard")
-    elif "8" in $unix_info.release:
-      result.add("v10.4 Tiger")
-    elif "7" in $unix_info.release:
-      result.add("v10.3 Panther")
-    elif "6" in $unix_info.release:
-      result.add("v10.2 Jaguar")
-    elif "1.4" in $unix_info.release:
-      result.add("v10.1 Puma")
-    elif "1.3" in $unix_info.release:
-      result.add("v10.0 Cheetah")
-    elif "0" in $unix_info.release:
-      result.add("Server 1.0 Hera")
-  else:
-    result.add($unix_info.sysname & " " & $unix_info.release)
-    
-    
-when false:
-  var unix_info: TUtsname
-  echo(uname(unix_info))
-  echo(unix_info.sysname)
-  echo("8" in $unix_info.release)
-
-  echo(getSystemVersion())
-
-  var stfs: TStatfs
-  echo(statfs("sysinfo_posix.nim", stfs))
-  echo(stfs.f_files)
-  
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+{.error: "This module has been moved to the 'osinfo' nimble package.".}
diff --git a/lib/impure/osinfo_win.nim b/lib/impure/osinfo_win.nim
index f423a34a3..0362fca12 100644
--- a/lib/impure/osinfo_win.nim
+++ b/lib/impure/osinfo_win.nim
@@ -1,404 +1,10 @@
-# XXX clean up this mess!
-
-import winlean
-
-const
-  INVALID_HANDLE_VALUE = int(- 1) # GetStockObject
-
-type
-  TMEMORYSTATUSEX {.final, pure.} = object
-    dwLength: int32
-    dwMemoryLoad: int32
-    ullTotalPhys: int64
-    ullAvailPhys: int64
-    ullTotalPageFile: int64
-    ullAvailPageFile: int64
-    ullTotalVirtual: int64
-    ullAvailVirtual: int64
-    ullAvailExtendedVirtual: int64
-    
-  SYSTEM_INFO* {.final, pure.} = object
-    wProcessorArchitecture*: int16
-    wReserved*: int16
-    dwPageSize*: int32
-    lpMinimumApplicationAddress*: pointer
-    lpMaximumApplicationAddress*: pointer
-    dwActiveProcessorMask*: int32
-    dwNumberOfProcessors*: int32
-    dwProcessorType*: int32
-    dwAllocationGranularity*: int32
-    wProcessorLevel*: int16
-    wProcessorRevision*: int16
-
-  LPSYSTEM_INFO* = ptr SYSTEM_INFO
-  TSYSTEMINFO* = SYSTEM_INFO
-
-  TMemoryInfo* = object
-    MemoryLoad*: int ## occupied memory, in percent
-    TotalPhysMem*: int64 ## Total Physical memory, in bytes
-    AvailablePhysMem*: int64 ## Available physical memory, in bytes
-    TotalPageFile*: int64 ## The current committed memory limit 
-                          ## for the system or the current process, whichever is smaller, in bytes.
-    AvailablePageFile*: int64 ## The maximum amount of memory the current process can commit, in bytes.
-    TotalVirtualMem*: int64 ## Total virtual memory, in bytes
-    AvailableVirtualMem*: int64 ## Available virtual memory, in bytes
-    
-  TOSVERSIONINFOEX {.final, pure.} = object
-    dwOSVersionInfoSize: int32
-    dwMajorVersion: int32
-    dwMinorVersion: int32
-    dwBuildNumber: int32
-    dwPlatformId: int32
-    szCSDVersion: array[0..127, char]
-    wServicePackMajor: int16
-    wServicePackMinor: int16
-    wSuiteMask: int16
-    wProductType: int8
-    wReserved: char
-    
-  TVersionInfo* = object
-    majorVersion*: int
-    minorVersion*: int
-    buildNumber*: int
-    platformID*: int
-    SPVersion*: string ## Full Service pack version string
-    SPMajor*: int ## Major service pack version
-    SPMinor*: int ## Minor service pack version
-    SuiteMask*: int
-    ProductType*: int
-    
-  TPartitionInfo* = tuple[FreeSpace, TotalSpace: Tfiletime]
-  
-const
-  # SuiteMask - VersionInfo.SuiteMask
-  VER_SUITE_BACKOFFICE* = 0x00000004
-  VER_SUITE_BLADE* = 0x00000400
-  VER_SUITE_COMPUTE_SERVER* = 0x00004000
-  VER_SUITE_DATACENTER* = 0x00000080
-  VER_SUITE_ENTERPRISE* = 0x00000002
-  VER_SUITE_EMBEDDEDNT* = 0x00000040
-  VER_SUITE_PERSONAL* = 0x00000200
-  VER_SUITE_SINGLEUSERTS* = 0x00000100
-  VER_SUITE_SMALLBUSINESS* = 0x00000001
-  VER_SUITE_SMALLBUSINESS_RESTRICTED* = 0x00000020
-  VER_SUITE_STORAGE_SERVER* = 0x00002000
-  VER_SUITE_TERMINAL* = 0x00000010
-  VER_SUITE_WH_SERVER* = 0x00008000
-
-  # ProductType - VersionInfo.ProductType
-  VER_NT_DOMAIN_CONTROLLER* = 0x0000002
-  VER_NT_SERVER* = 0x0000003
-  VER_NT_WORKSTATION* = 0x0000001
-  
-  VER_PLATFORM_WIN32_NT* = 2
-  
-  # Product Info - getProductInfo() - (Remove unused ones ?)
-  PRODUCT_BUSINESS* = 0x00000006
-  PRODUCT_BUSINESS_N* = 0x00000010
-  PRODUCT_CLUSTER_SERVER* = 0x00000012
-  PRODUCT_DATACENTER_SERVER* = 0x00000008
-  PRODUCT_DATACENTER_SERVER_CORE* = 0x0000000C
-  PRODUCT_DATACENTER_SERVER_CORE_V* = 0x00000027
-  PRODUCT_DATACENTER_SERVER_V* = 0x00000025
-  PRODUCT_ENTERPRISE* = 0x00000004
-  PRODUCT_ENTERPRISE_E* = 0x00000046
-  PRODUCT_ENTERPRISE_N* = 0x0000001B
-  PRODUCT_ENTERPRISE_SERVER* = 0x0000000A
-  PRODUCT_ENTERPRISE_SERVER_CORE* = 0x0000000E
-  PRODUCT_ENTERPRISE_SERVER_CORE_V* = 0x00000029
-  PRODUCT_ENTERPRISE_SERVER_IA64* = 0x0000000F
-  PRODUCT_ENTERPRISE_SERVER_V* = 0x00000026
-  PRODUCT_HOME_BASIC* = 0x00000002
-  PRODUCT_HOME_BASIC_E* = 0x00000043
-  PRODUCT_HOME_BASIC_N* = 0x00000005
-  PRODUCT_HOME_PREMIUM* = 0x00000003
-  PRODUCT_HOME_PREMIUM_E* = 0x00000044
-  PRODUCT_HOME_PREMIUM_N* = 0x0000001A
-  PRODUCT_HYPERV* = 0x0000002A
-  PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT* = 0x0000001E
-  PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING* = 0x00000020
-  PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY* = 0x0000001F
-  PRODUCT_PROFESSIONAL* = 0x00000030
-  PRODUCT_PROFESSIONAL_E* = 0x00000045
-  PRODUCT_PROFESSIONAL_N* = 0x00000031
-  PRODUCT_SERVER_FOR_SMALLBUSINESS* = 0x00000018
-  PRODUCT_SERVER_FOR_SMALLBUSINESS_V* = 0x00000023
-  PRODUCT_SERVER_FOUNDATION* = 0x00000021
-  PRODUCT_SMALLBUSINESS_SERVER* = 0x00000009
-  PRODUCT_STANDARD_SERVER* = 0x00000007
-  PRODUCT_STANDARD_SERVER_CORE * = 0x0000000D
-  PRODUCT_STANDARD_SERVER_CORE_V* = 0x00000028
-  PRODUCT_STANDARD_SERVER_V* = 0x00000024
-  PRODUCT_STARTER* = 0x0000000B
-  PRODUCT_STARTER_E* = 0x00000042
-  PRODUCT_STARTER_N* = 0x0000002F
-  PRODUCT_STORAGE_ENTERPRISE_SERVER* = 0x00000017
-  PRODUCT_STORAGE_EXPRESS_SERVER* = 0x00000014
-  PRODUCT_STORAGE_STANDARD_SERVER* = 0x00000015
-  PRODUCT_STORAGE_WORKGROUP_SERVER* = 0x00000016
-  PRODUCT_UNDEFINED* = 0x00000000
-  PRODUCT_ULTIMATE* = 0x00000001
-  PRODUCT_ULTIMATE_E* = 0x00000047
-  PRODUCT_ULTIMATE_N* = 0x0000001C
-  PRODUCT_WEB_SERVER* = 0x00000011
-  PRODUCT_WEB_SERVER_CORE* = 0x0000001D
-  
-  PROCESSOR_ARCHITECTURE_AMD64* = 9 ## x64 (AMD or Intel)
-  PROCESSOR_ARCHITECTURE_IA64* = 6 ## Intel Itanium Processor Family (IPF)
-  PROCESSOR_ARCHITECTURE_INTEL* = 0 ## x86
-  PROCESSOR_ARCHITECTURE_UNKNOWN* = 0xffff ## Unknown architecture.
-  
-  # GetSystemMetrics
-  SM_SERVERR2 = 89 
-  
-proc globalMemoryStatusEx*(lpBuffer: var TMEMORYSTATUSEX){.stdcall, dynlib: "kernel32",
-    importc: "GlobalMemoryStatusEx".}
-    
-proc getMemoryInfo*(): TMemoryInfo =
-  ## Retrieves memory info
-  var statex: TMEMORYSTATUSEX
-  statex.dwLength = sizeof(statex).int32
-
-  globalMemoryStatusEx(statex)
-  result.MemoryLoad = statex.dwMemoryLoad
-  result.TotalPhysMem = statex.ullTotalPhys
-  result.AvailablePhysMem = statex.ullAvailPhys
-  result.TotalPageFile = statex.ullTotalPageFile
-  result.AvailablePageFile = statex.ullAvailPageFile
-  result.TotalVirtualMem = statex.ullTotalVirtual
-  result.AvailableVirtualMem = statex.ullAvailExtendedVirtual
-
-proc getVersionEx*(lpVersionInformation: var TOSVERSIONINFOEX): WINBOOL{.stdcall,
-    dynlib: "kernel32", importc: "GetVersionExA".}
-
-proc getProcAddress*(hModule: int, lpProcName: cstring): pointer{.stdcall,
-    dynlib: "kernel32", importc: "GetProcAddress".}
-
-proc getModuleHandleA*(lpModuleName: cstring): int{.stdcall,
-     dynlib: "kernel32", importc: "GetModuleHandleA".}
-
-proc getVersionInfo*(): TVersionInfo =
-  ## Retrieves operating system info
-  var osvi: TOSVERSIONINFOEX
-  osvi.dwOSVersionInfoSize = sizeof(osvi).int32
-  discard getVersionEx(osvi)
-  result.majorVersion = osvi.dwMajorVersion
-  result.minorVersion = osvi.dwMinorVersion
-  result.buildNumber = osvi.dwBuildNumber
-  result.platformID = osvi.dwPlatformId
-  result.SPVersion = $osvi.szCSDVersion
-  result.SPMajor = osvi.wServicePackMajor
-  result.SPMinor = osvi.wServicePackMinor
-  result.SuiteMask = osvi.wSuiteMask
-  result.ProductType = osvi.wProductType
-
-proc getProductInfo*(majorVersion, minorVersion, SPMajorVersion, 
-                     SPMinorVersion: int): int =
-  ## Retrieves Windows' ProductInfo, this function only works in Vista and 7
-
-  var pGPI = cast[proc (dwOSMajorVersion, dwOSMinorVersion, 
-              dwSpMajorVersion, dwSpMinorVersion: int32, outValue: Pint32)](getProcAddress(
-                getModuleHandleA("kernel32.dll"), "GetProductInfo"))
-                
-  if pGPI != nil:
-    var dwType: int32
-    pGPI(int32(majorVersion), int32(minorVersion), int32(SPMajorVersion), int32(SPMinorVersion), addr(dwType))
-    result = int(dwType)
-  else:
-    return PRODUCT_UNDEFINED
-
-proc getSystemInfo*(lpSystemInfo: LPSYSTEM_INFO){.stdcall, dynlib: "kernel32",
-    importc: "GetSystemInfo".}
-    
-proc getSystemInfo*(): TSYSTEM_INFO =
-  ## Returns the SystemInfo
-
-  # Use GetNativeSystemInfo if it's available
-  var pGNSI = cast[proc (lpSystemInfo: LPSYSTEM_INFO)](getProcAddress(
-                getModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"))
-                
-  var systemi: TSYSTEM_INFO              
-  if pGNSI != nil:
-    pGNSI(addr(systemi))
-  else:
-    getSystemInfo(addr(systemi))
-
-  return systemi
-
-proc getSystemMetrics*(nIndex: int32): int32{.stdcall, dynlib: "user32",
-    importc: "GetSystemMetrics".}
-
-proc `$`*(osvi: TVersionInfo): string =
-  ## Turns a VersionInfo object, into a string
-
-  if osvi.platformID == VER_PLATFORM_WIN32_NT and osvi.majorVersion > 4:
-    result = "Microsoft "
-    
-    var si = getSystemInfo()
-    # Test for the specific product
-    if osvi.majorVersion == 6:
-      if osvi.minorVersion == 0:
-        if osvi.ProductType == VER_NT_WORKSTATION:
-          result.add("Windows Vista ")
-        else: result.add("Windows Server 2008 ")
-      elif osvi.minorVersion == 1:
-        if osvi.ProductType == VER_NT_WORKSTATION:
-          result.add("Windows 7 ")
-        else: result.add("Windows Server 2008 R2 ")
-    
-      var dwType = getProductInfo(osvi.majorVersion, osvi.minorVersion, 0, 0)
-      case dwType
-      of PRODUCT_ULTIMATE:
-        result.add("Ultimate Edition")
-      of PRODUCT_PROFESSIONAL:
-        result.add("Professional")
-      of PRODUCT_HOME_PREMIUM:
-        result.add("Home Premium Edition")
-      of PRODUCT_HOME_BASIC:
-        result.add("Home Basic Edition")
-      of PRODUCT_ENTERPRISE:
-        result.add("Enterprise Edition")
-      of PRODUCT_BUSINESS:
-        result.add("Business Edition")
-      of PRODUCT_STARTER:
-        result.add("Starter Edition")
-      of PRODUCT_CLUSTER_SERVER:
-        result.add("Cluster Server Edition")
-      of PRODUCT_DATACENTER_SERVER:
-        result.add("Datacenter Edition")
-      of PRODUCT_DATACENTER_SERVER_CORE:
-        result.add("Datacenter Edition (core installation)")
-      of PRODUCT_ENTERPRISE_SERVER:
-        result.add("Enterprise Edition")
-      of PRODUCT_ENTERPRISE_SERVER_CORE:
-        result.add("Enterprise Edition (core installation)")
-      of PRODUCT_ENTERPRISE_SERVER_IA64:
-        result.add("Enterprise Edition for Itanium-based Systems")
-      of PRODUCT_SMALLBUSINESS_SERVER:
-        result.add("Small Business Server")
-      of PRODUCT_STANDARD_SERVER:
-        result.add("Standard Edition")
-      of PRODUCT_STANDARD_SERVER_CORE:
-        result.add("Standard Edition (core installation)")
-      of PRODUCT_WEB_SERVER:
-        result.add("Web Server Edition")
-      else:
-        discard
-    # End of Windows 6.*
-
-    if osvi.majorVersion == 5 and osvi.minorVersion == 2:
-      if getSystemMetrics(SM_SERVERR2) != 0:
-        result.add("Windows Server 2003 R2, ")
-      elif (osvi.SuiteMask and VER_SUITE_PERSONAL) != 0: # Not sure if this will work
-        result.add("Windows Storage Server 2003")
-      elif (osvi.SuiteMask and VER_SUITE_WH_SERVER) != 0:
-        result.add("Windows Home Server")
-      elif osvi.ProductType == VER_NT_WORKSTATION and 
-          si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64:
-        result.add("Windows XP Professional x64 Edition")
-      else:
-        result.add("Windows Server 2003, ")
-      
-      # Test for the specific product
-      if osvi.ProductType != VER_NT_WORKSTATION:
-        if ze(si.wProcessorArchitecture) == PROCESSOR_ARCHITECTURE_IA64:
-          if (osvi.SuiteMask and VER_SUITE_DATACENTER) != 0:
-            result.add("Datacenter Edition for Itanium-based Systems")
-          elif (osvi.SuiteMask and VER_SUITE_ENTERPRISE) != 0:
-            result.add("Enterprise Edition for Itanium-based Systems")
-        elif ze(si.wProcessorArchitecture) == PROCESSOR_ARCHITECTURE_AMD64:
-          if (osvi.SuiteMask and VER_SUITE_DATACENTER) != 0:
-            result.add("Datacenter x64 Edition")
-          elif (osvi.SuiteMask and VER_SUITE_ENTERPRISE) != 0:
-            result.add("Enterprise x64 Edition")
-          else:
-            result.add("Standard x64 Edition")
-        else:
-          if (osvi.SuiteMask and VER_SUITE_COMPUTE_SERVER) != 0:
-            result.add("Compute Cluster Edition")
-          elif (osvi.SuiteMask and VER_SUITE_DATACENTER) != 0:
-            result.add("Datacenter Edition")
-          elif (osvi.SuiteMask and VER_SUITE_ENTERPRISE) != 0:
-            result.add("Enterprise Edition")
-          elif (osvi.SuiteMask and VER_SUITE_BLADE) != 0:
-            result.add("Web Edition")
-          else:
-            result.add("Standard Edition")
-    # End of 5.2
-    
-    if osvi.majorVersion == 5 and osvi.minorVersion == 1:
-      result.add("Windows XP ")
-      if (osvi.SuiteMask and VER_SUITE_PERSONAL) != 0:
-        result.add("Home Edition")
-      else:
-        result.add("Professional")
-    # End of 5.1
-    
-    if osvi.majorVersion == 5 and osvi.minorVersion == 0:
-      result.add("Windows 2000 ")
-      if osvi.ProductType == VER_NT_WORKSTATION:
-        result.add("Professional")
-      else:
-        if (osvi.SuiteMask and VER_SUITE_DATACENTER) != 0:
-          result.add("Datacenter Server")
-        elif (osvi.SuiteMask and VER_SUITE_ENTERPRISE) != 0:
-          result.add("Advanced Server")
-        else:
-          result.add("Server")
-    # End of 5.0
-    
-    # Include service pack (if any) and build number.
-    if len(osvi.SPVersion) > 0:
-      result.add(" ")
-      result.add(osvi.SPVersion)
-    
-    result.add(" (build " & $osvi.buildNumber & ")")
-    
-    if osvi.majorVersion >= 6:
-      if ze(si.wProcessorArchitecture) == PROCESSOR_ARCHITECTURE_AMD64:
-        result.add(", 64-bit")
-      elif ze(si.wProcessorArchitecture) == PROCESSOR_ARCHITECTURE_INTEL:
-        result.add(", 32-bit")
-    
-  else:
-    # Windows 98 etc...
-    result = "Unknown version of windows[Kernel version <= 4]"
-    
-
-proc getFileSize*(file: string): BiggestInt =
-  var fileData: TWIN32_FIND_DATA
-
-  when useWinUnicode:
-    var aa = newWideCString(file)
-    var hFile = findFirstFileW(aa, fileData)
-  else:
-    var hFile = findFirstFileA(file, fileData)
-  
-  if hFile == INVALID_HANDLE_VALUE:
-    raise newException(IOError, $getLastError())
-  
-  return fileData.nFileSizeLow
-
-proc getDiskFreeSpaceEx*(lpDirectoryName: cstring, lpFreeBytesAvailableToCaller,
-                         lpTotalNumberOfBytes,
-                         lpTotalNumberOfFreeBytes: var TFiletime): WINBOOL{.
-    stdcall, dynlib: "kernel32", importc: "GetDiskFreeSpaceExA".}
-
-proc getPartitionInfo*(partition: string): TPartitionInfo =
-  ## Retrieves partition info, for example ``partition`` may be ``"C:\"``
-  var freeBytes, totalBytes, totalFreeBytes: TFiletime 
-  discard getDiskFreeSpaceEx(r"C:\", freeBytes, totalBytes, 
-                               totalFreeBytes)
-  return (freeBytes, totalBytes)
-
-when isMainModule:
-  var r = getMemoryInfo()
-  echo("Memory load: ", r.MemoryLoad, "%")
-  
-  var osvi = getVersionInfo()
-  
-  echo($osvi)
-
-  echo(getFileSize(r"osinfo_win.nim") div 1024 div 1024)
-  
-  echo(rdFileTime(getPartitionInfo(r"C:\")[0]))
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+{.error: "This module has been moved to the 'osinfo' nimble package.".}
diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim
index 07ef13fd9..f4d00979c 100644
--- a/lib/impure/rdstdin.nim
+++ b/lib/impure/rdstdin.nim
@@ -1,21 +1,23 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
 ## This module contains code for reading from `stdin`:idx:. On UNIX the GNU
-## readline library is wrapped and set up to provide default key bindings 
+## readline library is wrapped and set up to provide default key bindings
 ## (e.g. you can navigate with the arrow keys). On Windows ``system.readLine``
-## is used. This suffices because Windows' console already provides the 
+## is used. This suffices because Windows' console already provides the
 ## wanted functionality.
 
+{.deadCodeElim: on.}
+
 when defined(Windows):
   proc readLineFromStdin*(prompt: string): TaintedString {.
-                          tags: [ReadIOEffect, WriteIOEffect].} = 
+                          tags: [ReadIOEffect, WriteIOEffect].} =
     ## Reads a line from stdin.
     stdout.write(prompt)
     result = readLine(stdin)
@@ -31,9 +33,75 @@ when defined(Windows):
     stdout.write(prompt)
     result = readLine(stdin, line)
 
+  import winlean
+
+  const
+    VK_SHIFT* = 16
+    VK_CONTROL* = 17
+    VK_MENU* = 18
+    KEY_EVENT* = 1
+
+  type
+    KEY_EVENT_RECORD = object
+      bKeyDown: WinBool
+      wRepeatCount: uint16
+      wVirtualKeyCode: uint16
+      wVirtualScanCode: uint16
+      unicodeChar: uint16
+      dwControlKeyState: uint32
+    INPUT_RECORD = object
+      eventType*: int16
+      reserved*: int16
+      event*: KEY_EVENT_RECORD
+      safetyBuffer: array[0..5, DWORD]
+
+  proc readConsoleInputW*(hConsoleInput: THANDLE, lpBuffer: var INPUTRECORD,
+                          nLength: uint32,
+                          lpNumberOfEventsRead: var uint32): WINBOOL{.
+      stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
+
+  proc getch(): uint16 =
+    let hStdin = getStdHandle(STD_INPUT_HANDLE)
+    var
+      irInputRecord: INPUT_RECORD
+      dwEventsRead: uint32
+
+    while readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead) != 0:
+      if irInputRecord.eventType == KEY_EVENT and
+          irInputRecord.event.wVirtualKeyCode notin {VK_SHIFT, VK_MENU, VK_CONTROL}:
+         result = irInputRecord.event.unicodeChar
+         discard readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead)
+         return result
+
+  from unicode import toUTF8, Rune, runeLenAt
+
+  proc readPasswordFromStdin*(prompt: string, password: var TaintedString):
+                              bool {.tags: [ReadIOEffect, WriteIOEffect].} =
+    ## Reads a `password` from stdin without printing it. `password` must not
+    ## be ``nil``! Returns ``false`` if the end of the file has been reached,
+    ## ``true`` otherwise.
+    password.setLen(0)
+    stdout.write(prompt)
+    while true:
+      let c = getch()
+      case c.char
+      of '\r', chr(0xA):
+        break
+      of '\b':
+        # ensure we delete the whole UTF-8 character:
+        var i = 0
+        var x = 1
+        while i < password.len:
+          x = runeLenAt(password, i)
+          inc i, x
+        password.setLen(password.len - x)
+      else:
+        password.add(toUTF8(c.Rune))
+    stdout.write "\n"
+
 else:
-  import readline, history
-    
+  import readline, history, termios, unsigned
+
   proc readLineFromStdin*(prompt: string): TaintedString {.
                           tags: [ReadIOEffect, WriteIOEffect].} =
     var buffer = readline.readLine(prompt)
@@ -55,8 +123,26 @@ else:
     result = true
 
   # initialization:
-  # disable auto-complete: 
+  # disable auto-complete:
   proc doNothing(a, b: cint): cint {.cdecl, procvar.} = discard
-  
+
   discard readline.bind_key('\t'.ord, doNothing)
 
+  proc readPasswordFromStdin*(prompt: string, password: var TaintedString):
+                              bool {.tags: [ReadIOEffect, WriteIOEffect].} =
+    password.setLen(0)
+    let fd = stdin.getFileHandle()
+    var cur, old: Termios
+    discard fd.tcgetattr(cur.addr)
+    old = cur
+    cur.c_lflag = cur.c_lflag and not Tcflag(ECHO)
+    discard fd.tcsetattr(TCSADRAIN, cur.addr)
+    stdout.write prompt
+    result = stdin.readLine(password)
+    stdout.write "\n"
+    discard fd.tcsetattr(TCSADRAIN, old.addr)
+
+proc readPasswordFromStdin*(prompt: string): TaintedString =
+  ## Reads a password from stdin without printing it.
+  result = TaintedString("")
+  discard readPasswordFromStdin(prompt, result)
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index a7bebb81c..fb95610f6 100644
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -7,8 +7,17 @@
 #    distribution, for details about the copyright.
 #
 
-## Regular expression support for Nim. Consider using the pegs module
-## instead.
+## Regular expression support for Nim. Consider using the pegs module instead.
+##
+## There is an alternative regular expressions library with a more unified API:
+## `nre <https://github.com/flaviut/nre>`_. It may be added to the standard
+## library in the future, instead of `re`.
+##
+## **Note:** The 're' proc defaults to the **extended regular expression
+## syntax** which lets you use whitespace freely to make your regexes readable.
+## However, this means to match whitespace ``\s`` or something similar has
+## to be used.
+##
 ## This module is implemented by providing a wrapper around the
 ## `PRCE (Perl-Compatible Regular Expressions) <http://www.pcre.org>`_
 ## C library. This means that your application will depend on the PRCE
@@ -30,42 +39,42 @@ const
 type
   RegexFlag* = enum     ## options for regular expressions
     reIgnoreCase = 0,    ## do caseless matching
-    reMultiLine = 1,     ## ``^`` and ``$`` match newlines within data 
+    reMultiLine = 1,     ## ``^`` and ``$`` match newlines within data
     reDotAll = 2,        ## ``.`` matches anything including NL
     reExtended = 3,      ## ignore whitespace and ``#`` comments
     reStudy = 4          ## study the expression (may be omitted if the
                          ## expression will be used only once)
-    
+  
   RegexDesc = object 
-    h: PPcre
-    e: ptr TExtra
-    
+    h: ptr Pcre
+    e: ptr ExtraData
+  
   Regex* = ref RegexDesc ## a compiled regular expression
-    
+
   RegexError* = object of ValueError
     ## is raised if the pattern is no valid regular expression.
 
 {.deprecated: [TRegexFlag: RegexFlag, TRegexDesc: RegexDesc, TRegex: Regex,
     EInvalidRegEx: RegexError].}
 
-proc raiseInvalidRegex(msg: string) {.noinline, noreturn.} = 
+proc raiseInvalidRegex(msg: string) {.noinline, noreturn.} =
   var e: ref RegexError
   new(e)
   e.msg = msg
   raise e
 
-proc rawCompile(pattern: string, flags: cint): PPcre =
+proc rawCompile(pattern: string, flags: cint): ptr Pcre =
   var
     msg: cstring
     offset: cint
   result = pcre.compile(pattern, flags, addr(msg), addr(offset), nil)
   if result == nil:
-    raiseInvalidRegex($msg & "\n" & pattern & "\n" & repeatChar(offset) & "^\n")
+    raiseInvalidRegex($msg & "\n" & pattern & "\n" & spaces(offset) & "^\n")
 
-proc finalizeRegEx(x: Regex) = 
+proc finalizeRegEx(x: Regex) =
   # XXX This is a hack, but PCRE does not export its "free" function properly.
   # Sigh. The hack relies on PCRE's implementation (see ``pcre_get.c``).
-  # Fortunately the implementation is unlikely to change. 
+  # Fortunately the implementation is unlikely to change.
   pcre.free_substring(cast[cstring](x.h))
   if not isNil(x.e):
     pcre.free_substring(cast[cstring](x.e))
@@ -78,7 +87,7 @@ proc re*(s: string, flags = {reExtended, reStudy}): Regex =
   result.h = rawCompile(s, cast[cint](flags - {reStudy}))
   if reStudy in flags:
     var msg: cstring
-    result.e = pcre.study(result.h, 0, msg)
+    result.e = pcre.study(result.h, 0, addr msg)
     if not isNil(msg): raiseInvalidRegex($msg)
 
 proc matchOrFind(s: string, pattern: Regex, matches: var openArray[string],
@@ -95,10 +104,10 @@ proc matchOrFind(s: string, pattern: Regex, matches: var openArray[string],
     if a >= 0'i32: matches[i-1] = substr(s, int(a), int(b)-1)
     else: matches[i-1] = nil
   return rawMatches[1] - rawMatches[0]
-  
+
 proc findBounds*(s: string, pattern: Regex, matches: var openArray[string],
                  start = 0): tuple[first, last: int] =
-  ## returns the starting position and end position of `pattern` in `s` 
+  ## returns the starting position and end position of `pattern` in `s`
   ## and the captured
   ## substrings in the array `matches`. If it does not match, nothing
   ## is written into `matches` and ``(-1,0)`` is returned.
@@ -114,12 +123,12 @@ proc findBounds*(s: string, pattern: Regex, matches: var openArray[string],
     if a >= 0'i32: matches[i-1] = substr(s, int(a), int(b)-1)
     else: matches[i-1] = nil
   return (rawMatches[0].int, rawMatches[1].int - 1)
-  
-proc findBounds*(s: string, pattern: Regex, 
+
+proc findBounds*(s: string, pattern: Regex,
                  matches: var openArray[tuple[first, last: int]],
                  start = 0): tuple[first, last: int] =
-  ## returns the starting position and end position of ``pattern`` in ``s`` 
-  ## and the captured substrings in the array `matches`. 
+  ## returns the starting position and end position of ``pattern`` in ``s``
+  ## and the captured substrings in the array `matches`.
   ## If it does not match, nothing is written into `matches` and
   ## ``(-1,0)`` is returned.
   var
@@ -135,7 +144,7 @@ proc findBounds*(s: string, pattern: Regex,
     else: matches[i-1] = (-1,0)
   return (rawMatches[0].int, rawMatches[1].int - 1)
 
-proc findBounds*(s: string, pattern: Regex, 
+proc findBounds*(s: string, pattern: Regex,
                  start = 0): tuple[first, last: int] =
   ## returns the starting position of `pattern` in `s`. If it does not
   ## match, ``(-1,0)`` is returned.
@@ -146,7 +155,7 @@ proc findBounds*(s: string, pattern: Regex,
       cast[ptr cint](rawMatches), 3)
   if res < 0'i32: return (int(res), 0)
   return (int(rawMatches[0]), int(rawMatches[1]-1))
-  
+
 proc matchOrFind(s: string, pattern: Regex, start, flags: cint): cint =
   var
     rtarray = initRtArray[cint](3)
@@ -156,19 +165,6 @@ proc matchOrFind(s: string, pattern: Regex, start, flags: cint): cint =
   if result >= 0'i32:
     result = rawMatches[1] - rawMatches[0]
 
-proc match*(s: string, pattern: Regex, matches: var openArray[string],
-           start = 0): bool =
-  ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and
-  ## the captured substrings in the array ``matches``. If it does not
-  ## match, nothing is written into ``matches`` and ``false`` is
-  ## returned.
-  return matchOrFind(s, pattern, matches, start.cint, 
-                     pcre.ANCHORED) == cint(s.len - start)
-
-proc match*(s: string, pattern: Regex, start = 0): bool =
-  ## returns ``true`` if ``s[start..]`` matches the ``pattern``.
-  return matchOrFind(s, pattern, start.cint, pcre.ANCHORED) == cint(s.len-start)
-
 proc matchLen*(s: string, pattern: Regex, matches: var openArray[string],
               start = 0): int =
   ## the same as ``match``, but it returns the length of the match,
@@ -179,9 +175,21 @@ proc matchLen*(s: string, pattern: Regex, matches: var openArray[string],
 proc matchLen*(s: string, pattern: Regex, start = 0): int =
   ## the same as ``match``, but it returns the length of the match,
   ## if there is no match, -1 is returned. Note that a match length
-  ## of zero can happen. 
+  ## of zero can happen.
   return matchOrFind(s, pattern, start.cint, pcre.ANCHORED)
 
+proc match*(s: string, pattern: Regex, start = 0): bool =
+  ## returns ``true`` if ``s[start..]`` matches the ``pattern``.
+  result = matchLen(s, pattern, start) != -1
+
+proc match*(s: string, pattern: Regex, matches: var openArray[string],
+           start = 0): bool =
+  ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and
+  ## the captured substrings in the array ``matches``. If it does not
+  ## match, nothing is written into ``matches`` and ``false`` is
+  ## returned.
+  result = matchLen(s, pattern, matches, start) != -1
+
 proc find*(s: string, pattern: Regex, matches: var openArray[string],
            start = 0): int =
   ## returns the starting position of ``pattern`` in ``s`` and the captured
@@ -211,7 +219,7 @@ proc find*(s: string, pattern: Regex, start = 0): int =
   if res < 0'i32: return res
   return rawMatches[0]
 
-iterator findAll*(s: string, pattern: Regex, start = 0): string = 
+iterator findAll*(s: string, pattern: Regex, start = 0): string =
   ## Yields all matching *substrings* of `s` that match `pattern`.
   ##
   ## Note that since this is an iterator you should not modify the string you
@@ -226,10 +234,11 @@ iterator findAll*(s: string, pattern: Regex, start = 0): string =
     if res < 0'i32: break
     let a = rawMatches[0]
     let b = rawMatches[1]
+    if a == b and a == i: break
     yield substr(s, int(a), int(b)-1)
     i = b
 
-proc findAll*(s: string, pattern: Regex, start = 0): seq[string] = 
+proc findAll*(s: string, pattern: Regex, start = 0): seq[string] =
   ## returns all matching *substrings* of `s` that match `pattern`.
   ## If it does not match, @[] is returned.
   accumulateResult(findAll(s, pattern, start))
@@ -237,13 +246,13 @@ proc findAll*(s: string, pattern: Regex, start = 0): seq[string] =
 when not defined(nimhygiene):
   {.pragma: inject.}
 
-template `=~` *(s: string, pattern: Regex): expr = 
-  ## This calls ``match`` with an implicit declared ``matches`` array that 
-  ## can be used in the scope of the ``=~`` call: 
-  ## 
+template `=~` *(s: string, pattern: Regex): expr =
+  ## This calls ``match`` with an implicit declared ``matches`` array that
+  ## can be used in the scope of the ``=~`` call:
+  ##
   ## .. code-block:: nim
   ##
-  ##   if line =~ re"\s*(\w+)\s*\=\s*(\w+)": 
+  ##   if line =~ re"\s*(\w+)\s*\=\s*(\w+)":
   ##     # matches a key=value pair:
   ##     echo("Key: ", matches[0])
   ##     echo("Value: ", matches[1])
@@ -255,9 +264,9 @@ template `=~` *(s: string, pattern: Regex): expr =
   ##   else:
   ##     echo("syntax error")
   ##
-  bind MaxSubPatterns
+  bind MaxSubpatterns
   when not declaredInScope(matches):
-    var matches {.inject.}: array[0..MaxSubpatterns-1, string]
+    var matches {.inject.}: array[MaxSubpatterns, string]
   match(s, pattern, matches)
 
 # ------------------------- more string handling ------------------------------
@@ -281,11 +290,11 @@ proc endsWith*(s: string, suffix: Regex): bool =
     if matchLen(s, suffix, i) == s.len - i: return true
 
 proc replace*(s: string, sub: Regex, by = ""): string =
-  ## Replaces `sub` in `s` by the string `by`. Captures cannot be 
+  ## Replaces `sub` in `s` by the string `by`. Captures cannot be
   ## accessed in `by`. Examples:
   ##
   ## .. code-block:: nim
-  ##   "var1=key; var2=key2".replace(re"(\w+)'='(\w+)")
+  ##   "var1=key; var2=key2".replace(re"(\w+)=(\w+)")
   ##
   ## Results in:
   ##
@@ -301,13 +310,13 @@ proc replace*(s: string, sub: Regex, by = ""): string =
     add(result, by)
     prev = match.last + 1
   add(result, substr(s, prev))
-  
+
 proc replacef*(s: string, sub: Regex, by: string): string =
   ## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by`
   ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
   ##
   ## .. code-block:: nim
-  ## "var1=key; var2=key2".replacef(re"(\w+)'='(\w+)", "$1<-$2$2")
+  ##   "var1=key; var2=key2".replacef(re"(\w+)=(\w+)", "$1<-$2$2")
   ##
   ## Results in:
   ##
@@ -315,7 +324,7 @@ proc replacef*(s: string, sub: Regex, by: string): string =
   ##
   ## "var1<-keykey; val2<-key2key2"
   result = ""
-  var caps: array[0..MaxSubpatterns-1, string]
+  var caps: array[MaxSubpatterns, string]
   var prev = 0
   while true:
     var match = findBounds(s, sub, caps, prev)
@@ -333,7 +342,7 @@ proc parallelReplace*(s: string, subs: openArray[
   ## applied in parallel.
   result = ""
   var i = 0
-  var caps: array[0..MaxSubpatterns-1, string]
+  var caps: array[MaxSubpatterns, string]
   while i < s.len:
     block searchSubs:
       for j in 0..high(subs):
@@ -354,7 +363,7 @@ proc transformFile*(infile, outfile: string,
   ## error occurs. This is supposed to be used for quick scripting.
   var x = readFile(infile).string
   writeFile(outfile, x.parallelReplace(subs))
-  
+
 iterator split*(s: string, sep: Regex): string =
   ## Splits the string `s` into substrings.
   ##
@@ -368,64 +377,73 @@ iterator split*(s: string, sep: Regex): string =
   ## Results in:
   ##
   ## .. code-block:: nim
+  ##   ""
   ##   "this"
   ##   "is"
   ##   "an"
   ##   "example"
+  ##   ""
   ##
   var
-    first = 0
-    last = 0
+    first = -1
+    last = -1
   while last < len(s):
     var x = matchLen(s, sep, last)
     if x > 0: inc(last, x)
     first = last
+    if x == 0: inc(last)
     while last < len(s):
-      inc(last)
       x = matchLen(s, sep, last)
-      if x > 0: break
-    if first < last:
+      if x >= 0: break
+      inc(last)
+    if first <= last:
       yield substr(s, first, last-1)
 
 proc split*(s: string, sep: Regex): seq[string] =
   ## Splits the string `s` into substrings.
   accumulateResult(split(s, sep))
-  
-proc escapeRe*(s: string): string = 
-  ## escapes `s` so that it is matched verbatim when used as a regular 
+
+proc escapeRe*(s: string): string =
+  ## escapes `s` so that it is matched verbatim when used as a regular
   ## expression.
   result = ""
   for c in items(s):
     case c
     of 'a'..'z', 'A'..'Z', '0'..'9', '_':
       result.add(c)
-    else: 
+    else:
       result.add("\\x")
       result.add(toHex(ord(c), 2))
-  
+
 const ## common regular expressions
-  reIdentifier* = r"\b[a-zA-Z_]+[a-zA-Z_0-9]*\b"  ## describes an identifier
-  reNatural* = r"\b\d+\b" ## describes a natural number
-  reInteger* = r"\b[-+]?\d+\b" ## describes an integer
-  reHex* = r"\b0[xX][0-9a-fA-F]+\b" ## describes a hexadecimal number
-  reBinary* = r"\b0[bB][01]+\b" ## describes a binary number (example: 0b11101)
-  reOctal* = r"\b0[oO][0-7]+\b" ## describes an octal number (example: 0o777)
-  reFloat* = r"\b[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\b"
+  reIdentifier* {.deprecated.} = r"\b[a-zA-Z_]+[a-zA-Z_0-9]*\b"
+    ## describes an identifier
+  reNatural* {.deprecated.} = r"\b\d+\b"
+    ## describes a natural number
+  reInteger* {.deprecated.} = r"\b[-+]?\d+\b"
+    ## describes an integer
+  reHex* {.deprecated.} = r"\b0[xX][0-9a-fA-F]+\b"
+    ## describes a hexadecimal number
+  reBinary* {.deprecated.} = r"\b0[bB][01]+\b"
+    ## describes a binary number (example: 0b11101)
+  reOctal* {.deprecated.} = r"\b0[oO][0-7]+\b"
+    ## describes an octal number (example: 0o777)
+  reFloat* {.deprecated.} = r"\b[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\b"
     ## describes a floating point number
-  reEmail* = r"\b[a-zA-Z0-9!#$%&'*+/=?^_`{|}~\-]+(?:\. &" &
-             r"[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)" &
-             r"*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+" &
-             r"(?:[a-zA-Z]{2}|com|org|" &
-             r"net|gov|mil|biz|info|mobi|name|aero|jobs|museum)\b"
+  reEmail* {.deprecated.} = r"\b[a-zA-Z0-9!#$%&'*+/=?^_`{|}~\-]+(?:\. &" &
+                            r"[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@" &
+                            r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+" &
+                            r"(?:[a-zA-Z]{2}|com|org|net|gov|mil|biz|" &
+                            r"info|mobi|name|aero|jobs|museum)\b"
     ## describes a common email address
-  reURL* = r"\b(http(s)?|ftp|gopher|telnet|file|notes|ms\-help):" &
-           r"((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-\=\\\.\&]*\b"
+  reURL* {.deprecated.} = r"\b(http(s)?|ftp|gopher|telnet|file|notes|ms-help)" &
+                          r":((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-\=\\\.\&]*\b"
     ## describes an URL
 
 when isMainModule:
   assert match("(a b c)", re"\( .* \)")
   assert match("WHiLe", re("while", {reIgnoreCase}))
-  
+
   assert "0158787".match(re"\d+")
   assert "ABC 0232".match(re"\w+\s+\d+")
   assert "ABC".match(re"\d+ | \w+")
@@ -434,21 +452,21 @@ when isMainModule:
 
   var pattern = re"[a-z0-9]+\s*=\s*[a-z0-9]+"
   assert matchLen("key1=  cal9", pattern) == 11
-  
+
   assert find("_____abc_______", re"abc") == 5
-  
-  var matches: array[0..5, string]
-  if match("abcdefg", re"c(d)ef(g)", matches, 2): 
+
+  var matches: array[6, string]
+  if match("abcdefg", re"c(d)ef(g)", matches, 2):
     assert matches[0] == "d"
     assert matches[1] == "g"
   else:
     assert false
-  
+
   if "abc" =~ re"(a)bcxyz|(\w+)":
     assert matches[1] == "abc"
   else:
     assert false
-  
+
   if "abc" =~ re"(cba)?.*":
     assert matches[0] == nil
   else: assert false
@@ -456,23 +474,35 @@ when isMainModule:
   if "abc" =~ re"().*":
     assert matches[0] == ""
   else: assert false
-    
+
   assert "var1=key; var2=key2".endsWith(re"\w+=\w+")
   assert("var1=key; var2=key2".replacef(re"(\w+)=(\w+)", "$1<-$2$2") ==
          "var1<-keykey; var2<-key2key2")
   assert("var1=key; var2=key2".replace(re"(\w+)=(\w+)", "$1<-$2$2") ==
          "$1<-$2$2; $1<-$2$2")
 
+  var accum: seq[string] = @[]
   for word in split("00232this02939is39an22example111", re"\d+"):
-    writeln(stdout, word)
+    accum.add(word)
+  assert(accum == @["", "this", "is", "an", "example", ""])
+
+  accum = @[]
+  for word in split("AAA :   : BBB", re"\s*:\s*"):
+    accum.add(word)
+  assert(accum == @["AAA", "", "BBB"])
 
   for x in findAll("abcdef", re"^{.}", 3):
     assert x == "d"
+  accum = @[]
   for x in findAll("abcdef", re".", 3):
-    echo x
+    accum.add(x)
+  assert(accum == @["d", "e", "f"])
+
+  assert("XYZ".find(re"^\d*") == 0)
+  assert("XYZ".match(re"^\d*") == true)
 
   block:
-    var matches: array[0..15, string]
+    var matches: array[16, string]
     if match("abcdefghijklmnop", re"(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)(n)(o)(p)", matches):
       for i in 0..matches.high:
         assert matches[i] == $chr(i + 'a'.ord)
diff --git a/lib/impure/ssl.nim b/lib/impure/ssl.nim
index bb7cfc0d3..d318a1979 100644
--- a/lib/impure/ssl.nim
+++ b/lib/impure/ssl.nim
@@ -82,7 +82,7 @@ proc close*(sock: TSecureSocket) =
     ERR_print_errors_fp(stderr)
     raiseOSError(osLastError())
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   var s: TSecureSocket
   echo connect(s, "smtp.gmail.com", 465)
   
diff --git a/lib/js/dom.nim b/lib/js/dom.nim
index 91b260a64..94f4fa29c 100644
--- a/lib/js/dom.nim
+++ b/lib/js/dom.nim
@@ -36,8 +36,11 @@ type
     onsubmit*: proc (event: ref TEvent) {.nimcall.}
     onunload*: proc (event: ref TEvent) {.nimcall.}
 
-  TWindow* {.importc.} = object of TEventHandlers
-    document*: ref TDocument
+    addEventListener*: proc(ev: cstring, cb: proc(ev: ref TEvent), useCapture: bool = false) {.nimcall.}
+
+  Window* = ref WindowObj
+  WindowObj {.importc.} = object of TEventHandlers
+    document*: Document
     event*: ref TEvent
     history*: ref THistory
     location*: ref TLocation
@@ -65,7 +68,7 @@ type
     confirm*: proc (msg: cstring): bool {.nimcall.}
     disableExternalCapture*: proc () {.nimcall.}
     enableExternalCapture*: proc () {.nimcall.}
-    find*: proc (text: cstring, caseSensitive = false, 
+    find*: proc (text: cstring, caseSensitive = false,
                  backwards = false) {.nimcall.}
     focus*: proc () {.nimcall.}
     forward*: proc () {.nimcall.}
@@ -74,7 +77,7 @@ type
     moveBy*: proc (x, y: int) {.nimcall.}
     moveTo*: proc (x, y: int) {.nimcall.}
     open*: proc (uri, windowname: cstring,
-                 properties: cstring = nil): ref TWindow {.nimcall.}
+                 properties: cstring = nil): Window {.nimcall.}
     print*: proc () {.nimcall.}
     prompt*: proc (text, default: cstring): cstring {.nimcall.}
     releaseEvents*: proc (eventMask: int) {.nimcall.}
@@ -88,9 +91,65 @@ type
     stop*: proc () {.nimcall.}
     frames*: seq[TFrame]
 
-  TFrame* {.importc.} = object of TWindow
+  Frame* = ref FrameObj
+  FrameObj {.importc.} = object of WindowObj
+
+  ClassList* {.importc.} = object of RootObj
+    add*: proc (class: cstring) {.nimcall.}
+    remove*: proc (class: cstring) {.nimcall.}
+    contains*: proc (class: cstring):bool {.nimcall.}
+    toggle*: proc (class: cstring) {.nimcall.}
+
+  TNodeType* = enum
+    ElementNode = 1,
+    AttributeNode,
+    TextNode,
+    CDATANode,
+    EntityRefNode,
+    EntityNode,
+    ProcessingInstructionNode,
+    CommentNode,
+    DocumentNode,
+    DocumentTypeNode,
+    DocumentFragmentNode,
+    NotationNode
+
+  Node* = ref NodeObj
+  NodeObj {.importc.} = object of TEventHandlers
+    attributes*: seq[Node]
+    childNodes*: seq[Node]
+    children*: seq[Node]
+    data*: cstring
+    firstChild*: Node
+    lastChild*: Node
+    nextSibling*: Node
+    nodeName*: cstring
+    nodeType*: TNodeType
+    nodeValue*: cstring
+    parentNode*: Node
+    previousSibling*: Node
+    appendChild*: proc (child: Node) {.nimcall.}
+    appendData*: proc (data: cstring) {.nimcall.}
+    cloneNode*: proc (copyContent: bool): Node {.nimcall.}
+    deleteData*: proc (start, len: int) {.nimcall.}
+    getAttribute*: proc (attr: cstring): cstring {.nimcall.}
+    getAttributeNode*: proc (attr: cstring): Node {.nimcall.}
+    hasChildNodes*: proc (): bool {.nimcall.}
+    innerHTML*: cstring
+    insertBefore*: proc (newNode, before: Node) {.nimcall.}
+    insertData*: proc (position: int, data: cstring) {.nimcall.}
+    removeAttribute*: proc (attr: cstring) {.nimcall.}
+    removeAttributeNode*: proc (attr: Node) {.nimcall.}
+    removeChild*: proc (child: Node) {.nimcall.}
+    replaceChild*: proc (newNode, oldNode: Node) {.nimcall.}
+    replaceData*: proc (start, len: int, text: cstring) {.nimcall.}
+    scrollIntoView*: proc () {.nimcall.}
+    setAttribute*: proc (name, value: cstring) {.nimcall.}
+    setAttributeNode*: proc (attr: Node) {.nimcall.}
+    style*: ref TStyle
 
-  TDocument* {.importc.} = object of TEventHandlers
+  Document* = ref DocumentObj
+  DocumentObj {.importc.} = object of NodeObj
     alinkColor*: cstring
     bgColor*: cstring
     charset*: cstring
@@ -104,12 +163,13 @@ type
     URL*: cstring
     vlinkColor*: cstring
     captureEvents*: proc (eventMask: int) {.nimcall.}
-    createAttribute*: proc (identifier: cstring): ref TNode {.nimcall.}
-    createElement*: proc (identifier: cstring): ref TNode {.nimcall.}
-    createTextNode*: proc (identifier: cstring): ref TNode {.nimcall.}
-    getElementById*: proc (id: cstring): ref TNode {.nimcall.}
-    getElementsByName*: proc (name: cstring): seq[ref TNode] {.nimcall.}
-    getElementsByTagName*: proc (name: cstring): seq[ref TNode] {.nimcall.}
+    createAttribute*: proc (identifier: cstring): Node {.nimcall.}
+    createElement*: proc (identifier: cstring): Element {.nimcall.}
+    createTextNode*: proc (identifier: cstring): Node {.nimcall.}
+    getElementById*: proc (id: cstring): Element {.nimcall.}
+    getElementsByName*: proc (name: cstring): seq[Element] {.nimcall.}
+    getElementsByTagName*: proc (name: cstring): seq[Element] {.nimcall.}
+    getElementsByClassName*: proc (name: cstring): seq[Element] {.nimcall.}
     getSelection*: proc (): cstring {.nimcall.}
     handleEvent*: proc (event: ref TEvent) {.nimcall.}
     open*: proc () {.nimcall.}
@@ -117,24 +177,43 @@ type
     routeEvent*: proc (event: ref TEvent) {.nimcall.}
     write*: proc (text: cstring) {.nimcall.}
     writeln*: proc (text: cstring) {.nimcall.}
-    anchors*: seq[ref TAnchor]
-    forms*: seq[ref TForm]
-    images*: seq[ref TImage]
+    anchors*: seq[AnchorElement]
+    forms*: seq[FormElement]
+    images*: seq[ImageElement]
     applets*: seq[ref TApplet]
-    embeds*: seq[ref TEmbed]
-    links*: seq[ref TLink]
+    embeds*: seq[EmbedElement]
+    links*: seq[LinkElement]
 
-  TLink* {.importc.} = object of RootObj
+  Element* = ref ElementObj
+  ElementObj {.importc.} = object of NodeObj
+    classList*: ref Classlist
+    checked*: bool
+    defaultChecked*: bool
+    defaultValue*: cstring
+    disabled*: bool
+    form*: FormElement
     name*: cstring
+    readOnly*: bool
+    blur*: proc () {.nimcall.}
+    click*: proc () {.nimcall.}
+    focus*: proc () {.nimcall.}
+    handleEvent*: proc (event: ref TEvent) {.nimcall.}
+    select*: proc () {.nimcall.}
+    options*: seq[OptionElement]
+    getElementsByTagName*: proc (name: cstring): seq[Element] {.nimcall.}
+    getElementsByClassName*: proc (name: cstring): seq[Element] {.nimcall.}
+
+  LinkElement* = ref LinkObj
+  LinkObj {.importc.} = object of ElementObj
     target*: cstring
     text*: cstring
     x*: int
     y*: int
 
-  TEmbed* {.importc.} = object of RootObj
+  EmbedElement* = ref EmbedObj
+  EmbedObj {.importc.} = object of ElementObj
     height*: int
     hspace*: int
-    name*: cstring
     src*: cstring
     width*: int
     `type`*: cstring
@@ -142,104 +221,42 @@ type
     play*: proc () {.nimcall.}
     stop*: proc () {.nimcall.}
 
-  TAnchor* {.importc.} = object of RootObj
-    name*: cstring
+  AnchorElement* = ref AnchorObj
+  AnchorObj {.importc.} = object of ElementObj
     text*: cstring
     x*, y*: int
 
   TApplet* {.importc.} = object of RootObj
 
-  TElement* {.importc.} = object of TEventHandlers
-    checked*: bool
-    defaultChecked*: bool
-    defaultValue*: cstring
-    disabled*: bool
-    form*: ref TForm
-    name*: cstring
-    readOnly*: bool
-    `type`*: cstring
-    value*: cstring
-    blur*: proc () {.nimcall.}
-    click*: proc () {.nimcall.}
-    focus*: proc () {.nimcall.}
-    handleEvent*: proc (event: ref TEvent) {.nimcall.}
-    select*: proc () {.nimcall.}
-    options*: seq[ref TOption]
-
-  TOption* {.importc.} = object of RootObj
+  OptionElement* = ref OptionObj
+  OptionObj {.importc.} = object of ElementObj
     defaultSelected*: bool
     selected*: bool
     selectedIndex*: int
     text*: cstring
     value*: cstring
 
-  TForm* {.importc.} = object of TEventHandlers
+  FormElement* = ref FormObj
+  FormObj {.importc.} = object of ElementObj
     action*: cstring
     encoding*: cstring
     `method`*: cstring
-    name*: cstring
     target*: cstring
-    handleEvent*: proc (event: ref TEvent) {.nimcall.}
     reset*: proc () {.nimcall.}
     submit*: proc () {.nimcall.}
-    elements*: seq[ref TElement]
+    elements*: seq[Element]
 
-  TImage* {.importc.} = object of TEventHandlers
+  ImageElement* = ref ImageObj
+  ImageObj {.importc.} = object of ElementObj
     border*: int
     complete*: bool
     height*: int
     hspace*: int
     lowsrc*: cstring
-    name*: cstring
     src*: cstring
     vspace*: int
     width*: int
-    handleEvent*: proc (event: ref TEvent) {.nimcall.}
 
-  TNodeType* = enum
-    ElementNode = 1,
-    AttributeNode,
-    TextNode,
-    CDATANode,
-    EntityRefNode,
-    EntityNode,
-    ProcessingInstructionNode,
-    CommentNode,
-    DocumentNode,
-    DocumentTypeNode,
-    DocumentFragmentNode,
-    NotationNode
-  TNode* {.importc.} = object of RootObj
-    attributes*: seq[ref TNode]
-    childNodes*: seq[ref TNode]
-    data*: cstring
-    firstChild*: ref TNode
-    lastChild*: ref TNode
-    nextSibling*: ref TNode
-    nodeName*: cstring
-    nodeType*: TNodeType
-    nodeValue*: cstring
-    parentNode*: ref TNode
-    previousSibling*: ref TNode
-    appendChild*: proc (child: ref TNode) {.nimcall.}
-    appendData*: proc (data: cstring) {.nimcall.}
-    cloneNode*: proc (copyContent: bool) {.nimcall.}
-    deleteData*: proc (start, len: int) {.nimcall.}
-    getAttribute*: proc (attr: cstring): cstring {.nimcall.}
-    getAttributeNode*: proc (attr: cstring): ref TNode {.nimcall.}
-    getElementsByTagName*: proc (): seq[ref TNode] {.nimcall.}
-    hasChildNodes*: proc (): bool {.nimcall.}
-    innerHTML*: cstring
-    insertBefore*: proc (newNode, before: ref TNode) {.nimcall.}
-    insertData*: proc (position: int, data: cstring) {.nimcall.}
-    removeAttribute*: proc (attr: cstring) {.nimcall.}
-    removeAttributeNode*: proc (attr: ref TNode) {.nimcall.}
-    removeChild*: proc (child: ref TNode) {.nimcall.}
-    replaceChild*: proc (newNode, oldNode: ref TNode) {.nimcall.}
-    replaceData*: proc (start, len: int, text: cstring) {.nimcall.}
-    setAttribute*: proc (name, value: cstring) {.nimcall.}
-    setAttributeNode*: proc (attr: ref TNode) {.nimcall.}
-    style*: ref TStyle
 
   TStyle* {.importc.} = object of RootObj
     background*: cstring
@@ -336,6 +353,7 @@ type
     setAttribute*: proc (attr, value: cstring, caseSensitive=false) {.nimcall.}
 
   TEvent* {.importc.} = object of RootObj
+    target*: Node
     altKey*, ctrlKey*, shiftKey*: bool
     button*: int
     clientX*, clientY*: int
@@ -433,8 +451,8 @@ type
   TInterval* {.importc.} = object of RootObj
 
 var
-  window* {.importc, nodecl.}: ref TWindow
-  document* {.importc, nodecl.}: ref TDocument
+  window* {.importc, nodecl.}: Window
+  document* {.importc, nodecl.}: Document
   navigator* {.importc, nodecl.}: ref TNavigator
   screen* {.importc, nodecl.}: ref TScreen
 
@@ -450,3 +468,18 @@ proc isFinite*(x: BiggestFloat): bool {.importc, nodecl.}
 proc isNaN*(x: BiggestFloat): bool {.importc, nodecl.}
 proc parseFloat*(s: cstring): BiggestFloat {.importc, nodecl.}
 proc parseInt*(s: cstring): int {.importc, nodecl.}
+proc parseInt*(s: cstring, radix: int):int {.importc, nodecl.}
+
+
+type
+  TWindow* {.deprecated.} = WindowObj
+  TFrame* {.deprecated.} = FrameObj
+  TNode* {.deprecated.} = NodeObj
+  TDocument* {.deprecated.} = DocumentObj
+  TElement* {.deprecated.} = ElementObj
+  TLink* {.deprecated.} = LinkObj
+  TEmbed* {.deprecated.} = EmbedObj
+  TAnchor* {.deprecated.} = AnchorObj
+  TOption* {.deprecated.} = OptionObj
+  TForm* {.deprecated.} = FormObj
+  TImage* {.deprecated.} = ImageObj
diff --git a/lib/nimbase.h b/lib/nimbase.h
index ac90081d8..eea618bac 100644
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -1,7 +1,7 @@
 /*
 
             Nim's Runtime Library
-        (c) Copyright 2014 Andreas Rumpf
+        (c) Copyright 2015 Andreas Rumpf
 
     See the file "copying.txt", included in this
     distribution, for details about the copyright.
@@ -67,7 +67,7 @@ __clang__
 #endif
 
 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
-#  define NIM_THREADVAR __declspec(thread) 
+#  define NIM_THREADVAR __declspec(thread)
 #else
 #  define NIM_THREADVAR __thread
 #endif
@@ -103,7 +103,11 @@ __clang__
 #  define N_FASTCALL_PTR(rettype, name) rettype (__fastcall *name)
 #  define N_SAFECALL_PTR(rettype, name) rettype (__safecall *name)
 
-#  define N_LIB_EXPORT  extern __declspec(dllexport)
+#  ifdef __cplusplus
+#    define N_LIB_EXPORT  extern "C" __declspec(dllexport)
+#  else
+#    define N_LIB_EXPORT  extern __declspec(dllexport)
+#  endif
 #  define N_LIB_IMPORT  extern __declspec(dllimport)
 #else
 #  define N_CDECL(rettype, name) rettype name
@@ -118,7 +122,11 @@ __clang__
 #  define N_FASTCALL_PTR(rettype, name) rettype (*name)
 #  define N_SAFECALL_PTR(rettype, name) rettype (*name)
 
-#  define N_LIB_EXPORT  extern
+#  ifdef __cplusplus
+#    define N_LIB_EXPORT  extern "C"
+#  else
+#    define N_LIB_EXPORT  extern
+#  endif
 #  define N_LIB_IMPORT  extern
 #endif
 
@@ -335,17 +343,17 @@ struct TFrame {
 };
 
 #define nimfr(proc, file) \
-  TFrame F; \
-  F.procname = proc; F.filename = file; F.line = 0; F.len = 0; nimFrame(&F);
+  TFrame FR; \
+  FR.procname = proc; FR.filename = file; FR.line = 0; FR.len = 0; nimFrame(&FR);
 
 #define nimfrs(proc, file, slots, length) \
-  struct {TFrame* prev;NCSTRING procname;NI line;NCSTRING filename; NI len; TVarSlot s[slots];} F; \
-  F.procname = proc; F.filename = file; F.line = 0; F.len = length; nimFrame((TFrame*)&F);
+  struct {TFrame* prev;NCSTRING procname;NI line;NCSTRING filename; NI len; TVarSlot s[slots];} FR; \
+  FR.procname = proc; FR.filename = file; FR.line = 0; FR.len = length; nimFrame((TFrame*)&FR);
 
 #define nimln(n, file) \
-  F.line = n; F.filename = file;
+  FR.line = n; FR.filename = file;
 
-#define NIM_POSIX_INIT  __attribute__((constructor)) 
+#define NIM_POSIX_INIT  __attribute__((constructor))
 
 #if defined(_MSCVER) && defined(__i386__)
 __declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
@@ -379,8 +387,8 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
 #  define GC_GUARD
 #endif
 
-/* Test to see if nimrod and the C compiler agree on the size of a pointer.
-   On disagreement, your C compiler will say something like: 
+/* Test to see if Nim and the C compiler agree on the size of a pointer.
+   On disagreement, your C compiler will say something like:
    "error: 'assert_numbits' declared as an array with a negative size" */
 typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
 #endif
@@ -390,3 +398,14 @@ typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(
 #else
 #  define NIM_EXTERNC
 #endif
+
+/* ---------------- platform specific includes ----------------------- */
+
+/* VxWorks related includes */
+#if defined(__VXWORKS__)
+#  include <sys/types.h>
+#  include <types/vxWind.h>
+#  include <tool/gnu/toolMacros.h>
+#elif defined(__FreeBSD__)
+#  include <sys/types.h>
+#endif
diff --git a/lib/nimrtl.nimrod.cfg b/lib/nimrtl.nim.cfg
index b60de183a..b60de183a 100644
--- a/lib/nimrtl.nimrod.cfg
+++ b/lib/nimrtl.nim.cfg
diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim
index 7fc2e1aa3..9485f3912 100644
--- a/lib/packages/docutils/highlite.nim
+++ b/lib/packages/docutils/highlite.nim
@@ -14,14 +14,14 @@
 import
   strutils
 
-type 
-  TTokenClass* = enum 
-    gtEof, gtNone, gtWhitespace, gtDecNumber, gtBinNumber, gtHexNumber, 
-    gtOctNumber, gtFloatNumber, gtIdentifier, gtKeyword, gtStringLit, 
+type
+  TTokenClass* = enum
+    gtEof, gtNone, gtWhitespace, gtDecNumber, gtBinNumber, gtHexNumber,
+    gtOctNumber, gtFloatNumber, gtIdentifier, gtKeyword, gtStringLit,
     gtLongStringLit, gtCharLit, gtEscapeSequence, # escape sequence like \xff
-    gtOperator, gtPunctuation, gtComment, gtLongComment, gtRegularExpression, 
-    gtTagStart, gtTagEnd, gtKey, gtValue, gtRawData, gtAssembler, 
-    gtPreprocessor, gtDirective, gtCommand, gtRule, gtHyperlink, gtLabel, 
+    gtOperator, gtPunctuation, gtComment, gtLongComment, gtRegularExpression,
+    gtTagStart, gtTagEnd, gtKey, gtValue, gtRawData, gtAssembler,
+    gtPreprocessor, gtDirective, gtCommand, gtRule, gtHyperlink, gtLabel,
     gtReference, gtOther
   TGeneralTokenizer* = object of RootObj
     kind*: TTokenClass
@@ -30,27 +30,27 @@ type
     pos: int
     state: TTokenClass
 
-  TSourceLanguage* = enum 
+  TSourceLanguage* = enum
     langNone, langNim, langNimrod, langCpp, langCsharp, langC, langJava
 
-const 
+const
   sourceLanguageToStr*: array[TSourceLanguage, string] = ["none",
     "Nim", "Nimrod", "C++", "C#", "C", "Java"]
-  tokenClassToStr*: array[TTokenClass, string] = ["Eof", "None", "Whitespace", 
-    "DecNumber", "BinNumber", "HexNumber", "OctNumber", "FloatNumber", 
-    "Identifier", "Keyword", "StringLit", "LongStringLit", "CharLit", 
-    "EscapeSequence", "Operator", "Punctuation", "Comment", "LongComment", 
-    "RegularExpression", "TagStart", "TagEnd", "Key", "Value", "RawData", 
-    "Assembler", "Preprocessor", "Directive", "Command", "Rule", "Hyperlink", 
+  tokenClassToStr*: array[TTokenClass, string] = ["Eof", "None", "Whitespace",
+    "DecNumber", "BinNumber", "HexNumber", "OctNumber", "FloatNumber",
+    "Identifier", "Keyword", "StringLit", "LongStringLit", "CharLit",
+    "EscapeSequence", "Operator", "Punctuation", "Comment", "LongComment",
+    "RegularExpression", "TagStart", "TagEnd", "Key", "Value", "RawData",
+    "Assembler", "Preprocessor", "Directive", "Command", "Rule", "Hyperlink",
     "Label", "Reference", "Other"]
 
   # The following list comes from doc/keywords.txt, make sure it is
   # synchronized with this array by running the module itself as a test case.
   nimKeywords = ["addr", "and", "as", "asm", "atomic", "bind", "block",
-    "break", "case", "cast", "const", "continue", "converter",
+    "break", "case", "cast", "concept", "const", "continue", "converter",
     "defer", "discard", "distinct", "div", "do",
     "elif", "else", "end", "enum", "except", "export",
-    "finally", "for", "from", "func", 
+    "finally", "for", "from", "func",
     "generic", "if", "import", "in", "include",
     "interface", "is", "isnot", "iterator", "let", "macro", "method",
     "mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc",
@@ -58,12 +58,12 @@ const
     "template", "try", "tuple", "type", "using", "var", "when", "while", "with",
     "without", "xor", "yield"]
 
-proc getSourceLanguage*(name: string): TSourceLanguage = 
-  for i in countup(succ(low(TSourceLanguage)), high(TSourceLanguage)): 
-    if cmpIgnoreStyle(name, sourceLanguageToStr[i]) == 0: 
+proc getSourceLanguage*(name: string): TSourceLanguage =
+  for i in countup(succ(low(TSourceLanguage)), high(TSourceLanguage)):
+    if cmpIgnoreStyle(name, sourceLanguageToStr[i]) == 0:
       return i
   result = langNone
-  
+
 proc initGeneralTokenizer*(g: var TGeneralTokenizer, buf: cstring) =
   g.buf = buf
   g.kind = low(TTokenClass)
@@ -74,52 +74,52 @@ proc initGeneralTokenizer*(g: var TGeneralTokenizer, buf: cstring) =
   while g.buf[pos] in {' ', '\x09'..'\x0D'}: inc(pos)
   g.pos = pos
 
-proc initGeneralTokenizer*(g: var TGeneralTokenizer, buf: string) = 
+proc initGeneralTokenizer*(g: var TGeneralTokenizer, buf: string) =
   initGeneralTokenizer(g, cstring(buf))
 
-proc deinitGeneralTokenizer*(g: var TGeneralTokenizer) = 
+proc deinitGeneralTokenizer*(g: var TGeneralTokenizer) =
   discard
 
-proc nimGetKeyword(id: string): TTokenClass = 
+proc nimGetKeyword(id: string): TTokenClass =
   for k in nimKeywords:
     if cmpIgnoreStyle(id, k) == 0: return gtKeyword
   result = gtIdentifier
   when false:
     var i = getIdent(id)
     if (i.id >= ord(tokKeywordLow) - ord(tkSymbol)) and
-        (i.id <= ord(tokKeywordHigh) - ord(tkSymbol)): 
+        (i.id <= ord(tokKeywordHigh) - ord(tkSymbol)):
       result = gtKeyword
-    else: 
+    else:
       result = gtIdentifier
-  
-proc nimNumberPostfix(g: var TGeneralTokenizer, position: int): int = 
+
+proc nimNumberPostfix(g: var TGeneralTokenizer, position: int): int =
   var pos = position
-  if g.buf[pos] == '\'': 
+  if g.buf[pos] == '\'':
     inc(pos)
     case g.buf[pos]
-    of 'f', 'F': 
+    of 'f', 'F':
       g.kind = gtFloatNumber
       inc(pos)
       if g.buf[pos] in {'0'..'9'}: inc(pos)
       if g.buf[pos] in {'0'..'9'}: inc(pos)
-    of 'i', 'I': 
+    of 'i', 'I':
       inc(pos)
       if g.buf[pos] in {'0'..'9'}: inc(pos)
       if g.buf[pos] in {'0'..'9'}: inc(pos)
-    else: 
+    else:
       discard
   result = pos
 
-proc nimNumber(g: var TGeneralTokenizer, position: int): int = 
+proc nimNumber(g: var TGeneralTokenizer, position: int): int =
   const decChars = {'0'..'9', '_'}
   var pos = position
   g.kind = gtDecNumber
   while g.buf[pos] in decChars: inc(pos)
-  if g.buf[pos] == '.': 
+  if g.buf[pos] == '.':
     g.kind = gtFloatNumber
     inc(pos)
     while g.buf[pos] in decChars: inc(pos)
-  if g.buf[pos] in {'e', 'E'}: 
+  if g.buf[pos] in {'e', 'E'}:
     g.kind = gtFloatNumber
     inc(pos)
     if g.buf[pos] in {'+', '-'}: inc(pos)
@@ -127,150 +127,150 @@ proc nimNumber(g: var TGeneralTokenizer, position: int): int =
   result = nimNumberPostfix(g, pos)
 
 const
-  OpChars  = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', '.', 
+  OpChars  = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', '.',
               '|', '=', '%', '&', '$', '@', '~', ':', '\x80'..'\xFF'}
 
-proc nimNextToken(g: var TGeneralTokenizer) = 
-  const 
+proc nimNextToken(g: var TGeneralTokenizer) =
+  const
     hexChars = {'0'..'9', 'A'..'F', 'a'..'f', '_'}
     octChars = {'0'..'7', '_'}
     binChars = {'0'..'1', '_'}
     SymChars = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'}
   var pos = g.pos
   g.start = g.pos
-  if g.state == gtStringLit: 
+  if g.state == gtStringLit:
     g.kind = gtStringLit
-    while true: 
+    while true:
       case g.buf[pos]
-      of '\\': 
+      of '\\':
         g.kind = gtEscapeSequence
         inc(pos)
         case g.buf[pos]
-        of 'x', 'X': 
+        of 'x', 'X':
           inc(pos)
           if g.buf[pos] in hexChars: inc(pos)
           if g.buf[pos] in hexChars: inc(pos)
-        of '0'..'9': 
+        of '0'..'9':
           while g.buf[pos] in {'0'..'9'}: inc(pos)
-        of '\0': 
+        of '\0':
           g.state = gtNone
         else: inc(pos)
-        break 
-      of '\0', '\x0D', '\x0A': 
+        break
+      of '\0', '\x0D', '\x0A':
         g.state = gtNone
-        break 
-      of '\"': 
+        break
+      of '\"':
         inc(pos)
         g.state = gtNone
-        break 
+        break
       else: inc(pos)
-  else: 
+  else:
     case g.buf[pos]
-    of ' ', '\x09'..'\x0D': 
+    of ' ', '\x09'..'\x0D':
       g.kind = gtWhitespace
       while g.buf[pos] in {' ', '\x09'..'\x0D'}: inc(pos)
-    of '#': 
+    of '#':
       g.kind = gtComment
       while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}): inc(pos)
-    of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF': 
+    of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF':
       var id = ""
-      while g.buf[pos] in SymChars + {'_'}: 
+      while g.buf[pos] in SymChars + {'_'}:
         add(id, g.buf[pos])
         inc(pos)
-      if (g.buf[pos] == '\"'): 
-        if (g.buf[pos + 1] == '\"') and (g.buf[pos + 2] == '\"'): 
+      if (g.buf[pos] == '\"'):
+        if (g.buf[pos + 1] == '\"') and (g.buf[pos + 2] == '\"'):
           inc(pos, 3)
           g.kind = gtLongStringLit
-          while true: 
+          while true:
             case g.buf[pos]
-            of '\0': 
-              break 
-            of '\"': 
+            of '\0':
+              break
+            of '\"':
               inc(pos)
-              if g.buf[pos] == '\"' and g.buf[pos+1] == '\"' and 
-                  g.buf[pos+2] != '\"': 
+              if g.buf[pos] == '\"' and g.buf[pos+1] == '\"' and
+                  g.buf[pos+2] != '\"':
                 inc(pos, 2)
-                break 
+                break
             else: inc(pos)
-        else: 
+        else:
           g.kind = gtRawData
           inc(pos)
-          while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}): 
+          while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}):
             if g.buf[pos] == '"' and g.buf[pos+1] != '"': break
             inc(pos)
           if g.buf[pos] == '\"': inc(pos)
-      else: 
+      else:
         g.kind = nimGetKeyword(id)
-    of '0': 
+    of '0':
       inc(pos)
       case g.buf[pos]
-      of 'b', 'B': 
+      of 'b', 'B':
         inc(pos)
         while g.buf[pos] in binChars: inc(pos)
         pos = nimNumberPostfix(g, pos)
-      of 'x', 'X': 
+      of 'x', 'X':
         inc(pos)
         while g.buf[pos] in hexChars: inc(pos)
         pos = nimNumberPostfix(g, pos)
-      of 'o', 'O': 
+      of 'o', 'O':
         inc(pos)
         while g.buf[pos] in octChars: inc(pos)
         pos = nimNumberPostfix(g, pos)
       else: pos = nimNumber(g, pos)
-    of '1'..'9': 
+    of '1'..'9':
       pos = nimNumber(g, pos)
-    of '\'': 
+    of '\'':
       inc(pos)
       g.kind = gtCharLit
-      while true: 
+      while true:
         case g.buf[pos]
-        of '\0', '\x0D', '\x0A': 
-          break 
-        of '\'': 
+        of '\0', '\x0D', '\x0A':
+          break
+        of '\'':
           inc(pos)
-          break 
-        of '\\': 
+          break
+        of '\\':
           inc(pos, 2)
         else: inc(pos)
-    of '\"': 
+    of '\"':
       inc(pos)
-      if (g.buf[pos] == '\"') and (g.buf[pos + 1] == '\"'): 
+      if (g.buf[pos] == '\"') and (g.buf[pos + 1] == '\"'):
         inc(pos, 2)
         g.kind = gtLongStringLit
-        while true: 
+        while true:
           case g.buf[pos]
-          of '\0': 
-            break 
-          of '\"': 
+          of '\0':
+            break
+          of '\"':
             inc(pos)
-            if g.buf[pos] == '\"' and g.buf[pos+1] == '\"' and 
-                g.buf[pos+2] != '\"': 
+            if g.buf[pos] == '\"' and g.buf[pos+1] == '\"' and
+                g.buf[pos+2] != '\"':
               inc(pos, 2)
-              break 
+              break
           else: inc(pos)
-      else: 
+      else:
         g.kind = gtStringLit
-        while true: 
+        while true:
           case g.buf[pos]
-          of '\0', '\x0D', '\x0A': 
-            break 
-          of '\"': 
+          of '\0', '\x0D', '\x0A':
+            break
+          of '\"':
             inc(pos)
-            break 
-          of '\\': 
+            break
+          of '\\':
             g.state = g.kind
-            break 
+            break
           else: inc(pos)
-    of '(', ')', '[', ']', '{', '}', '`', ':', ',', ';': 
+    of '(', ')', '[', ']', '{', '}', '`', ':', ',', ';':
       inc(pos)
       g.kind = gtPunctuation
-    of '\0': 
+    of '\0':
       g.kind = gtEof
-    else: 
-      if g.buf[pos] in OpChars: 
+    else:
+      if g.buf[pos] in OpChars:
         g.kind = gtOperator
         while g.buf[pos] in OpChars: inc(pos)
-      else: 
+      else:
         inc(pos)
         g.kind = gtNone
   g.length = pos - g.pos
@@ -278,211 +278,211 @@ proc nimNextToken(g: var TGeneralTokenizer) =
     assert false, "nimNextToken: produced an empty token"
   g.pos = pos
 
-proc generalNumber(g: var TGeneralTokenizer, position: int): int = 
+proc generalNumber(g: var TGeneralTokenizer, position: int): int =
   const decChars = {'0'..'9'}
   var pos = position
   g.kind = gtDecNumber
   while g.buf[pos] in decChars: inc(pos)
-  if g.buf[pos] == '.': 
+  if g.buf[pos] == '.':
     g.kind = gtFloatNumber
     inc(pos)
     while g.buf[pos] in decChars: inc(pos)
-  if g.buf[pos] in {'e', 'E'}: 
+  if g.buf[pos] in {'e', 'E'}:
     g.kind = gtFloatNumber
     inc(pos)
     if g.buf[pos] in {'+', '-'}: inc(pos)
     while g.buf[pos] in decChars: inc(pos)
   result = pos
 
-proc generalStrLit(g: var TGeneralTokenizer, position: int): int = 
-  const 
+proc generalStrLit(g: var TGeneralTokenizer, position: int): int =
+  const
     decChars = {'0'..'9'}
     hexChars = {'0'..'9', 'A'..'F', 'a'..'f'}
   var pos = position
   g.kind = gtStringLit
   var c = g.buf[pos]
   inc(pos)                    # skip " or '
-  while true: 
+  while true:
     case g.buf[pos]
-    of '\0': 
-      break 
-    of '\\': 
+    of '\0':
+      break
+    of '\\':
       inc(pos)
       case g.buf[pos]
-      of '\0': 
-        break 
-      of '0'..'9': 
+      of '\0':
+        break
+      of '0'..'9':
         while g.buf[pos] in decChars: inc(pos)
-      of 'x', 'X': 
+      of 'x', 'X':
         inc(pos)
         if g.buf[pos] in hexChars: inc(pos)
         if g.buf[pos] in hexChars: inc(pos)
       else: inc(pos, 2)
-    else: 
-      if g.buf[pos] == c: 
+    else:
+      if g.buf[pos] == c:
         inc(pos)
-        break 
-      else: 
+        break
+      else:
         inc(pos)
   result = pos
 
-proc isKeyword(x: openArray[string], y: string): int = 
+proc isKeyword(x: openArray[string], y: string): int =
   var a = 0
   var b = len(x) - 1
-  while a <= b: 
+  while a <= b:
     var mid = (a + b) div 2
     var c = cmp(x[mid], y)
-    if c < 0: 
+    if c < 0:
       a = mid + 1
-    elif c > 0: 
+    elif c > 0:
       b = mid - 1
-    else: 
+    else:
       return mid
   result = - 1
 
-proc isKeywordIgnoreCase(x: openArray[string], y: string): int = 
+proc isKeywordIgnoreCase(x: openArray[string], y: string): int =
   var a = 0
   var b = len(x) - 1
-  while a <= b: 
+  while a <= b:
     var mid = (a + b) div 2
     var c = cmpIgnoreCase(x[mid], y)
-    if c < 0: 
+    if c < 0:
       a = mid + 1
-    elif c > 0: 
+    elif c > 0:
       b = mid - 1
-    else: 
+    else:
       return mid
   result = - 1
 
-type 
-  TTokenizerFlag = enum 
+type
+  TTokenizerFlag = enum
     hasPreprocessor, hasNestedComments
   TTokenizerFlags = set[TTokenizerFlag]
 
-proc clikeNextToken(g: var TGeneralTokenizer, keywords: openArray[string], 
-                    flags: TTokenizerFlags) = 
-  const 
+proc clikeNextToken(g: var TGeneralTokenizer, keywords: openArray[string],
+                    flags: TTokenizerFlags) =
+  const
     hexChars = {'0'..'9', 'A'..'F', 'a'..'f'}
     octChars = {'0'..'7'}
     binChars = {'0'..'1'}
     symChars = {'A'..'Z', 'a'..'z', '0'..'9', '_', '\x80'..'\xFF'}
   var pos = g.pos
   g.start = g.pos
-  if g.state == gtStringLit: 
+  if g.state == gtStringLit:
     g.kind = gtStringLit
-    while true: 
+    while true:
       case g.buf[pos]
-      of '\\': 
+      of '\\':
         g.kind = gtEscapeSequence
         inc(pos)
         case g.buf[pos]
-        of 'x', 'X': 
+        of 'x', 'X':
           inc(pos)
           if g.buf[pos] in hexChars: inc(pos)
           if g.buf[pos] in hexChars: inc(pos)
-        of '0'..'9': 
+        of '0'..'9':
           while g.buf[pos] in {'0'..'9'}: inc(pos)
-        of '\0': 
+        of '\0':
           g.state = gtNone
         else: inc(pos)
-        break 
-      of '\0', '\x0D', '\x0A': 
+        break
+      of '\0', '\x0D', '\x0A':
         g.state = gtNone
-        break 
-      of '\"': 
+        break
+      of '\"':
         inc(pos)
         g.state = gtNone
-        break 
+        break
       else: inc(pos)
-  else: 
+  else:
     case g.buf[pos]
-    of ' ', '\x09'..'\x0D': 
+    of ' ', '\x09'..'\x0D':
       g.kind = gtWhitespace
       while g.buf[pos] in {' ', '\x09'..'\x0D'}: inc(pos)
-    of '/': 
+    of '/':
       inc(pos)
-      if g.buf[pos] == '/': 
+      if g.buf[pos] == '/':
         g.kind = gtComment
         while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}): inc(pos)
-      elif g.buf[pos] == '*': 
+      elif g.buf[pos] == '*':
         g.kind = gtLongComment
         var nested = 0
         inc(pos)
-        while true: 
+        while true:
           case g.buf[pos]
-          of '*': 
+          of '*':
             inc(pos)
-            if g.buf[pos] == '/': 
+            if g.buf[pos] == '/':
               inc(pos)
-              if nested == 0: break 
-          of '/': 
+              if nested == 0: break
+          of '/':
             inc(pos)
-            if g.buf[pos] == '*': 
+            if g.buf[pos] == '*':
               inc(pos)
               if hasNestedComments in flags: inc(nested)
-          of '\0': 
-            break 
+          of '\0':
+            break
           else: inc(pos)
-    of '#': 
+    of '#':
       inc(pos)
-      if hasPreprocessor in flags: 
+      if hasPreprocessor in flags:
         g.kind = gtPreprocessor
         while g.buf[pos] in {' ', '\t'}: inc(pos)
         while g.buf[pos] in symChars: inc(pos)
-      else: 
+      else:
         g.kind = gtOperator
-    of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF': 
+    of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF':
       var id = ""
-      while g.buf[pos] in symChars: 
+      while g.buf[pos] in symChars:
         add(id, g.buf[pos])
         inc(pos)
       if isKeyword(keywords, id) >= 0: g.kind = gtKeyword
       else: g.kind = gtIdentifier
-    of '0': 
+    of '0':
       inc(pos)
       case g.buf[pos]
-      of 'b', 'B': 
+      of 'b', 'B':
         inc(pos)
         while g.buf[pos] in binChars: inc(pos)
         if g.buf[pos] in {'A'..'Z', 'a'..'z'}: inc(pos)
-      of 'x', 'X': 
+      of 'x', 'X':
         inc(pos)
         while g.buf[pos] in hexChars: inc(pos)
         if g.buf[pos] in {'A'..'Z', 'a'..'z'}: inc(pos)
-      of '0'..'7': 
+      of '0'..'7':
         inc(pos)
         while g.buf[pos] in octChars: inc(pos)
         if g.buf[pos] in {'A'..'Z', 'a'..'z'}: inc(pos)
-      else: 
+      else:
         pos = generalNumber(g, pos)
         if g.buf[pos] in {'A'..'Z', 'a'..'z'}: inc(pos)
-    of '1'..'9': 
+    of '1'..'9':
       pos = generalNumber(g, pos)
       if g.buf[pos] in {'A'..'Z', 'a'..'z'}: inc(pos)
-    of '\'': 
+    of '\'':
       pos = generalStrLit(g, pos)
       g.kind = gtCharLit
-    of '\"': 
+    of '\"':
       inc(pos)
       g.kind = gtStringLit
-      while true: 
+      while true:
         case g.buf[pos]
-        of '\0': 
-          break 
-        of '\"': 
+        of '\0':
+          break
+        of '\"':
           inc(pos)
-          break 
-        of '\\': 
+          break
+        of '\\':
           g.state = g.kind
-          break 
+          break
         else: inc(pos)
-    of '(', ')', '[', ']', '{', '}', ':', ',', ';', '.': 
+    of '(', ')', '[', ']', '{', '}', ':', ',', ';', '.':
       inc(pos)
       g.kind = gtPunctuation
-    of '\0': 
+    of '\0':
       g.kind = gtEof
-    else: 
-      if g.buf[pos] in OpChars: 
+    else:
+      if g.buf[pos] in OpChars:
         g.kind = gtOperator
         while g.buf[pos] in OpChars: inc(pos)
       else:
@@ -493,55 +493,55 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openArray[string],
     assert false, "clikeNextToken: produced an empty token"
   g.pos = pos
 
-proc cNextToken(g: var TGeneralTokenizer) = 
-  const 
-    keywords: array[0..36, string] = ["_Bool", "_Complex", "_Imaginary", "auto", 
-      "break", "case", "char", "const", "continue", "default", "do", "double", 
-      "else", "enum", "extern", "float", "for", "goto", "if", "inline", "int", 
-      "long", "register", "restrict", "return", "short", "signed", "sizeof", 
-      "static", "struct", "switch", "typedef", "union", "unsigned", "void", 
+proc cNextToken(g: var TGeneralTokenizer) =
+  const
+    keywords: array[0..36, string] = ["_Bool", "_Complex", "_Imaginary", "auto",
+      "break", "case", "char", "const", "continue", "default", "do", "double",
+      "else", "enum", "extern", "float", "for", "goto", "if", "inline", "int",
+      "long", "register", "restrict", "return", "short", "signed", "sizeof",
+      "static", "struct", "switch", "typedef", "union", "unsigned", "void",
       "volatile", "while"]
   clikeNextToken(g, keywords, {hasPreprocessor})
 
-proc cppNextToken(g: var TGeneralTokenizer) = 
-  const 
-    keywords: array[0..47, string] = ["asm", "auto", "break", "case", "catch", 
-      "char", "class", "const", "continue", "default", "delete", "do", "double", 
-      "else", "enum", "extern", "float", "for", "friend", "goto", "if", 
-      "inline", "int", "long", "new", "operator", "private", "protected", 
-      "public", "register", "return", "short", "signed", "sizeof", "static", 
-      "struct", "switch", "template", "this", "throw", "try", "typedef", 
+proc cppNextToken(g: var TGeneralTokenizer) =
+  const
+    keywords: array[0..47, string] = ["asm", "auto", "break", "case", "catch",
+      "char", "class", "const", "continue", "default", "delete", "do", "double",
+      "else", "enum", "extern", "float", "for", "friend", "goto", "if",
+      "inline", "int", "long", "new", "operator", "private", "protected",
+      "public", "register", "return", "short", "signed", "sizeof", "static",
+      "struct", "switch", "template", "this", "throw", "try", "typedef",
       "union", "unsigned", "virtual", "void", "volatile", "while"]
   clikeNextToken(g, keywords, {hasPreprocessor})
 
-proc csharpNextToken(g: var TGeneralTokenizer) = 
-  const 
-    keywords: array[0..76, string] = ["abstract", "as", "base", "bool", "break", 
-      "byte", "case", "catch", "char", "checked", "class", "const", "continue", 
-      "decimal", "default", "delegate", "do", "double", "else", "enum", "event", 
-      "explicit", "extern", "false", "finally", "fixed", "float", "for", 
-      "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", 
-      "is", "lock", "long", "namespace", "new", "null", "object", "operator", 
-      "out", "override", "params", "private", "protected", "public", "readonly", 
-      "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", 
-      "static", "string", "struct", "switch", "this", "throw", "true", "try", 
-      "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", 
+proc csharpNextToken(g: var TGeneralTokenizer) =
+  const
+    keywords: array[0..76, string] = ["abstract", "as", "base", "bool", "break",
+      "byte", "case", "catch", "char", "checked", "class", "const", "continue",
+      "decimal", "default", "delegate", "do", "double", "else", "enum", "event",
+      "explicit", "extern", "false", "finally", "fixed", "float", "for",
+      "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal",
+      "is", "lock", "long", "namespace", "new", "null", "object", "operator",
+      "out", "override", "params", "private", "protected", "public", "readonly",
+      "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc",
+      "static", "string", "struct", "switch", "this", "throw", "true", "try",
+      "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using",
       "virtual", "void", "volatile", "while"]
   clikeNextToken(g, keywords, {hasPreprocessor})
 
-proc javaNextToken(g: var TGeneralTokenizer) = 
-  const 
-    keywords: array[0..52, string] = ["abstract", "assert", "boolean", "break", 
-      "byte", "case", "catch", "char", "class", "const", "continue", "default", 
-      "do", "double", "else", "enum", "extends", "false", "final", "finally", 
-      "float", "for", "goto", "if", "implements", "import", "instanceof", "int", 
-      "interface", "long", "native", "new", "null", "package", "private", 
-      "protected", "public", "return", "short", "static", "strictfp", "super", 
-      "switch", "synchronized", "this", "throw", "throws", "transient", "true", 
+proc javaNextToken(g: var TGeneralTokenizer) =
+  const
+    keywords: array[0..52, string] = ["abstract", "assert", "boolean", "break",
+      "byte", "case", "catch", "char", "class", "const", "continue", "default",
+      "do", "double", "else", "enum", "extends", "false", "final", "finally",
+      "float", "for", "goto", "if", "implements", "import", "instanceof", "int",
+      "interface", "long", "native", "new", "null", "package", "private",
+      "protected", "public", "return", "short", "static", "strictfp", "super",
+      "switch", "synchronized", "this", "throw", "throws", "transient", "true",
       "try", "void", "volatile", "while"]
   clikeNextToken(g, keywords, {})
 
-proc getNextToken*(g: var TGeneralTokenizer, lang: TSourceLanguage) = 
+proc getNextToken*(g: var TGeneralTokenizer, lang: TSourceLanguage) =
   case lang
   of langNone: assert false
   of langNim, langNimrod: nimNextToken(g)
@@ -549,15 +549,17 @@ proc getNextToken*(g: var TGeneralTokenizer, lang: TSourceLanguage) =
   of langCsharp: csharpNextToken(g)
   of langC: cNextToken(g)
   of langJava: javaNextToken(g)
-  
+
 when isMainModule:
   var keywords: seq[string]
   # Try to work running in both the subdir or at the root.
   for filename in ["doc/keywords.txt", "../../../doc/keywords.txt"]:
-    except: echo filename, " not found"
-    let input = string(readFile(filename))
-    keywords = input.split()
-    break
+    try:
+      let input = string(readFile(filename))
+      keywords = input.split()
+      break
+    except:
+      echo filename, " not found"
   doAssert(not keywords.isNil, "Couldn't read any keywords.txt file!")
   doAssert keywords.len == nimKeywords.len, "No matching lengths"
   for i in 0..keywords.len-1:
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index 95d49bad7..2ee94ba13 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -11,25 +11,25 @@
 ## subset is implemented. Some features of the `markdown`:idx: wiki syntax are
 ## also supported.
 
-import 
+import
   os, strutils, rstast
 
 type
-  TRstParseOption* = enum     ## options for the RST parser 
+  TRstParseOption* = enum     ## options for the RST parser
     roSkipPounds,             ## skip ``#`` at line beginning (documentation
                               ## embedded in Nim comments)
     roSupportSmilies,         ## make the RST parser support smilies like ``:)``
     roSupportRawDirective,    ## support the ``raw`` directive (don't support
                               ## it for sandboxing)
     roSupportMarkdown         ## support additional features of markdown
-  
+
   TRstParseOptions* = set[TRstParseOption]
-  
+
   TMsgClass* = enum
-    mcHint = "Hint", 
-    mcWarning = "Warning", 
+    mcHint = "Hint",
+    mcWarning = "Warning",
     mcError = "Error"
-  
+
   TMsgKind* = enum          ## the possible messages
     meCannotOpenFile,
     meExpected,
@@ -41,20 +41,20 @@ type
     mwUnknownSubstitution,
     mwUnsupportedLanguage,
     mwUnsupportedField
-  
+
   TMsgHandler* = proc (filename: string, line, col: int, msgKind: TMsgKind,
                        arg: string) {.nimcall.} ## what to do in case of an error
   TFindFileHandler* = proc (filename: string): string {.nimcall.}
 
 const
   messages: array [TMsgKind, string] = [
-    meCannotOpenFile: "cannot open '$1'", 
+    meCannotOpenFile: "cannot open '$1'",
     meExpected: "'$1' expected",
     meGridTableNotImplemented: "grid table is not implemented",
-    meNewSectionExpected: "new section expected", 
+    meNewSectionExpected: "new section expected",
     meGeneralParseError: "general parse error",
     meInvalidDirective: "invalid directive: '$1'",
-    mwRedefinitionOfLabel: "redefinition of label '$1'", 
+    mwRedefinitionOfLabel: "redefinition of label '$1'",
     mwUnknownSubstitution: "unknown substitution '$1'",
     mwUnsupportedLanguage: "language '$1' not supported",
     mwUnsupportedField: "field '$1' not supported"
@@ -67,7 +67,7 @@ proc getArgument*(n: PRstNode): string
 
 # ----------------------------- scanner part --------------------------------
 
-const 
+const
   SymChars: set[char] = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'}
   SmileyStartChars: set[char] = {':', ';', '8'}
   Smilies = {
@@ -111,14 +111,14 @@ const
   }
 
 type
-  TTokType = enum 
+  TTokType = enum
     tkEof, tkIndent, tkWhite, tkWord, tkAdornment, tkPunct, tkOther
   TToken = object             # a RST token
     kind*: TTokType           # the type of the token
     ival*: int                # the indentation or parsed integer value
     symbol*: string           # the parsed symbol as string
     line*, col*: int          # line and column of the token
-  
+
   TTokenSeq = seq[TToken]
   TLexer = object of RootObj
     buf*: cstring
@@ -127,61 +127,61 @@ type
     skipPounds*: bool
 
 
-proc getThing(L: var TLexer, tok: var TToken, s: set[char]) = 
+proc getThing(L: var TLexer, tok: var TToken, s: set[char]) =
   tok.kind = tkWord
   tok.line = L.line
   tok.col = L.col
   var pos = L.bufpos
-  while true: 
+  while true:
     add(tok.symbol, L.buf[pos])
     inc(pos)
-    if L.buf[pos] notin s: break 
+    if L.buf[pos] notin s: break
   inc(L.col, pos - L.bufpos)
   L.bufpos = pos
 
-proc getAdornment(L: var TLexer, tok: var TToken) = 
+proc getAdornment(L: var TLexer, tok: var TToken) =
   tok.kind = tkAdornment
   tok.line = L.line
   tok.col = L.col
   var pos = L.bufpos
   var c = L.buf[pos]
-  while true: 
+  while true:
     add(tok.symbol, L.buf[pos])
     inc(pos)
-    if L.buf[pos] != c: break 
+    if L.buf[pos] != c: break
   inc(L.col, pos - L.bufpos)
   L.bufpos = pos
 
-proc getIndentAux(L: var TLexer, start: int): int = 
+proc getIndentAux(L: var TLexer, start: int): int =
   var pos = start
-  var buf = L.buf                 
+  var buf = L.buf
   # skip the newline (but include it in the token!)
-  if buf[pos] == '\x0D': 
+  if buf[pos] == '\x0D':
     if buf[pos + 1] == '\x0A': inc(pos, 2)
     else: inc(pos)
-  elif buf[pos] == '\x0A': 
+  elif buf[pos] == '\x0A':
     inc(pos)
-  if L.skipPounds: 
+  if L.skipPounds:
     if buf[pos] == '#': inc(pos)
     if buf[pos] == '#': inc(pos)
-  while true: 
+  while true:
     case buf[pos]
-    of ' ', '\x0B', '\x0C': 
+    of ' ', '\x0B', '\x0C':
       inc(pos)
       inc(result)
-    of '\x09': 
+    of '\x09':
       inc(pos)
       result = result - (result mod 8) + 8
-    else: 
+    else:
       break                   # EndOfFile also leaves the loop
-  if buf[pos] == '\0': 
+  if buf[pos] == '\0':
     result = 0
-  elif (buf[pos] == '\x0A') or (buf[pos] == '\x0D'): 
+  elif (buf[pos] == '\x0A') or (buf[pos] == '\x0D'):
     # look at the next line for proper indentation:
     result = getIndentAux(L, pos)
   L.bufpos = pos              # no need to set back buf
-  
-proc getIndent(L: var TLexer, tok: var TToken) = 
+
+proc getIndent(L: var TLexer, tok: var TToken) =
   tok.col = 0
   tok.kind = tkIndent         # skip the newline (but include it in the token!)
   tok.ival = getIndentAux(L, L.bufpos)
@@ -189,87 +189,87 @@ proc getIndent(L: var TLexer, tok: var TToken) =
   tok.line = L.line
   L.col = tok.ival
   tok.ival = max(tok.ival - L.baseIndent, 0)
-  tok.symbol = "\n" & repeatChar(tok.ival)
+  tok.symbol = "\n" & spaces(tok.ival)
 
-proc rawGetTok(L: var TLexer, tok: var TToken) = 
+proc rawGetTok(L: var TLexer, tok: var TToken) =
   tok.symbol = ""
   tok.ival = 0
   var c = L.buf[L.bufpos]
   case c
-  of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '0'..'9': 
+  of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '0'..'9':
     getThing(L, tok, SymChars)
-  of ' ', '\x09', '\x0B', '\x0C': 
+  of ' ', '\x09', '\x0B', '\x0C':
     getThing(L, tok, {' ', '\x09'})
     tok.kind = tkWhite
-    if L.buf[L.bufpos] in {'\x0D', '\x0A'}: 
+    if L.buf[L.bufpos] in {'\x0D', '\x0A'}:
       rawGetTok(L, tok)       # ignore spaces before \n
-  of '\x0D', '\x0A': 
+  of '\x0D', '\x0A':
     getIndent(L, tok)
-  of '!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', 
+  of '!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
      '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{',
-     '|', '}', '~': 
+     '|', '}', '~':
     getAdornment(L, tok)
     if len(tok.symbol) <= 3: tok.kind = tkPunct
-  else: 
+  else:
     tok.line = L.line
     tok.col = L.col
-    if c == '\0': 
+    if c == '\0':
       tok.kind = tkEof
-    else: 
+    else:
       tok.kind = tkOther
       add(tok.symbol, c)
       inc(L.bufpos)
       inc(L.col)
   tok.col = max(tok.col - L.baseIndent, 0)
 
-proc getTokens(buffer: string, skipPounds: bool, tokens: var TTokenSeq): int = 
+proc getTokens(buffer: string, skipPounds: bool, tokens: var TTokenSeq): int =
   var L: TLexer
   var length = len(tokens)
   L.buf = cstring(buffer)
   L.line = 0                  # skip UTF-8 BOM
-  if (L.buf[0] == '\xEF') and (L.buf[1] == '\xBB') and (L.buf[2] == '\xBF'): 
+  if (L.buf[0] == '\xEF') and (L.buf[1] == '\xBB') and (L.buf[2] == '\xBF'):
     inc(L.bufpos, 3)
   L.skipPounds = skipPounds
-  if skipPounds: 
-    if L.buf[L.bufpos] == '#': 
+  if skipPounds:
+    if L.buf[L.bufpos] == '#':
       inc(L.bufpos)
       inc(result)
-    if L.buf[L.bufpos] == '#': 
+    if L.buf[L.bufpos] == '#':
       inc(L.bufpos)
       inc(result)
     L.baseIndent = 0
-    while L.buf[L.bufpos] == ' ': 
+    while L.buf[L.bufpos] == ' ':
       inc(L.bufpos)
       inc(L.baseIndent)
       inc(result)
-  while true: 
+  while true:
     inc(length)
     setLen(tokens, length)
     rawGetTok(L, tokens[length - 1])
-    if tokens[length - 1].kind == tkEof: break 
-  if tokens[0].kind == tkWhite: 
+    if tokens[length - 1].kind == tkEof: break
+  if tokens[0].kind == tkWhite:
     # BUGFIX
     tokens[0].ival = len(tokens[0].symbol)
     tokens[0].kind = tkIndent
 
 type
   TLevelMap = array[char, int]
-  TSubstitution = object 
+  TSubstitution = object
     key*: string
     value*: PRstNode
 
-  TSharedState = object 
+  TSharedState = object
     options: TRstParseOptions   # parsing options
     uLevel, oLevel: int         # counters for the section levels
     subs: seq[TSubstitution]    # substitutions
     refs: seq[TSubstitution]    # references
     underlineToLevel: TLevelMap # Saves for each possible title adornment
                                 # character its level in the
-                                # current document. 
+                                # current document.
                                 # This is for single underline adornments.
-    overlineToLevel: TLevelMap  # Saves for each possible title adornment 
+    overlineToLevel: TLevelMap  # Saves for each possible title adornment
                                 # character its level in the current
-                                # document. 
+                                # document.
                                 # This is for over-underline adornments.
     msgHandler: TMsgHandler     # How to handle errors.
     findFile: TFindFileHandler  # How to find files.
@@ -293,7 +293,7 @@ proc whichMsgClass*(k: TMsgKind): TMsgClass =
   of 'w', 'W': result = mcWarning
   of 'h', 'H': result = mcHint
   else: assert false, "msgkind does not fit naming scheme"
-  
+
 proc defaultMsgHandler*(filename: string, line, col: int, msgkind: TMsgKind,
                         arg: string) {.procvar.} =
   let mc = msgkind.whichMsgClass
@@ -302,31 +302,31 @@ proc defaultMsgHandler*(filename: string, line, col: int, msgkind: TMsgKind,
   if mc == mcError: raise newException(EParseError, message)
   else: writeln(stdout, message)
 
-proc defaultFindFile*(filename: string): string {.procvar.} = 
+proc defaultFindFile*(filename: string): string {.procvar.} =
   if existsFile(filename): result = filename
   else: result = ""
 
 proc newSharedState(options: TRstParseOptions,
                     findFile: TFindFileHandler,
-                    msgHandler: TMsgHandler): PSharedState = 
+                    msgHandler: TMsgHandler): PSharedState =
   new(result)
   result.subs = @[]
   result.refs = @[]
   result.options = options
   result.msgHandler = if not isNil(msgHandler): msgHandler else: defaultMsgHandler
   result.findFile = if not isNil(findFile): findFile else: defaultFindFile
-  
-proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string) = 
-  p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line, 
+
+proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string) =
+  p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line,
                              p.col + p.tok[p.idx].col, msgKind, arg)
 
-proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string, line, col: int) = 
+proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string, line, col: int) =
   p.s.msgHandler(p.filename, p.line + line,
                              p.col + col, msgKind, arg)
 
-proc rstMessage(p: TRstParser, msgKind: TMsgKind) = 
-  p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line, 
-                             p.col + p.tok[p.idx].col, msgKind, 
+proc rstMessage(p: TRstParser, msgKind: TMsgKind) =
+  p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line,
+                             p.col + p.tok[p.idx].col, msgKind,
                              p.tok[p.idx].symbol)
 
 when false:
@@ -334,16 +334,16 @@ when false:
     assert p.indentStack[0] == 0
     for i in 1 .. high(p.indentStack): assert p.indentStack[i] < 1_000
 
-proc currInd(p: TRstParser): int = 
+proc currInd(p: TRstParser): int =
   result = p.indentStack[high(p.indentStack)]
 
-proc pushInd(p: var TRstParser, ind: int) = 
+proc pushInd(p: var TRstParser, ind: int) =
   add(p.indentStack, ind)
 
 proc popInd(p: var TRstParser) =
   if len(p.indentStack) > 1: setLen(p.indentStack, len(p.indentStack) - 1)
-  
-proc initParser(p: var TRstParser, sharedState: PSharedState) = 
+
+proc initParser(p: var TRstParser, sharedState: PSharedState) =
   p.indentStack = @[0]
   p.tok = @[]
   p.idx = 0
@@ -353,150 +353,150 @@ proc initParser(p: var TRstParser, sharedState: PSharedState) =
   p.line = 1
   p.s = sharedState
 
-proc addNodesAux(n: PRstNode, result: var string) = 
-  if n.kind == rnLeaf: 
+proc addNodesAux(n: PRstNode, result: var string) =
+  if n.kind == rnLeaf:
     add(result, n.text)
-  else: 
+  else:
     for i in countup(0, len(n) - 1): addNodesAux(n.sons[i], result)
-  
-proc addNodes(n: PRstNode): string = 
+
+proc addNodes(n: PRstNode): string =
   result = ""
   addNodesAux(n, result)
 
-proc rstnodeToRefnameAux(n: PRstNode, r: var string, b: var bool) = 
-  if n.kind == rnLeaf: 
-    for i in countup(0, len(n.text) - 1): 
+proc rstnodeToRefnameAux(n: PRstNode, r: var string, b: var bool) =
+  if n.kind == rnLeaf:
+    for i in countup(0, len(n.text) - 1):
       case n.text[i]
-      of '0'..'9': 
-        if b: 
+      of '0'..'9':
+        if b:
           add(r, '-')
           b = false
         if len(r) == 0: add(r, 'Z')
         add(r, n.text[i])
-      of 'a'..'z': 
-        if b: 
+      of 'a'..'z':
+        if b:
           add(r, '-')
           b = false
         add(r, n.text[i])
-      of 'A'..'Z': 
-        if b: 
+      of 'A'..'Z':
+        if b:
           add(r, '-')
           b = false
         add(r, chr(ord(n.text[i]) - ord('A') + ord('a')))
-      else: 
+      else:
         if (len(r) > 0): b = true
-  else: 
+  else:
     for i in countup(0, len(n) - 1): rstnodeToRefnameAux(n.sons[i], r, b)
-  
-proc rstnodeToRefname(n: PRstNode): string = 
+
+proc rstnodeToRefname(n: PRstNode): string =
   result = ""
   var b = false
   rstnodeToRefnameAux(n, result, b)
 
-proc findSub(p: var TRstParser, n: PRstNode): int = 
-  var key = addNodes(n)           
+proc findSub(p: var TRstParser, n: PRstNode): int =
+  var key = addNodes(n)
   # the spec says: if no exact match, try one without case distinction:
-  for i in countup(0, high(p.s.subs)): 
-    if key == p.s.subs[i].key: 
+  for i in countup(0, high(p.s.subs)):
+    if key == p.s.subs[i].key:
       return i
-  for i in countup(0, high(p.s.subs)): 
-    if cmpIgnoreStyle(key, p.s.subs[i].key) == 0: 
+  for i in countup(0, high(p.s.subs)):
+    if cmpIgnoreStyle(key, p.s.subs[i].key) == 0:
       return i
   result = -1
 
-proc setSub(p: var TRstParser, key: string, value: PRstNode) = 
+proc setSub(p: var TRstParser, key: string, value: PRstNode) =
   var length = len(p.s.subs)
-  for i in countup(0, length - 1): 
-    if key == p.s.subs[i].key: 
+  for i in countup(0, length - 1):
+    if key == p.s.subs[i].key:
       p.s.subs[i].value = value
-      return 
+      return
   setLen(p.s.subs, length + 1)
   p.s.subs[length].key = key
   p.s.subs[length].value = value
 
-proc setRef(p: var TRstParser, key: string, value: PRstNode) = 
+proc setRef(p: var TRstParser, key: string, value: PRstNode) =
   var length = len(p.s.refs)
-  for i in countup(0, length - 1): 
+  for i in countup(0, length - 1):
     if key == p.s.refs[i].key:
       if p.s.refs[i].value.addNodes != value.addNodes:
         rstMessage(p, mwRedefinitionOfLabel, key)
 
       p.s.refs[i].value = value
-      return 
+      return
   setLen(p.s.refs, length + 1)
   p.s.refs[length].key = key
   p.s.refs[length].value = value
 
-proc findRef(p: var TRstParser, key: string): PRstNode = 
-  for i in countup(0, high(p.s.refs)): 
-    if key == p.s.refs[i].key: 
+proc findRef(p: var TRstParser, key: string): PRstNode =
+  for i in countup(0, high(p.s.refs)):
+    if key == p.s.refs[i].key:
       return p.s.refs[i].value
 
-proc newLeaf(p: var TRstParser): PRstNode = 
+proc newLeaf(p: var TRstParser): PRstNode =
   result = newRstNode(rnLeaf, p.tok[p.idx].symbol)
 
-proc getReferenceName(p: var TRstParser, endStr: string): PRstNode = 
+proc getReferenceName(p: var TRstParser, endStr: string): PRstNode =
   var res = newRstNode(rnInner)
-  while true: 
+  while true:
     case p.tok[p.idx].kind
-    of tkWord, tkOther, tkWhite: 
+    of tkWord, tkOther, tkWhite:
       add(res, newLeaf(p))
-    of tkPunct: 
-      if p.tok[p.idx].symbol == endStr: 
+    of tkPunct:
+      if p.tok[p.idx].symbol == endStr:
         inc(p.idx)
-        break 
-      else: 
+        break
+      else:
         add(res, newLeaf(p))
-    else: 
+    else:
       rstMessage(p, meExpected, endStr)
-      break 
+      break
     inc(p.idx)
   result = res
 
-proc untilEol(p: var TRstParser): PRstNode = 
+proc untilEol(p: var TRstParser): PRstNode =
   result = newRstNode(rnInner)
-  while not (p.tok[p.idx].kind in {tkIndent, tkEof}): 
+  while not (p.tok[p.idx].kind in {tkIndent, tkEof}):
     add(result, newLeaf(p))
     inc(p.idx)
 
-proc expect(p: var TRstParser, tok: string) = 
+proc expect(p: var TRstParser, tok: string) =
   if p.tok[p.idx].symbol == tok: inc(p.idx)
   else: rstMessage(p, meExpected, tok)
-  
-proc isInlineMarkupEnd(p: TRstParser, markup: string): bool = 
+
+proc isInlineMarkupEnd(p: TRstParser, markup: string): bool =
   result = p.tok[p.idx].symbol == markup
-  if not result: 
+  if not result:
     return                    # Rule 3:
   result = not (p.tok[p.idx - 1].kind in {tkIndent, tkWhite})
-  if not result: 
+  if not result:
     return                    # Rule 4:
   result = (p.tok[p.idx + 1].kind in {tkIndent, tkWhite, tkEof}) or
       (p.tok[p.idx + 1].symbol[0] in
-      {'\'', '\"', ')', ']', '}', '>', '-', '/', '\\', ':', '.', ',', ';', '!', 
+      {'\'', '\"', ')', ']', '}', '>', '-', '/', '\\', ':', '.', ',', ';', '!',
        '?', '_'})
-  if not result: 
+  if not result:
     return                    # Rule 7:
-  if p.idx > 0: 
-    if (markup != "``") and (p.tok[p.idx - 1].symbol == "\\"): 
+  if p.idx > 0:
+    if (markup != "``") and (p.tok[p.idx - 1].symbol == "\\"):
       result = false
 
-proc isInlineMarkupStart(p: TRstParser, markup: string): bool = 
+proc isInlineMarkupStart(p: TRstParser, markup: string): bool =
   var d: char
   result = p.tok[p.idx].symbol == markup
-  if not result: 
+  if not result:
     return                    # Rule 1:
   result = (p.idx == 0) or (p.tok[p.idx - 1].kind in {tkIndent, tkWhite}) or
       (p.tok[p.idx - 1].symbol[0] in
       {'\'', '\"', '(', '[', '{', '<', '-', '/', ':', '_'})
-  if not result: 
+  if not result:
     return                    # Rule 2:
   result = not (p.tok[p.idx + 1].kind in {tkIndent, tkWhite, tkEof})
-  if not result: 
+  if not result:
     return                    # Rule 5 & 7:
-  if p.idx > 0: 
-    if p.tok[p.idx - 1].symbol == "\\": 
+  if p.idx > 0:
+    if p.tok[p.idx - 1].symbol == "\\":
       result = false
-    else: 
+    else:
       var c = p.tok[p.idx - 1].symbol[0]
       case c
       of '\'', '\"': d = c
@@ -507,7 +507,7 @@ proc isInlineMarkupStart(p: TRstParser, markup: string): bool =
       else: d = '\0'
       if d != '\0': result = p.tok[p.idx + 1].symbol[0] != d
 
-proc match(p: TRstParser, start: int, expr: string): bool = 
+proc match(p: TRstParser, start: int, expr: string): bool =
   # regular expressions are:
   # special char     exact match
   # 'w'              tkWord
@@ -521,7 +521,7 @@ proc match(p: TRstParser, start: int, expr: string): bool =
   var i = 0
   var j = start
   var last = len(expr) - 1
-  while i <= last: 
+  while i <= last:
     case expr[i]
     of 'w': result = p.tok[j].kind == tkWord
     of ' ': result = p.tok[j].kind == tkWhite
@@ -531,75 +531,75 @@ proc match(p: TRstParser, start: int, expr: string): bool =
     of 'o': result = p.tok[j].kind == tkOther
     of 'T': result = true
     of 'E': result = p.tok[j].kind in {tkEof, tkWhite, tkIndent}
-    of 'e': 
+    of 'e':
       result = (p.tok[j].kind == tkWord) or (p.tok[j].symbol == "#")
-      if result: 
+      if result:
         case p.tok[j].symbol[0]
         of 'a'..'z', 'A'..'Z': result = len(p.tok[j].symbol) == 1
         of '0'..'9': result = allCharsInSet(p.tok[j].symbol, {'0'..'9'})
         else: discard
-    else: 
+    else:
       var c = expr[i]
       var length = 0
-      while (i <= last) and (expr[i] == c): 
+      while (i <= last) and (expr[i] == c):
         inc(i)
         inc(length)
       dec(i)
       result = (p.tok[j].kind in {tkPunct, tkAdornment}) and
           (len(p.tok[j].symbol) == length) and (p.tok[j].symbol[0] == c)
-    if not result: return 
+    if not result: return
     inc(j)
     inc(i)
   result = true
-  
-proc fixupEmbeddedRef(n, a, b: PRstNode) = 
+
+proc fixupEmbeddedRef(n, a, b: PRstNode) =
   var sep = - 1
-  for i in countdown(len(n) - 2, 0): 
-    if n.sons[i].text == "<": 
+  for i in countdown(len(n) - 2, 0):
+    if n.sons[i].text == "<":
       sep = i
-      break 
+      break
   var incr = if (sep > 0) and (n.sons[sep - 1].text[0] == ' '): 2 else: 1
   for i in countup(0, sep - incr): add(a, n.sons[i])
   for i in countup(sep + 1, len(n) - 2): add(b, n.sons[i])
-  
-proc parsePostfix(p: var TRstParser, n: PRstNode): PRstNode = 
+
+proc parsePostfix(p: var TRstParser, n: PRstNode): PRstNode =
   result = n
-  if isInlineMarkupEnd(p, "_"): 
+  if isInlineMarkupEnd(p, "_") or isInlineMarkupEnd(p, "__"):
     inc(p.idx)
     if p.tok[p.idx-2].symbol == "`" and p.tok[p.idx-3].symbol == ">":
       var a = newRstNode(rnInner)
       var b = newRstNode(rnInner)
       fixupEmbeddedRef(n, a, b)
-      if len(a) == 0: 
+      if len(a) == 0:
         result = newRstNode(rnStandaloneHyperlink)
         add(result, b)
-      else: 
+      else:
         result = newRstNode(rnHyperlink)
         add(result, a)
         add(result, b)
         setRef(p, rstnodeToRefname(a), b)
-    elif n.kind == rnInterpretedText: 
+    elif n.kind == rnInterpretedText:
       n.kind = rnRef
-    else: 
+    else:
       result = newRstNode(rnRef)
       add(result, n)
-  elif match(p, p.idx, ":w:"): 
+  elif match(p, p.idx, ":w:"):
     # a role:
-    if p.tok[p.idx + 1].symbol == "idx": 
+    if p.tok[p.idx + 1].symbol == "idx":
       n.kind = rnIdx
-    elif p.tok[p.idx + 1].symbol == "literal": 
+    elif p.tok[p.idx + 1].symbol == "literal":
       n.kind = rnInlineLiteral
-    elif p.tok[p.idx + 1].symbol == "strong": 
+    elif p.tok[p.idx + 1].symbol == "strong":
       n.kind = rnStrongEmphasis
-    elif p.tok[p.idx + 1].symbol == "emphasis": 
+    elif p.tok[p.idx + 1].symbol == "emphasis":
       n.kind = rnEmphasis
     elif (p.tok[p.idx + 1].symbol == "sub") or
-        (p.tok[p.idx + 1].symbol == "subscript"): 
+        (p.tok[p.idx + 1].symbol == "subscript"):
       n.kind = rnSub
     elif (p.tok[p.idx + 1].symbol == "sup") or
-        (p.tok[p.idx + 1].symbol == "supscript"): 
+        (p.tok[p.idx + 1].symbol == "supscript"):
       n.kind = rnSup
-    else: 
+    else:
       result = newRstNode(rnGeneralRole)
       n.kind = rnInner
       add(result, n)
@@ -614,7 +614,7 @@ proc matchVerbatim(p: TRstParser, start: int, expr: string): int =
     inc j, p.tok[result].symbol.len
     inc result
   if j < expr.len: result = 0
-  
+
 proc parseSmiley(p: var TRstParser): PRstNode =
   if p.tok[p.idx].symbol[0] notin SmileyStartChars: return
   for key, val in items(Smilies):
@@ -636,17 +636,17 @@ proc isUrl(p: TRstParser, i: int): bool =
     (p.tok[i+3].kind == tkWord) and
     (p.tok[i].symbol in ["http", "https", "ftp", "telnet", "file"])
 
-proc parseUrl(p: var TRstParser, father: PRstNode) = 
+proc parseUrl(p: var TRstParser, father: PRstNode) =
   #if p.tok[p.idx].symbol[strStart] == '<':
   if isUrl(p, p.idx):
     var n = newRstNode(rnStandaloneHyperlink)
-    while true: 
+    while true:
       case p.tok[p.idx].kind
       of tkWord, tkAdornment, tkOther: discard
-      of tkPunct: 
+      of tkPunct:
         if p.tok[p.idx+1].kind notin {tkWord, tkAdornment, tkOther, tkPunct}:
           break
-      else: break 
+      else: break
       add(n, newLeaf(p))
       inc(p.idx)
     add(father, n)
@@ -655,13 +655,13 @@ proc parseUrl(p: var TRstParser, father: PRstNode) =
     inc(p.idx)
     if p.tok[p.idx].symbol == "_": n = parsePostfix(p, n)
     add(father, n)
-  
-proc parseBackslash(p: var TRstParser, father: PRstNode) = 
+
+proc parseBackslash(p: var TRstParser, father: PRstNode) =
   assert(p.tok[p.idx].kind == tkPunct)
-  if p.tok[p.idx].symbol == "\\\\": 
+  if p.tok[p.idx].symbol == "\\\\":
     add(father, newRstNode(rnLeaf, "\\"))
     inc(p.idx)
-  elif p.tok[p.idx].symbol == "\\": 
+  elif p.tok[p.idx].symbol == "\\":
     # XXX: Unicode?
     inc(p.idx)
     if p.tok[p.idx].kind != tkWhite: add(father, newLeaf(p))
@@ -674,13 +674,13 @@ when false:
   proc parseAdhoc(p: var TRstParser, father: PRstNode, verbatim: bool) =
     if not verbatim and isURL(p, p.idx):
       var n = newRstNode(rnStandaloneHyperlink)
-      while true: 
+      while true:
         case p.tok[p.idx].kind
         of tkWord, tkAdornment, tkOther: nil
-        of tkPunct: 
+        of tkPunct:
           if p.tok[p.idx+1].kind notin {tkWord, tkAdornment, tkOther, tkPunct}:
             break
-        else: break 
+        else: break
         add(n, newLeaf(p))
         inc(p.idx)
       add(father, n)
@@ -694,33 +694,33 @@ when false:
       if p.tok[p.idx].symbol == "_": n = parsePostfix(p, n)
       add(father, n)
 
-proc parseUntil(p: var TRstParser, father: PRstNode, postfix: string, 
-                interpretBackslash: bool) = 
+proc parseUntil(p: var TRstParser, father: PRstNode, postfix: string,
+                interpretBackslash: bool) =
   let
     line = p.tok[p.idx].line
     col = p.tok[p.idx].col
   inc p.idx
-  while true: 
+  while true:
     case p.tok[p.idx].kind
-    of tkPunct: 
-      if isInlineMarkupEnd(p, postfix): 
+    of tkPunct:
+      if isInlineMarkupEnd(p, postfix):
         inc(p.idx)
-        break 
-      elif interpretBackslash: 
+        break
+      elif interpretBackslash:
         parseBackslash(p, father)
-      else: 
+      else:
         add(father, newLeaf(p))
         inc(p.idx)
-    of tkAdornment, tkWord, tkOther: 
+    of tkAdornment, tkWord, tkOther:
       add(father, newLeaf(p))
       inc(p.idx)
-    of tkIndent: 
+    of tkIndent:
       add(father, newRstNode(rnLeaf, " "))
       inc(p.idx)
-      if p.tok[p.idx].kind == tkIndent: 
+      if p.tok[p.idx].kind == tkIndent:
         rstMessage(p, meExpected, postfix, line, col)
-        break 
-    of tkWhite: 
+        break
+    of tkWhite:
       add(father, newRstNode(rnLeaf, " "))
       inc(p.idx)
     else: rstMessage(p, meExpected, postfix, line, col)
@@ -753,20 +753,20 @@ proc parseMarkdownCodeblock(p: var TRstParser): PRstNode =
   result = newRstNode(rnCodeBlock)
   add(result, args)
   add(result, nil)
-  add(result, lb)  
-  
-proc parseInline(p: var TRstParser, father: PRstNode) = 
+  add(result, lb)
+
+proc parseInline(p: var TRstParser, father: PRstNode) =
   case p.tok[p.idx].kind
-  of tkPunct: 
+  of tkPunct:
     if isInlineMarkupStart(p, "***"):
       var n = newRstNode(rnTripleEmphasis)
       parseUntil(p, n, "***", true)
       add(father, n)
-    elif isInlineMarkupStart(p, "**"): 
+    elif isInlineMarkupStart(p, "**"):
       var n = newRstNode(rnStrongEmphasis)
       parseUntil(p, n, "**", true)
       add(father, n)
-    elif isInlineMarkupStart(p, "*"): 
+    elif isInlineMarkupStart(p, "*"):
       var n = newRstNode(rnEmphasis)
       parseUntil(p, n, "*", true)
       add(father, n)
@@ -777,12 +777,12 @@ proc parseInline(p: var TRstParser, father: PRstNode) =
       var n = newRstNode(rnInlineLiteral)
       parseUntil(p, n, "``", false)
       add(father, n)
-    elif isInlineMarkupStart(p, "`"): 
+    elif isInlineMarkupStart(p, "`"):
       var n = newRstNode(rnInterpretedText)
       parseUntil(p, n, "`", true)
       n = parsePostfix(p, n)
       add(father, n)
-    elif isInlineMarkupStart(p, "|"): 
+    elif isInlineMarkupStart(p, "|"):
       var n = newRstNode(rnSubstitutionReferences)
       parseUntil(p, n, "|", false)
       add(father, n)
@@ -800,7 +800,7 @@ proc parseInline(p: var TRstParser, father: PRstNode) =
         add(father, n)
         return
     parseUrl(p, father)
-  of tkAdornment, tkOther, tkWhite: 
+  of tkAdornment, tkOther, tkWhite:
     if roSupportSmilies in p.s.options:
       let n = parseSmiley(p)
       if n != nil:
@@ -809,75 +809,75 @@ proc parseInline(p: var TRstParser, father: PRstNode) =
     add(father, newLeaf(p))
     inc(p.idx)
   else: discard
-  
-proc getDirective(p: var TRstParser): string = 
-  if p.tok[p.idx].kind == tkWhite and p.tok[p.idx+1].kind == tkWord: 
+
+proc getDirective(p: var TRstParser): string =
+  if p.tok[p.idx].kind == tkWhite and p.tok[p.idx+1].kind == tkWord:
     var j = p.idx
     inc(p.idx)
     result = p.tok[p.idx].symbol
     inc(p.idx)
-    while p.tok[p.idx].kind in {tkWord, tkPunct, tkAdornment, tkOther}: 
-      if p.tok[p.idx].symbol == "::": break 
+    while p.tok[p.idx].kind in {tkWord, tkPunct, tkAdornment, tkOther}:
+      if p.tok[p.idx].symbol == "::": break
       add(result, p.tok[p.idx].symbol)
       inc(p.idx)
     if p.tok[p.idx].kind == tkWhite: inc(p.idx)
-    if p.tok[p.idx].symbol == "::": 
+    if p.tok[p.idx].symbol == "::":
       inc(p.idx)
       if (p.tok[p.idx].kind == tkWhite): inc(p.idx)
-    else: 
+    else:
       p.idx = j               # set back
       result = ""             # error
-  else: 
+  else:
     result = ""
-  
-proc parseComment(p: var TRstParser): PRstNode = 
+
+proc parseComment(p: var TRstParser): PRstNode =
   case p.tok[p.idx].kind
-  of tkIndent, tkEof: 
-    if p.tok[p.idx].kind != tkEof and p.tok[p.idx + 1].kind == tkIndent: 
+  of tkIndent, tkEof:
+    if p.tok[p.idx].kind != tkEof and p.tok[p.idx + 1].kind == tkIndent:
       inc(p.idx)              # empty comment
-    else: 
+    else:
       var indent = p.tok[p.idx].ival
-      while true: 
+      while true:
         case p.tok[p.idx].kind
-        of tkEof: 
-          break 
-        of tkIndent: 
-          if (p.tok[p.idx].ival < indent): break 
-        else: 
+        of tkEof:
+          break
+        of tkIndent:
+          if (p.tok[p.idx].ival < indent): break
+        else:
           discard
         inc(p.idx)
   else:
     while p.tok[p.idx].kind notin {tkIndent, tkEof}: inc(p.idx)
   result = nil
 
-type 
+type
   TDirKind = enum             # must be ordered alphabetically!
     dkNone, dkAuthor, dkAuthors, dkCode, dkCodeBlock, dkContainer, dkContents,
     dkFigure, dkImage, dkInclude, dkIndex, dkRaw, dkTitle
 
-const 
+const
   DirIds: array[0..12, string] = ["", "author", "authors", "code",
     "code-block", "container", "contents", "figure", "image", "include",
     "index", "raw", "title"]
 
-proc getDirKind(s: string): TDirKind = 
+proc getDirKind(s: string): TDirKind =
   let i = find(DirIds, s)
   if i >= 0: result = TDirKind(i)
   else: result = dkNone
-  
-proc parseLine(p: var TRstParser, father: PRstNode) = 
-  while true: 
+
+proc parseLine(p: var TRstParser, father: PRstNode) =
+  while true:
     case p.tok[p.idx].kind
     of tkWhite, tkWord, tkOther, tkPunct: parseInline(p, father)
-    else: break 
+    else: break
 
-proc parseUntilNewline(p: var TRstParser, father: PRstNode) = 
-  while true: 
+proc parseUntilNewline(p: var TRstParser, father: PRstNode) =
+  while true:
     case p.tok[p.idx].kind
     of tkWhite, tkWord, tkAdornment, tkOther, tkPunct: parseInline(p, father)
     of tkEof, tkIndent: break
-  
-proc parseSection(p: var TRstParser, result: PRstNode)
+
+proc parseSection(p: var TRstParser, result: PRstNode) {.gcsafe.}
 proc parseField(p: var TRstParser): PRstNode =
   ## Returns a parsed rnField node.
   ##
@@ -888,9 +888,9 @@ proc parseField(p: var TRstParser): PRstNode =
   parseUntil(p, fieldname, ":", false)
   var fieldbody = newRstNode(rnFieldBody)
   if p.tok[p.idx].kind != tkIndent: parseLine(p, fieldbody)
-  if p.tok[p.idx].kind == tkIndent: 
+  if p.tok[p.idx].kind == tkIndent:
     var indent = p.tok[p.idx].ival
-    if indent > col: 
+    if indent > col:
       pushInd(p, indent)
       parseSection(p, fieldbody)
       popInd(p)
@@ -909,14 +909,14 @@ proc parseFields(p: var TRstParser): PRstNode =
     var col = if atStart: p.tok[p.idx].col else: p.tok[p.idx].ival
     result = newRstNode(rnFieldList)
     if not atStart: inc(p.idx)
-    while true: 
+    while true:
       add(result, parseField(p))
       if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and
-          (p.tok[p.idx + 1].symbol == ":"): 
+          (p.tok[p.idx + 1].symbol == ":"):
         inc(p.idx)
-      else: 
-        break 
-  
+      else:
+        break
+
 proc getFieldValue*(n: PRstNode): string =
   ## Returns the value of a specific ``rnField`` node.
   ##
@@ -929,122 +929,122 @@ proc getFieldValue*(n: PRstNode): string =
   assert n.sons[1].kind == rnFieldBody
   result = addNodes(n.sons[1]).strip
 
-proc getFieldValue(n: PRstNode, fieldname: string): string = 
+proc getFieldValue(n: PRstNode, fieldname: string): string =
   result = ""
-  if n.sons[1] == nil: return 
-  if (n.sons[1].kind != rnFieldList): 
+  if n.sons[1] == nil: return
+  if (n.sons[1].kind != rnFieldList):
     #InternalError("getFieldValue (2): " & $n.sons[1].kind)
     # We don't like internal errors here anymore as that would break the forum!
     return
-  for i in countup(0, len(n.sons[1]) - 1): 
+  for i in countup(0, len(n.sons[1]) - 1):
     var f = n.sons[1].sons[i]
-    if cmpIgnoreStyle(addNodes(f.sons[0]), fieldname) == 0: 
+    if cmpIgnoreStyle(addNodes(f.sons[0]), fieldname) == 0:
       result = addNodes(f.sons[1])
       if result == "": result = "\x01\x01" # indicates that the field exists
-      return 
+      return
 
-proc getArgument(n: PRstNode): string = 
+proc getArgument(n: PRstNode): string =
   if n.sons[0] == nil: result = ""
   else: result = addNodes(n.sons[0])
-  
-proc parseDotDot(p: var TRstParser): PRstNode
-proc parseLiteralBlock(p: var TRstParser): PRstNode = 
+
+proc parseDotDot(p: var TRstParser): PRstNode {.gcsafe.}
+proc parseLiteralBlock(p: var TRstParser): PRstNode =
   result = newRstNode(rnLiteralBlock)
   var n = newRstNode(rnLeaf, "")
-  if p.tok[p.idx].kind == tkIndent: 
+  if p.tok[p.idx].kind == tkIndent:
     var indent = p.tok[p.idx].ival
     inc(p.idx)
-    while true: 
+    while true:
       case p.tok[p.idx].kind
-      of tkEof: 
-        break 
-      of tkIndent: 
-        if (p.tok[p.idx].ival < indent): 
-          break 
-        else: 
+      of tkEof:
+        break
+      of tkIndent:
+        if (p.tok[p.idx].ival < indent):
+          break
+        else:
           add(n.text, "\n")
-          add(n.text, repeatChar(p.tok[p.idx].ival - indent))
+          add(n.text, spaces(p.tok[p.idx].ival - indent))
           inc(p.idx)
-      else: 
+      else:
         add(n.text, p.tok[p.idx].symbol)
         inc(p.idx)
-  else: 
-    while not (p.tok[p.idx].kind in {tkIndent, tkEof}): 
+  else:
+    while not (p.tok[p.idx].kind in {tkIndent, tkEof}):
       add(n.text, p.tok[p.idx].symbol)
       inc(p.idx)
   add(result, n)
 
-proc getLevel(map: var TLevelMap, lvl: var int, c: char): int = 
-  if map[c] == 0: 
+proc getLevel(map: var TLevelMap, lvl: var int, c: char): int =
+  if map[c] == 0:
     inc(lvl)
     map[c] = lvl
   result = map[c]
 
-proc tokenAfterNewline(p: TRstParser): int = 
+proc tokenAfterNewline(p: TRstParser): int =
   result = p.idx
-  while true: 
+  while true:
     case p.tok[result].kind
-    of tkEof: 
-      break 
-    of tkIndent: 
+    of tkEof:
+      break
+    of tkIndent:
       inc(result)
-      break 
+      break
     else: inc(result)
-  
-proc isLineBlock(p: TRstParser): bool = 
+
+proc isLineBlock(p: TRstParser): bool =
   var j = tokenAfterNewline(p)
   result = (p.tok[p.idx].col == p.tok[j].col) and (p.tok[j].symbol == "|") or
       (p.tok[j].col > p.tok[p.idx].col)
 
-proc predNL(p: TRstParser): bool = 
+proc predNL(p: TRstParser): bool =
   result = true
   if p.idx > 0:
     result = p.tok[p.idx-1].kind == tkIndent and
         p.tok[p.idx-1].ival == currInd(p)
-  
-proc isDefList(p: TRstParser): bool = 
+
+proc isDefList(p: TRstParser): bool =
   var j = tokenAfterNewline(p)
   result = (p.tok[p.idx].col < p.tok[j].col) and
       (p.tok[j].kind in {tkWord, tkOther, tkPunct}) and
       (p.tok[j - 2].symbol != "::")
 
-proc isOptionList(p: TRstParser): bool = 
+proc isOptionList(p: TRstParser): bool =
   result = match(p, p.idx, "-w") or match(p, p.idx, "--w") or
            match(p, p.idx, "/w") or match(p, p.idx, "//w")
 
-proc whichSection(p: TRstParser): TRstNodeKind = 
+proc whichSection(p: TRstParser): TRstNodeKind =
   case p.tok[p.idx].kind
-  of tkAdornment: 
+  of tkAdornment:
     if match(p, p.idx + 1, "ii"): result = rnTransition
     elif match(p, p.idx + 1, " a"): result = rnTable
     elif match(p, p.idx + 1, "i"): result = rnOverline
     else: result = rnLeaf
-  of tkPunct: 
-    if match(p, tokenAfterNewline(p), "ai"): 
+  of tkPunct:
+    if match(p, tokenAfterNewline(p), "ai"):
       result = rnHeadline
-    elif p.tok[p.idx].symbol == "::": 
+    elif p.tok[p.idx].symbol == "::":
       result = rnLiteralBlock
     elif predNL(p) and
         ((p.tok[p.idx].symbol == "+") or (p.tok[p.idx].symbol == "*") or
-        (p.tok[p.idx].symbol == "-")) and (p.tok[p.idx + 1].kind == tkWhite): 
+        (p.tok[p.idx].symbol == "-")) and (p.tok[p.idx + 1].kind == tkWhite):
       result = rnBulletList
-    elif (p.tok[p.idx].symbol == "|") and isLineBlock(p): 
+    elif (p.tok[p.idx].symbol == "|") and isLineBlock(p):
       result = rnLineBlock
-    elif (p.tok[p.idx].symbol == "..") and predNL(p): 
+    elif (p.tok[p.idx].symbol == "..") and predNL(p):
       result = rnDirective
     elif match(p, p.idx, ":w:") and predNL(p):
       # (p.tok[p.idx].symbol == ":")
       result = rnFieldList
-    elif match(p, p.idx, "(e) "): 
+    elif match(p, p.idx, "(e) "):
       result = rnEnumList
-    elif match(p, p.idx, "+a+"): 
+    elif match(p, p.idx, "+a+"):
       result = rnGridTable
       rstMessage(p, meGridTableNotImplemented)
-    elif isDefList(p): 
+    elif isDefList(p):
       result = rnDefList
-    elif isOptionList(p): 
+    elif isOptionList(p):
       result = rnOptionList
-    else: 
+    else:
       result = rnParagraph
   of tkWord, tkOther, tkWhite:
     if match(p, tokenAfterNewline(p), "ai"): result = rnHeadline
@@ -1052,58 +1052,58 @@ proc whichSection(p: TRstParser): TRstNodeKind =
     elif isDefList(p): result = rnDefList
     else: result = rnParagraph
   else: result = rnLeaf
-  
-proc parseLineBlock(p: var TRstParser): PRstNode = 
+
+proc parseLineBlock(p: var TRstParser): PRstNode =
   result = nil
-  if p.tok[p.idx + 1].kind == tkWhite: 
+  if p.tok[p.idx + 1].kind == tkWhite:
     var col = p.tok[p.idx].col
     result = newRstNode(rnLineBlock)
     pushInd(p, p.tok[p.idx + 2].col)
     inc(p.idx, 2)
-    while true: 
+    while true:
       var item = newRstNode(rnLineBlockItem)
       parseSection(p, item)
       add(result, item)
       if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and
           (p.tok[p.idx + 1].symbol == "|") and
-          (p.tok[p.idx + 2].kind == tkWhite): 
+          (p.tok[p.idx + 2].kind == tkWhite):
         inc(p.idx, 3)
-      else: 
-        break 
+      else:
+        break
     popInd(p)
 
-proc parseParagraph(p: var TRstParser, result: PRstNode) = 
-  while true: 
+proc parseParagraph(p: var TRstParser, result: PRstNode) =
+  while true:
     case p.tok[p.idx].kind
-    of tkIndent: 
-      if p.tok[p.idx + 1].kind == tkIndent: 
+    of tkIndent:
+      if p.tok[p.idx + 1].kind == tkIndent:
         inc(p.idx)
-        break 
-      elif (p.tok[p.idx].ival == currInd(p)): 
+        break
+      elif (p.tok[p.idx].ival == currInd(p)):
         inc(p.idx)
         case whichSection(p)
-        of rnParagraph, rnLeaf, rnHeadline, rnOverline, rnDirective: 
+        of rnParagraph, rnLeaf, rnHeadline, rnOverline, rnDirective:
           add(result, newRstNode(rnLeaf, " "))
-        of rnLineBlock: 
+        of rnLineBlock:
           addIfNotNil(result, parseLineBlock(p))
-        else: break 
-      else: 
-        break 
-    of tkPunct: 
+        else: break
+      else:
+        break
+    of tkPunct:
       if (p.tok[p.idx].symbol == "::") and
           (p.tok[p.idx + 1].kind == tkIndent) and
-          (currInd(p) < p.tok[p.idx + 1].ival): 
+          (currInd(p) < p.tok[p.idx + 1].ival):
         add(result, newRstNode(rnLeaf, ":"))
         inc(p.idx)            # skip '::'
         add(result, parseLiteralBlock(p))
-        break 
-      else: 
+        break
+      else:
         parseInline(p, result)
-    of tkWhite, tkWord, tkAdornment, tkOther: 
+    of tkWhite, tkWord, tkAdornment, tkOther:
       parseInline(p, result)
     else: break
 
-proc parseHeadline(p: var TRstParser): PRstNode = 
+proc parseHeadline(p: var TRstParser): PRstNode =
   result = newRstNode(rnHeadline)
   parseUntilNewline(p, result)
   assert(p.tok[p.idx].kind == tkIndent)
@@ -1112,31 +1112,31 @@ proc parseHeadline(p: var TRstParser): PRstNode =
   inc(p.idx, 2)
   result.level = getLevel(p.s.underlineToLevel, p.s.uLevel, c)
 
-type 
+type
   TIntSeq = seq[int]
 
-proc tokEnd(p: TRstParser): int = 
+proc tokEnd(p: TRstParser): int =
   result = p.tok[p.idx].col + len(p.tok[p.idx].symbol) - 1
 
-proc getColumns(p: var TRstParser, cols: var TIntSeq) = 
+proc getColumns(p: var TRstParser, cols: var TIntSeq) =
   var L = 0
-  while true: 
+  while true:
     inc(L)
     setLen(cols, L)
     cols[L - 1] = tokEnd(p)
     assert(p.tok[p.idx].kind == tkAdornment)
     inc(p.idx)
-    if p.tok[p.idx].kind != tkWhite: break 
+    if p.tok[p.idx].kind != tkWhite: break
     inc(p.idx)
-    if p.tok[p.idx].kind != tkAdornment: break 
-  if p.tok[p.idx].kind == tkIndent: inc(p.idx)                
+    if p.tok[p.idx].kind != tkAdornment: break
+  if p.tok[p.idx].kind == tkIndent: inc(p.idx)
   # last column has no limit:
   cols[L - 1] = 32000
 
-proc parseDoc(p: var TRstParser): PRstNode
+proc parseDoc(p: var TRstParser): PRstNode {.gcsafe.}
 
-proc parseSimpleTable(p: var TRstParser): PRstNode = 
-  var 
+proc parseSimpleTable(p: var TRstParser): PRstNode =
+  var
     cols: TIntSeq
     row: seq[string]
     i, last, line: int
@@ -1148,36 +1148,36 @@ proc parseSimpleTable(p: var TRstParser): PRstNode =
   row = @[]
   a = nil
   c = p.tok[p.idx].symbol[0]
-  while true: 
-    if p.tok[p.idx].kind == tkAdornment: 
+  while true:
+    if p.tok[p.idx].kind == tkAdornment:
       last = tokenAfterNewline(p)
-      if p.tok[last].kind in {tkEof, tkIndent}: 
+      if p.tok[last].kind in {tkEof, tkIndent}:
         # skip last adornment line:
         p.idx = last
-        break 
+        break
       getColumns(p, cols)
       setLen(row, len(cols))
-      if a != nil: 
+      if a != nil:
         for j in 0..len(a)-1: a.sons[j].kind = rnTableHeaderCell
-    if p.tok[p.idx].kind == tkEof: break 
+    if p.tok[p.idx].kind == tkEof: break
     for j in countup(0, high(row)): row[j] = ""
     # the following while loop iterates over the lines a single cell may span:
     line = p.tok[p.idx].line
-    while true: 
+    while true:
       i = 0
-      while not (p.tok[p.idx].kind in {tkIndent, tkEof}): 
-        if (tokEnd(p) <= cols[i]): 
+      while not (p.tok[p.idx].kind in {tkIndent, tkEof}):
+        if (tokEnd(p) <= cols[i]):
           add(row[i], p.tok[p.idx].symbol)
           inc(p.idx)
-        else: 
+        else:
           if p.tok[p.idx].kind == tkWhite: inc(p.idx)
           inc(i)
       if p.tok[p.idx].kind == tkIndent: inc(p.idx)
-      if tokEnd(p) <= cols[0]: break 
-      if p.tok[p.idx].kind in {tkEof, tkAdornment}: break 
+      if tokEnd(p) <= cols[0]: break
+      if p.tok[p.idx].kind in {tkEof, tkAdornment}: break
       for j in countup(1, high(row)): add(row[j], '\x0A')
     a = newRstNode(rnTableRow)
-    for j in countup(0, high(row)): 
+    for j in countup(0, high(row)):
       initParser(q, p.s)
       q.col = cols[j]
       q.line = line - 1
@@ -1188,95 +1188,95 @@ proc parseSimpleTable(p: var TRstParser): PRstNode =
       add(a, b)
     add(result, a)
 
-proc parseTransition(p: var TRstParser): PRstNode = 
+proc parseTransition(p: var TRstParser): PRstNode =
   result = newRstNode(rnTransition)
   inc(p.idx)
   if p.tok[p.idx].kind == tkIndent: inc(p.idx)
   if p.tok[p.idx].kind == tkIndent: inc(p.idx)
-  
-proc parseOverline(p: var TRstParser): PRstNode = 
+
+proc parseOverline(p: var TRstParser): PRstNode =
   var c = p.tok[p.idx].symbol[0]
   inc(p.idx, 2)
   result = newRstNode(rnOverline)
-  while true: 
+  while true:
     parseUntilNewline(p, result)
-    if p.tok[p.idx].kind == tkIndent: 
+    if p.tok[p.idx].kind == tkIndent:
       inc(p.idx)
-      if p.tok[p.idx - 1].ival > currInd(p): 
+      if p.tok[p.idx - 1].ival > currInd(p):
         add(result, newRstNode(rnLeaf, " "))
-      else: 
-        break 
-    else: 
-      break 
+      else:
+        break
+    else:
+      break
   result.level = getLevel(p.s.overlineToLevel, p.s.oLevel, c)
-  if p.tok[p.idx].kind == tkAdornment: 
+  if p.tok[p.idx].kind == tkAdornment:
     inc(p.idx)                # XXX: check?
     if p.tok[p.idx].kind == tkIndent: inc(p.idx)
-  
-proc parseBulletList(p: var TRstParser): PRstNode = 
+
+proc parseBulletList(p: var TRstParser): PRstNode =
   result = nil
-  if p.tok[p.idx + 1].kind == tkWhite: 
+  if p.tok[p.idx + 1].kind == tkWhite:
     var bullet = p.tok[p.idx].symbol
     var col = p.tok[p.idx].col
     result = newRstNode(rnBulletList)
     pushInd(p, p.tok[p.idx + 2].col)
     inc(p.idx, 2)
-    while true: 
+    while true:
       var item = newRstNode(rnBulletItem)
       parseSection(p, item)
       add(result, item)
       if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and
           (p.tok[p.idx + 1].symbol == bullet) and
-          (p.tok[p.idx + 2].kind == tkWhite): 
+          (p.tok[p.idx + 2].kind == tkWhite):
         inc(p.idx, 3)
-      else: 
-        break 
+      else:
+        break
     popInd(p)
 
-proc parseOptionList(p: var TRstParser): PRstNode = 
+proc parseOptionList(p: var TRstParser): PRstNode =
   result = newRstNode(rnOptionList)
-  while true: 
+  while true:
     if isOptionList(p):
       var a = newRstNode(rnOptionGroup)
       var b = newRstNode(rnDescription)
       var c = newRstNode(rnOptionListItem)
       if match(p, p.idx, "//w"): inc(p.idx)
-      while not (p.tok[p.idx].kind in {tkIndent, tkEof}): 
-        if (p.tok[p.idx].kind == tkWhite) and (len(p.tok[p.idx].symbol) > 1): 
+      while not (p.tok[p.idx].kind in {tkIndent, tkEof}):
+        if (p.tok[p.idx].kind == tkWhite) and (len(p.tok[p.idx].symbol) > 1):
           inc(p.idx)
-          break 
+          break
         add(a, newLeaf(p))
         inc(p.idx)
       var j = tokenAfterNewline(p)
       if (j > 0) and (p.tok[j - 1].kind == tkIndent) and
-          (p.tok[j - 1].ival > currInd(p)): 
+          (p.tok[j - 1].ival > currInd(p)):
         pushInd(p, p.tok[j - 1].ival)
         parseSection(p, b)
         popInd(p)
-      else: 
+      else:
         parseLine(p, b)
       if (p.tok[p.idx].kind == tkIndent): inc(p.idx)
       add(c, a)
       add(c, b)
       add(result, c)
-    else: 
-      break 
-  
-proc parseDefinitionList(p: var TRstParser): PRstNode = 
+    else:
+      break
+
+proc parseDefinitionList(p: var TRstParser): PRstNode =
   result = nil
   var j = tokenAfterNewline(p) - 1
   if (j >= 1) and (p.tok[j].kind == tkIndent) and
-      (p.tok[j].ival > currInd(p)) and (p.tok[j - 1].symbol != "::"): 
+      (p.tok[j].ival > currInd(p)) and (p.tok[j - 1].symbol != "::"):
     var col = p.tok[p.idx].col
     result = newRstNode(rnDefList)
-    while true: 
+    while true:
       j = p.idx
       var a = newRstNode(rnDefName)
       parseLine(p, a)
       if (p.tok[p.idx].kind == tkIndent) and
           (p.tok[p.idx].ival > currInd(p)) and
           (p.tok[p.idx + 1].symbol != "::") and
-          not (p.tok[p.idx + 1].kind in {tkIndent, tkEof}): 
+          not (p.tok[p.idx + 1].kind in {tkIndent, tkEof}):
         pushInd(p, p.tok[p.idx].ival)
         var b = newRstNode(rnDefBody)
         parseSection(p, b)
@@ -1285,74 +1285,74 @@ proc parseDefinitionList(p: var TRstParser): PRstNode =
         add(c, b)
         add(result, c)
         popInd(p)
-      else: 
+      else:
         p.idx = j
-        break 
-      if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col): 
+        break
+      if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col):
         inc(p.idx)
         j = tokenAfterNewline(p) - 1
         if j >= 1 and p.tok[j].kind == tkIndent and p.tok[j].ival > col and
-            p.tok[j-1].symbol != "::" and p.tok[j+1].kind != tkIndent: 
+            p.tok[j-1].symbol != "::" and p.tok[j+1].kind != tkIndent:
           discard
-        else: 
-          break 
+        else:
+          break
     if len(result) == 0: result = nil
-  
-proc parseEnumList(p: var TRstParser): PRstNode = 
-  const 
+
+proc parseEnumList(p: var TRstParser): PRstNode =
+  const
     wildcards: array[0..2, string] = ["(e) ", "e) ", "e. "]
     wildpos: array[0..2, int] = [1, 0, 0]
   result = nil
   var w = 0
-  while w <= 2: 
-    if match(p, p.idx, wildcards[w]): break 
+  while w <= 2:
+    if match(p, p.idx, wildcards[w]): break
     inc(w)
-  if w <= 2: 
+  if w <= 2:
     var col = p.tok[p.idx].col
     result = newRstNode(rnEnumList)
     inc(p.idx, wildpos[w] + 3)
     var j = tokenAfterNewline(p)
-    if (p.tok[j].col == p.tok[p.idx].col) or match(p, j, wildcards[w]): 
+    if (p.tok[j].col == p.tok[p.idx].col) or match(p, j, wildcards[w]):
       pushInd(p, p.tok[p.idx].col)
-      while true: 
+      while true:
         var item = newRstNode(rnEnumItem)
         parseSection(p, item)
         add(result, item)
         if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and
-            match(p, p.idx + 1, wildcards[w]): 
+            match(p, p.idx + 1, wildcards[w]):
           inc(p.idx, wildpos[w] + 4)
-        else: 
-          break 
+        else:
+          break
       popInd(p)
-    else: 
+    else:
       dec(p.idx, wildpos[w] + 3)
       result = nil
 
-proc sonKind(father: PRstNode, i: int): TRstNodeKind = 
+proc sonKind(father: PRstNode, i: int): TRstNodeKind =
   result = rnLeaf
   if i < len(father): result = father.sons[i].kind
-  
-proc parseSection(p: var TRstParser, result: PRstNode) = 
-  while true: 
+
+proc parseSection(p: var TRstParser, result: PRstNode) =
+  while true:
     var leave = false
     assert(p.idx >= 0)
-    while p.tok[p.idx].kind == tkIndent: 
-      if currInd(p) == p.tok[p.idx].ival: 
+    while p.tok[p.idx].kind == tkIndent:
+      if currInd(p) == p.tok[p.idx].ival:
         inc(p.idx)
-      elif p.tok[p.idx].ival > currInd(p): 
+      elif p.tok[p.idx].ival > currInd(p):
         pushInd(p, p.tok[p.idx].ival)
         var a = newRstNode(rnBlockQuote)
         parseSection(p, a)
         add(result, a)
         popInd(p)
-      else: 
+      else:
         leave = true
         break
     if leave or p.tok[p.idx].kind == tkEof: break
     var a: PRstNode = nil
     var k = whichSection(p)
     case k
-    of rnLiteralBlock: 
+    of rnLiteralBlock:
       inc(p.idx)              # skip '::'
       a = parseLiteralBlock(p)
     of rnBulletList: a = parseBulletList(p)
@@ -1362,7 +1362,7 @@ proc parseSection(p: var TRstParser, result: PRstNode) =
     of rnLeaf: rstMessage(p, meNewSectionExpected)
     of rnParagraph: discard
     of rnDefList: a = parseDefinitionList(p)
-    of rnFieldList: 
+    of rnFieldList:
       if p.idx > 0: dec(p.idx)
       a = parseFields(p)
     of rnTransition: a = parseTransition(p)
@@ -1373,35 +1373,35 @@ proc parseSection(p: var TRstParser, result: PRstNode) =
     else:
       #InternalError("rst.parseSection()")
       discard
-    if a == nil and k != rnDirective: 
+    if a == nil and k != rnDirective:
       a = newRstNode(rnParagraph)
       parseParagraph(p, a)
     addIfNotNil(result, a)
-  if sonKind(result, 0) == rnParagraph and sonKind(result, 1) != rnParagraph: 
+  if sonKind(result, 0) == rnParagraph and sonKind(result, 1) != rnParagraph:
     result.sons[0].kind = rnInner
-  
-proc parseSectionWrapper(p: var TRstParser): PRstNode = 
+
+proc parseSectionWrapper(p: var TRstParser): PRstNode =
   result = newRstNode(rnInner)
   parseSection(p, result)
-  while (result.kind == rnInner) and (len(result) == 1): 
+  while (result.kind == rnInner) and (len(result) == 1):
     result = result.sons[0]
-  
+
 proc `$`(t: TToken): string =
   result = $t.kind & ' ' & (if isNil(t.symbol): "NIL" else: t.symbol)
 
-proc parseDoc(p: var TRstParser): PRstNode = 
+proc parseDoc(p: var TRstParser): PRstNode =
   result = parseSectionWrapper(p)
-  if p.tok[p.idx].kind != tkEof: 
+  if p.tok[p.idx].kind != tkEof:
     when false:
       assert isAllocatedPtr(cast[pointer](p.tok))
       for i in 0 .. high(p.tok):
-        assert isNil(p.tok[i].symbol) or 
+        assert isNil(p.tok[i].symbol) or
                isAllocatedPtr(cast[pointer](p.tok[i].symbol))
       echo "index: ", p.idx, " length: ", high(p.tok), "##",
           p.tok[p.idx-1], p.tok[p.idx], p.tok[p.idx+1]
     #assert isAllocatedPtr(cast[pointer](p.indentStack))
     rstMessage(p, meGeneralParseError)
-  
+
 type
   TDirFlag = enum
     hasArg, hasOptions, argIsFile, argIsWord
@@ -1421,55 +1421,55 @@ proc parseDirective(p: var TRstParser, flags: TDirFlags): PRstNode =
   result = newRstNode(rnDirective)
   var args: PRstNode = nil
   var options: PRstNode = nil
-  if hasArg in flags: 
+  if hasArg in flags:
     args = newRstNode(rnDirArg)
-    if argIsFile in flags: 
-      while true: 
+    if argIsFile in flags:
+      while true:
         case p.tok[p.idx].kind
-        of tkWord, tkOther, tkPunct, tkAdornment: 
+        of tkWord, tkOther, tkPunct, tkAdornment:
           add(args, newLeaf(p))
           inc(p.idx)
-        else: break 
+        else: break
     elif argIsWord in flags:
       while p.tok[p.idx].kind == tkWhite: inc(p.idx)
-      if p.tok[p.idx].kind == tkWord: 
+      if p.tok[p.idx].kind == tkWord:
         add(args, newLeaf(p))
         inc(p.idx)
       else:
         args = nil
-    else: 
+    else:
       parseLine(p, args)
   add(result, args)
-  if hasOptions in flags: 
+  if hasOptions in flags:
     if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival >= 3) and
-        (p.tok[p.idx + 1].symbol == ":"): 
+        (p.tok[p.idx + 1].symbol == ":"):
       options = parseFields(p)
   add(result, options)
-  
-proc indFollows(p: TRstParser): bool = 
+
+proc indFollows(p: TRstParser): bool =
   result = p.tok[p.idx].kind == tkIndent and p.tok[p.idx].ival > currInd(p)
-  
-proc parseDirective(p: var TRstParser, flags: TDirFlags, 
-                    contentParser: TSectionParser): PRstNode = 
+
+proc parseDirective(p: var TRstParser, flags: TDirFlags,
+                    contentParser: TSectionParser): PRstNode =
   ## Returns a generic rnDirective tree.
   ##
   ## The children are rnDirArg, rnFieldList and rnLineBlock. Any might be nil.
   result = parseDirective(p, flags)
-  if not isNil(contentParser) and indFollows(p): 
+  if not isNil(contentParser) and indFollows(p):
     pushInd(p, p.tok[p.idx].ival)
     var content = contentParser(p)
     popInd(p)
     add(result, content)
-  else: 
+  else:
     add(result, nil)
 
-proc parseDirBody(p: var TRstParser, contentParser: TSectionParser): PRstNode = 
-  if indFollows(p): 
+proc parseDirBody(p: var TRstParser, contentParser: TSectionParser): PRstNode =
+  if indFollows(p):
     pushInd(p, p.tok[p.idx].ival)
     result = contentParser(p)
     popInd(p)
-  
-proc dirInclude(p: var TRstParser): PRstNode = 
+
+proc dirInclude(p: var TRstParser): PRstNode =
   #
   #The following options are recognized:
   #
@@ -1490,18 +1490,18 @@ proc dirInclude(p: var TRstParser): PRstNode =
   var n = parseDirective(p, {hasArg, argIsFile, hasOptions}, nil)
   var filename = strip(addNodes(n.sons[0]))
   var path = p.s.findFile(filename)
-  if path == "": 
+  if path == "":
     rstMessage(p, meCannotOpenFile, filename)
-  else: 
+  else:
     # XXX: error handling; recursive file inclusion!
-    if getFieldValue(n, "literal") != "": 
+    if getFieldValue(n, "literal") != "":
       result = newRstNode(rnLiteralBlock)
       add(result, newRstNode(rnLeaf, readFile(path)))
     else:
       var q: TRstParser
       initParser(q, p.s)
       q.filename = filename
-      q.col += getTokens(readFile(path), false, q.tok) 
+      q.col += getTokens(readFile(path), false, q.tok)
       # workaround a GCC bug; more like the interior pointer bug?
       #if find(q.tok[high(q.tok)].symbol, "\0\x01\x02") > 0:
       #  InternalError("Too many binary zeros in include file")
@@ -1526,7 +1526,7 @@ proc dirCodeBlock(p: var TRstParser, nimrodExtension = false): PRstNode =
   ## file.
   result = parseDirective(p, {hasArg, hasOptions}, parseLiteralBlock)
   var filename = strip(getFieldValue(result, "file"))
-  if filename != "": 
+  if filename != "":
     var path = p.s.findFile(filename)
     if path == "": rstMessage(p, meCannotOpenFile, filename)
     var n = newRstNode(rnLiteralBlock)
@@ -1548,49 +1548,49 @@ proc dirCodeBlock(p: var TRstParser, nimrodExtension = false): PRstNode =
 
   result.kind = rnCodeBlock
 
-proc dirContainer(p: var TRstParser): PRstNode = 
+proc dirContainer(p: var TRstParser): PRstNode =
   result = parseDirective(p, {hasArg}, parseSectionWrapper)
   assert(result.kind == rnDirective)
   assert(len(result) == 3)
   result.kind = rnContainer
 
-proc dirImage(p: var TRstParser): PRstNode = 
+proc dirImage(p: var TRstParser): PRstNode =
   result = parseDirective(p, {hasOptions, hasArg, argIsFile}, nil)
   result.kind = rnImage
 
-proc dirFigure(p: var TRstParser): PRstNode = 
-  result = parseDirective(p, {hasOptions, hasArg, argIsFile}, 
+proc dirFigure(p: var TRstParser): PRstNode =
+  result = parseDirective(p, {hasOptions, hasArg, argIsFile},
                           parseSectionWrapper)
   result.kind = rnFigure
 
-proc dirTitle(p: var TRstParser): PRstNode = 
+proc dirTitle(p: var TRstParser): PRstNode =
   result = parseDirective(p, {hasArg}, nil)
   result.kind = rnTitle
 
-proc dirContents(p: var TRstParser): PRstNode = 
+proc dirContents(p: var TRstParser): PRstNode =
   result = parseDirective(p, {hasArg}, nil)
   result.kind = rnContents
 
-proc dirIndex(p: var TRstParser): PRstNode = 
+proc dirIndex(p: var TRstParser): PRstNode =
   result = parseDirective(p, {}, parseSectionWrapper)
   result.kind = rnIndex
 
 proc dirRawAux(p: var TRstParser, result: var PRstNode, kind: TRstNodeKind,
-               contentParser: TSectionParser) = 
+               contentParser: TSectionParser) =
   var filename = getFieldValue(result, "file")
-  if filename.len > 0: 
+  if filename.len > 0:
     var path = p.s.findFile(filename)
-    if path.len == 0: 
+    if path.len == 0:
       rstMessage(p, meCannotOpenFile, filename)
-    else: 
+    else:
       var f = readFile(path)
       result = newRstNode(kind)
       add(result, newRstNode(rnLeaf, f))
-  else:      
+  else:
     result.kind = kind
     add(result, parseDirBody(p, contentParser))
 
-proc dirRaw(p: var TRstParser): PRstNode = 
+proc dirRaw(p: var TRstParser): PRstNode =
   #
   #The following options are recognized:
   #
@@ -1603,19 +1603,19 @@ proc dirRaw(p: var TRstParser): PRstNode =
   if result.sons[0] != nil:
     if cmpIgnoreCase(result.sons[0].sons[0].text, "html") == 0:
       dirRawAux(p, result, rnRawHtml, parseLiteralBlock)
-    elif cmpIgnoreCase(result.sons[0].sons[0].text, "latex") == 0: 
+    elif cmpIgnoreCase(result.sons[0].sons[0].text, "latex") == 0:
       dirRawAux(p, result, rnRawLatex, parseLiteralBlock)
     else:
       rstMessage(p, meInvalidDirective, result.sons[0].sons[0].text)
   else:
     dirRawAux(p, result, rnRaw, parseSectionWrapper)
 
-proc parseDotDot(p: var TRstParser): PRstNode = 
+proc parseDotDot(p: var TRstParser): PRstNode =
   result = nil
   var col = p.tok[p.idx].col
   inc(p.idx)
   var d = getDirective(p)
-  if d != "": 
+  if d != "":
     pushInd(p, col)
     case getDirKind(d)
     of dkInclude: result = dirInclude(p)
@@ -1634,66 +1634,66 @@ proc parseDotDot(p: var TRstParser): PRstNode =
     of dkIndex: result = dirIndex(p)
     else: rstMessage(p, meInvalidDirective, d)
     popInd(p)
-  elif match(p, p.idx, " _"): 
+  elif match(p, p.idx, " _"):
     # hyperlink target:
     inc(p.idx, 2)
     var a = getReferenceName(p, ":")
     if p.tok[p.idx].kind == tkWhite: inc(p.idx)
     var b = untilEol(p)
     setRef(p, rstnodeToRefname(a), b)
-  elif match(p, p.idx, " |"): 
+  elif match(p, p.idx, " |"):
     # substitution definitions:
     inc(p.idx, 2)
     var a = getReferenceName(p, "|")
     var b: PRstNode
     if p.tok[p.idx].kind == tkWhite: inc(p.idx)
-    if cmpIgnoreStyle(p.tok[p.idx].symbol, "replace") == 0: 
+    if cmpIgnoreStyle(p.tok[p.idx].symbol, "replace") == 0:
       inc(p.idx)
       expect(p, "::")
       b = untilEol(p)
-    elif cmpIgnoreStyle(p.tok[p.idx].symbol, "image") == 0: 
+    elif cmpIgnoreStyle(p.tok[p.idx].symbol, "image") == 0:
       inc(p.idx)
       b = dirImage(p)
-    else: 
+    else:
       rstMessage(p, meInvalidDirective, p.tok[p.idx].symbol)
     setSub(p, addNodes(a), b)
-  elif match(p, p.idx, " ["): 
+  elif match(p, p.idx, " ["):
     # footnotes, citations
     inc(p.idx, 2)
     var a = getReferenceName(p, "]")
     if p.tok[p.idx].kind == tkWhite: inc(p.idx)
     var b = untilEol(p)
     setRef(p, rstnodeToRefname(a), b)
-  else: 
+  else:
     result = parseComment(p)
-  
-proc resolveSubs(p: var TRstParser, n: PRstNode): PRstNode = 
+
+proc resolveSubs(p: var TRstParser, n: PRstNode): PRstNode =
   result = n
-  if n == nil: return 
+  if n == nil: return
   case n.kind
-  of rnSubstitutionReferences: 
+  of rnSubstitutionReferences:
     var x = findSub(p, n)
-    if x >= 0: 
+    if x >= 0:
       result = p.s.subs[x].value
-    else: 
+    else:
       var key = addNodes(n)
       var e = getEnv(key)
       if e != "": result = newRstNode(rnLeaf, e)
       else: rstMessage(p, mwUnknownSubstitution, key)
-  of rnRef: 
+  of rnRef:
     var y = findRef(p, rstnodeToRefname(n))
-    if y != nil: 
+    if y != nil:
       result = newRstNode(rnHyperlink)
       n.kind = rnInner
       add(result, n)
       add(result, y)
-  of rnLeaf: 
+  of rnLeaf:
     discard
-  of rnContents: 
+  of rnContents:
     p.hasToc = true
-  else: 
+  else:
     for i in countup(0, len(n) - 1): n.sons[i] = resolveSubs(p, n.sons[i])
-  
+
 proc rstParse*(text, filename: string,
                line, column: int, hasToc: var bool,
                options: TRstParseOptions,
diff --git a/lib/packages/docutils/rstast.nim b/lib/packages/docutils/rstast.nim
index 52af672df..c3956ab8b 100644
--- a/lib/packages/docutils/rstast.nim
+++ b/lib/packages/docutils/rstast.nim
@@ -30,7 +30,7 @@ type
     rnField,                  # a field item
     rnFieldName,              # consisting of a field name ...
     rnFieldBody,              # ... and a field body
-    rnOptionList, rnOptionListItem, rnOptionGroup, rnOption, rnOptionString, 
+    rnOptionList, rnOptionListItem, rnOptionGroup, rnOption, rnOptionString,
     rnOptionArgument, rnDescription, rnLiteralBlock, rnQuotedLiteralBlock,
     rnLineBlock,              # the | thingie
     rnLineBlockItem,          # sons of the | thing
@@ -50,7 +50,7 @@ type
                               #     * `file#id <file#id>'_
     rnSubstitutionDef,        # a definition of a substitution
     rnGeneralRole,            # Inline markup:
-    rnSub, rnSup, rnIdx, 
+    rnSub, rnSup, rnIdx,
     rnEmphasis,               # "*"
     rnStrongEmphasis,         # "**"
     rnTripleEmphasis,         # "***"
@@ -71,25 +71,25 @@ type
     level*: int               ## valid for some node kinds
     sons*: TRstNodeSeq        ## the node's sons
 
-proc len*(n: PRstNode): int = 
+proc len*(n: PRstNode): int =
   result = len(n.sons)
 
-proc newRstNode*(kind: TRstNodeKind): PRstNode = 
+proc newRstNode*(kind: TRstNodeKind): PRstNode =
   new(result)
   result.sons = @[]
   result.kind = kind
 
-proc newRstNode*(kind: TRstNodeKind, s: string): PRstNode = 
+proc newRstNode*(kind: TRstNodeKind, s: string): PRstNode =
   result = newRstNode(kind)
   result.text = s
 
-proc lastSon*(n: PRstNode): PRstNode = 
+proc lastSon*(n: PRstNode): PRstNode =
   result = n.sons[len(n.sons)-1]
 
 proc add*(father, son: PRstNode) =
   add(father.sons, son)
 
-proc addIfNotNil*(father, son: PRstNode) = 
+proc addIfNotNil*(father, son: PRstNode) =
   if son != nil: add(father, son)
 
 
@@ -98,62 +98,63 @@ type
     indent: int
     verbatim: int
 
-proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string)
+proc renderRstToRst(d: var TRenderContext, n: PRstNode,
+                    result: var string) {.gcsafe.}
 
-proc renderRstSons(d: var TRenderContext, n: PRstNode, result: var string) = 
-  for i in countup(0, len(n) - 1): 
+proc renderRstSons(d: var TRenderContext, n: PRstNode, result: var string) =
+  for i in countup(0, len(n) - 1):
     renderRstToRst(d, n.sons[i], result)
-  
+
 proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
   # this is needed for the index generation; it may also be useful for
   # debugging, but most code is already debugged...
-  const 
+  const
     lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+']
   if n == nil: return
-  var ind = repeatChar(d.indent)
+  var ind = spaces(d.indent)
   case n.kind
-  of rnInner: 
+  of rnInner:
     renderRstSons(d, n, result)
   of rnHeadline:
     result.add("\n")
     result.add(ind)
-    
+
     let oldLen = result.len
     renderRstSons(d, n, result)
     let headlineLen = result.len - oldLen
 
     result.add("\n")
     result.add(ind)
-    result.add repeatChar(headlineLen, lvlToChar[n.level])
+    result.add repeat(lvlToChar[n.level], headlineLen)
   of rnOverline:
     result.add("\n")
     result.add(ind)
 
     var headline = ""
     renderRstSons(d, n, headline)
-    
-    let lvl = repeatChar(headline.len - d.indent, lvlToChar[n.level])
+
+    let lvl = repeat(lvlToChar[n.level], headline.len - d.indent)
     result.add(lvl)
     result.add("\n")
     result.add(headline)
-    
+
     result.add("\n")
     result.add(ind)
     result.add(lvl)
-  of rnTransition: 
+  of rnTransition:
     result.add("\n\n")
     result.add(ind)
-    result.add repeatChar(78-d.indent, '-')
+    result.add repeat('-', 78-d.indent)
     result.add("\n\n")
   of rnParagraph:
     result.add("\n\n")
     result.add(ind)
     renderRstSons(d, n, result)
-  of rnBulletItem: 
+  of rnBulletItem:
     inc(d.indent, 2)
     var tmp = ""
     renderRstSons(d, n, tmp)
-    if tmp.len > 0: 
+    if tmp.len > 0:
       result.add("\n")
       result.add(ind)
       result.add("* ")
@@ -163,22 +164,22 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
     inc(d.indent, 4)
     var tmp = ""
     renderRstSons(d, n, tmp)
-    if tmp.len > 0: 
+    if tmp.len > 0:
       result.add("\n")
       result.add(ind)
       result.add("(#) ")
       result.add(tmp)
     dec(d.indent, 4)
-  of rnOptionList, rnFieldList, rnDefList, rnDefItem, rnLineBlock, rnFieldName, 
-     rnFieldBody, rnStandaloneHyperlink, rnBulletList, rnEnumList: 
+  of rnOptionList, rnFieldList, rnDefList, rnDefItem, rnLineBlock, rnFieldName,
+     rnFieldBody, rnStandaloneHyperlink, rnBulletList, rnEnumList:
     renderRstSons(d, n, result)
-  of rnDefName: 
+  of rnDefName:
     result.add("\n\n")
     result.add(ind)
     renderRstSons(d, n, result)
   of rnDefBody:
     inc(d.indent, 2)
-    if n.sons[0].kind != rnBulletList: 
+    if n.sons[0].kind != rnBulletList:
       result.add("\n")
       result.add(ind)
       result.add("  ")
@@ -187,20 +188,20 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
   of rnField:
     var tmp = ""
     renderRstToRst(d, n.sons[0], tmp)
-    
+
     var L = max(tmp.len + 3, 30)
     inc(d.indent, L)
-    
+
     result.add "\n"
     result.add ind
     result.add ':'
     result.add tmp
     result.add ':'
-    result.add repeatChar(L - tmp.len - 2)
+    result.add spaces(L - tmp.len - 2)
     renderRstToRst(d, n.sons[1], result)
-    
+
     dec(d.indent, L)
-  of rnLineBlockItem: 
+  of rnLineBlockItem:
     result.add("\n")
     result.add(ind)
     result.add("| ")
@@ -209,11 +210,11 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
     inc(d.indent, 2)
     renderRstSons(d, n, result)
     dec(d.indent, 2)
-  of rnRef: 
+  of rnRef:
     result.add("`")
     renderRstSons(d, n, result)
     result.add("`_")
-  of rnHyperlink: 
+  of rnHyperlink:
     result.add('`')
     renderRstToRst(d, n.sons[0], result)
     result.add(" <")
@@ -225,23 +226,23 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
     result.add("`:")
     renderRstToRst(d, n.sons[1],result)
     result.add(':')
-  of rnSub: 
+  of rnSub:
     result.add('`')
     renderRstSons(d, n, result)
     result.add("`:sub:")
-  of rnSup: 
+  of rnSup:
     result.add('`')
     renderRstSons(d, n, result)
     result.add("`:sup:")
-  of rnIdx: 
+  of rnIdx:
     result.add('`')
     renderRstSons(d, n, result)
     result.add("`:idx:")
-  of rnEmphasis: 
+  of rnEmphasis:
     result.add("*")
     renderRstSons(d, n, result)
     result.add("*")
-  of rnStrongEmphasis: 
+  of rnStrongEmphasis:
     result.add("**")
     renderRstSons(d, n, result)
     result.add("**")
@@ -249,11 +250,11 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
     result.add("***")
     renderRstSons(d, n, result)
     result.add("***")
-  of rnInterpretedText: 
+  of rnInterpretedText:
     result.add('`')
     renderRstSons(d, n, result)
     result.add('`')
-  of rnInlineLiteral: 
+  of rnInlineLiteral:
     inc(d.verbatim)
     result.add("``")
     renderRstSons(d, n, result)
@@ -266,11 +267,11 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
       result.add("\\\\") # XXX: escape more special characters!
     else:
       result.add(n.text)
-  of rnIndex: 
+  of rnIndex:
     result.add("\n\n")
     result.add(ind)
     result.add(".. index::\n")
-    
+
     inc(d.indent, 3)
     if n.sons[2] != nil: renderRstSons(d, n.sons[2], result)
     dec(d.indent, 3)
@@ -280,7 +281,7 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
     result.add(".. contents::")
   else:
     result.add("Error: cannot render: " & $n.kind)
-  
+
 proc renderRstToRst*(n: PRstNode, result: var string) =
   ## renders `n` into its string representation and appends to `result`.
   var d: TRenderContext
@@ -302,7 +303,7 @@ proc renderRstToJsonNode(node: PRstNode): JsonNode =
 
 proc renderRstToJson*(node: PRstNode): string =
   ## Writes the given RST node as JSON that is in the form
-  ## :: 
+  ## ::
   ##   {
   ##     "kind":string node.kind,
   ##     "text":optional string node.text,
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index 09373ac9e..9e96d8a63 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -34,14 +34,14 @@ type
   TOutputTarget* = enum ## which document type to generate
     outHtml,            # output is HTML
     outLatex            # output is Latex
-  
-  TTocEntry = object 
+
+  TTocEntry = object
     n*: PRstNode
     refname*, header*: string
 
-  TMetaEnum* = enum 
+  TMetaEnum* = enum
     metaNone, metaTitle, metaSubtitle, metaAuthor, metaVersion
-    
+
   TRstGenerator* = object of RootObj
     target*: TOutputTarget
     config*: StringTableRef
@@ -60,7 +60,7 @@ type
     seenIndexTerms: Table[string, int] ## \
     ## Keeps count of same text index terms to generate different identifiers
     ## for hyperlinks. See renderIndexTerm proc for details.
-  
+
   PDoc = var TRstGenerator ## Alias to type less.
 
   CodeBlockParams = object ## Stores code block params.
@@ -136,7 +136,7 @@ proc initRstGenerator*(g: var TRstGenerator, target: TOutputTarget,
     g.currentSection = "Module " & fileParts.name
   g.seenIndexTerms = initTable[string, int]()
   g.msgHandler = msgHandler
-  
+
   let s = config["split.item.toc"]
   if s != "": g.splitAfter = parseInt(s)
   for i in low(g.meta)..high(g.meta): g.meta[i] = ""
@@ -147,23 +147,23 @@ proc writeIndexFile*(g: var TRstGenerator, outfile: string) =
   ## You previously need to add entries to the index with the `setIndexTerm()
   ## <#setIndexTerm>`_ proc. If the index is empty the file won't be created.
   if g.theIndex.len > 0: writeFile(outfile, g.theIndex)
-  
-proc addXmlChar(dest: var string, c: char) = 
+
+proc addXmlChar(dest: var string, c: char) =
   case c
   of '&': add(dest, "&amp;")
   of '<': add(dest, "&lt;")
   of '>': add(dest, "&gt;")
   of '\"': add(dest, "&quot;")
   else: add(dest, c)
-  
-proc addRtfChar(dest: var string, c: char) = 
+
+proc addRtfChar(dest: var string, c: char) =
   case c
   of '{': add(dest, "\\{")
   of '}': add(dest, "\\}")
   of '\\': add(dest, "\\\\")
   else: add(dest, c)
-  
-proc addTexChar(dest: var string, c: char) = 
+
+proc addTexChar(dest: var string, c: char) =
   case c
   of '_': add(dest, "\\_")
   of '{': add(dest, "\\symbol{123}")
@@ -183,54 +183,54 @@ proc addTexChar(dest: var string, c: char) =
 
 var splitter*: string = "<wbr />"
 
-proc escChar*(target: TOutputTarget, dest: var string, c: char) {.inline.} = 
+proc escChar*(target: TOutputTarget, dest: var string, c: char) {.inline.} =
   case target
   of outHtml:  addXmlChar(dest, c)
   of outLatex: addTexChar(dest, c)
-  
-proc nextSplitPoint*(s: string, start: int): int = 
+
+proc nextSplitPoint*(s: string, start: int): int =
   result = start
-  while result < len(s) + 0: 
+  while result < len(s) + 0:
     case s[result]
-    of '_': return 
-    of 'a'..'z': 
-      if result + 1 < len(s) + 0: 
-        if s[result + 1] in {'A'..'Z'}: return 
+    of '_': return
+    of 'a'..'z':
+      if result + 1 < len(s) + 0:
+        if s[result + 1] in {'A'..'Z'}: return
     else: discard
     inc(result)
   dec(result)                 # last valid index
-  
-proc esc*(target: TOutputTarget, s: string, splitAfter = -1): string = 
+
+proc esc*(target: TOutputTarget, s: string, splitAfter = -1): string =
   result = ""
-  if splitAfter >= 0: 
+  if splitAfter >= 0:
     var partLen = 0
     var j = 0
-    while j < len(s): 
+    while j < len(s):
       var k = nextSplitPoint(s, j)
-      if (splitter != " ") or (partLen + k - j + 1 > splitAfter): 
+      if (splitter != " ") or (partLen + k - j + 1 > splitAfter):
         partLen = 0
         add(result, splitter)
       for i in countup(j, k): escChar(target, result, s[i])
       inc(partLen, k - j + 1)
       j = k + 1
-  else: 
+  else:
     for i in countup(0, len(s) - 1): escChar(target, result, s[i])
 
 
 proc disp(target: TOutputTarget, xml, tex: string): string =
-  if target != outLatex: result = xml 
+  if target != outLatex: result = xml
   else: result = tex
-  
-proc dispF(target: TOutputTarget, xml, tex: string, 
-           args: varargs[string]): string = 
-  if target != outLatex: result = xml % args 
+
+proc dispF(target: TOutputTarget, xml, tex: string,
+           args: varargs[string]): string =
+  if target != outLatex: result = xml % args
   else: result = tex % args
-  
-proc dispA(target: TOutputTarget, dest: var string, 
+
+proc dispA(target: TOutputTarget, dest: var string,
            xml, tex: string, args: varargs[string]) =
   if target != outLatex: addf(dest, xml, args)
   else: addf(dest, tex, args)
-  
+
 proc `or`(x, y: string): string {.inline.} =
   result = if x.isNil: y else: x
 
@@ -248,7 +248,7 @@ proc renderRstToOut*(d: var TRstGenerator, n: PRstNode, result: var string)
   ##   renderRstToOut(gen, rst, generatedHTML)
   ##   echo generatedHTML
 
-proc renderAux(d: PDoc, n: PRstNode, result: var string) = 
+proc renderAux(d: PDoc, n: PRstNode, result: var string) =
   for i in countup(0, len(n)-1): renderRstToOut(d, n.sons[i], result)
 
 proc renderAux(d: PDoc, n: PRstNode, frmtA, frmtB: string, result: var string) =
@@ -347,7 +347,7 @@ proc renderIndexTerm*(d: PDoc, n: PRstNode, result: var string) =
   var term = ""
   renderAux(d, n, term)
   setIndexTerm(d, id, term, d.currentSection)
-  dispA(d.target, result, "<span id=\"$1\">$2</span>", "$2\\label{$1}", 
+  dispA(d.target, result, "<span id=\"$1\">$2</span>", "$2\\label{$1}",
         [id, term])
 
 type
@@ -417,10 +417,12 @@ proc generateSymbolIndex(symbols: seq[TIndexEntry]): string =
   result = ""
   var i = 0
   while i < symbols.len:
-    result.addf("<dt><span>$1:</span></dt><ul class=\"simple\"><dd>\n",
-                [symbols[i].keyword])
+    let keyword= symbols[i].keyword
+    let cleaned_keyword = keyword[1..keyword.high - 1]
+    result.addf("<dt><a name=\"$2\" href=\"#$2\"><span>$1:</span></a></dt><ul class=\"simple\"><dd>\n",
+                [keyword, cleaned_keyword])
     var j = i
-    while j < symbols.len and symbols[i].keyword == symbols[j].keyword:
+    while j < symbols.len and keyword == symbols[j].keyword:
       let
         url = symbols[j].link
         text = if not symbols[j].linkTitle.isNil: symbols[j].linkTitle else: url
@@ -459,9 +461,9 @@ proc indentToLevel(level: var int, newLevel: int): string =
   if level == newLevel:
     return
   if newLevel > level:
-    result = repeatStr(newLevel - level, "<ul>")
+    result = repeat("<ul>", newLevel - level)
   else:
-    result = repeatStr(level - newLevel, "</ul>")
+    result = repeat("</ul>", level - newLevel)
   level = newLevel
 
 proc generateDocumentationTOC(entries: seq[TIndexEntry]): string =
@@ -654,7 +656,7 @@ proc mergeIndexes*(dir: string): string =
     result.add("<h2>API symbols</h2>\n")
     result.add(generateSymbolIndex(symbols))
 
-  
+
 # ----------------------------------------------------------------------------
 
 proc stripTOCHTML(s: string): string =
@@ -675,11 +677,18 @@ proc stripTOCHTML(s: string): string =
     result.delete(first, last)
     first = result.find('<', first)
 
-proc renderHeadline(d: PDoc, n: PRstNode, result: var string) = 
+proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
   var tmp = ""
   for i in countup(0, len(n) - 1): renderRstToOut(d, n.sons[i], tmp)
   d.currentSection = tmp
-  var refname = rstnodeToRefname(n)
+  # Find the last higher level section for unique reference name
+  var sectionPrefix = ""
+  for i in countdown(d.tocPart.high, 0):
+    let n2 = d.tocPart[i].n
+    if n2.level < n.level:
+      sectionPrefix = rstnodeToRefname(n2) & "-"
+      break
+  var refname = sectionPrefix & rstnodeToRefname(n)
   if d.hasToc:
     var length = len(d.tocPart)
     setLen(d.tocPart, length + 1)
@@ -691,17 +700,17 @@ proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
       "id=\"$2\" href=\"#$2\">$3</a></h$1>", "\\rsth$4{$3}\\label{$2}\n",
       [$n.level, d.tocPart[length].refname, tmp, $chr(n.level - 1 + ord('A'))])
   else:
-    dispA(d.target, result, "\n<h$1 id=\"$2\">$3</h$1>", 
+    dispA(d.target, result, "\n<h$1 id=\"$2\">$3</h$1>",
                             "\\rsth$4{$3}\\label{$2}\n", [
-        $n.level, refname, tmp, 
+        $n.level, refname, tmp,
         $chr(n.level - 1 + ord('A'))])
 
   # Generate index entry using spaces to indicate TOC level for the output HTML.
   assert n.level >= 0
   setIndexTerm(d, refname, tmp.stripTOCHTML,
-    repeatChar(max(0, n.level), ' ') & tmp)
+    spaces(max(0, n.level)) & tmp)
 
-proc renderOverline(d: PDoc, n: PRstNode, result: var string) = 
+proc renderOverline(d: PDoc, n: PRstNode, result: var string) =
   if d.meta[metaTitle].len == 0:
     for i in countup(0, len(n)-1):
       renderRstToOut(d, n.sons[i], d.meta[metaTitle])
@@ -714,14 +723,14 @@ proc renderOverline(d: PDoc, n: PRstNode, result: var string) =
     var tmp = ""
     for i in countup(0, len(n) - 1): renderRstToOut(d, n.sons[i], tmp)
     d.currentSection = tmp
-    dispA(d.target, result, "<h$1 id=\"$2\"><center>$3</center></h$1>", 
+    dispA(d.target, result, "<h$1 id=\"$2\"><center>$3</center></h$1>",
                    "\\rstov$4{$3}\\label{$2}\n", [$n.level,
         rstnodeToRefname(n), tmp, $chr(n.level - 1 + ord('A'))])
-  
 
-proc renderTocEntry(d: PDoc, e: TTocEntry, result: var string) = 
+
+proc renderTocEntry(d: PDoc, e: TTocEntry, result: var string) =
   dispA(d.target, result,
-    "<li><a class=\"reference\" id=\"$1_toc\" href=\"#$1\">$2</a></li>\n", 
+    "<li><a class=\"reference\" id=\"$1_toc\" href=\"#$1\">$2</a></li>\n",
     "\\item\\label{$1_toc} $2\\ref{$1}\n", [e.refname, e.header])
 
 proc renderTocEntries*(d: var TRstGenerator, j: var int, lvl: int,
@@ -750,33 +759,33 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
   var options = ""
   var s = getFieldValue(n, "scale")
   if s.valid: dispA(d.target, options, " scale=\"$1\"", " scale=$1", [strip(s)])
-  
+
   s = getFieldValue(n, "height")
   if s.valid: dispA(d.target, options, " height=\"$1\"", " height=$1", [strip(s)])
-  
+
   s = getFieldValue(n, "width")
   if s.valid: dispA(d.target, options, " width=\"$1\"", " width=$1", [strip(s)])
-  
+
   s = getFieldValue(n, "alt")
   if s.valid: dispA(d.target, options, " alt=\"$1\"", "", [strip(s)])
-  
+
   s = getFieldValue(n, "align")
   if s.valid: dispA(d.target, options, " align=\"$1\"", "", [strip(s)])
-  
+
   if options.len > 0: options = dispF(d.target, "$1", "[$1]", [options])
 
   let arg = getArgument(n)
   if arg.valid:
-    dispA(d.target, result, "<img src=\"$1\"$2 />", "\\includegraphics$2{$1}", 
+    dispA(d.target, result, "<img src=\"$1\"$2 />", "\\includegraphics$2{$1}",
           [arg, options])
   if len(n) >= 3: renderRstToOut(d, n.sons[2], result)
-  
+
 proc renderSmiley(d: PDoc, n: PRstNode, result: var string) =
   dispA(d.target, result,
-    """<img src="$1" width="15" 
+    """<img src="$1" width="15"
         height="17" hspace="2" vspace="2" class="smiley" />""",
     "\\includegraphics{$1}", [d.config["doc.smiley_format"] % n.text])
-  
+
 proc parseCodeBlockField(d: PDoc, n: PRstNode, params: var CodeBlockParams) =
   ## Parses useful fields which can appear before a code block.
   ##
@@ -871,11 +880,11 @@ proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) =
   else:
     var g: TGeneralTokenizer
     initGeneralTokenizer(g, m.text)
-    while true: 
+    while true:
       getNextToken(g, params.lang)
       case g.kind
-      of gtEof: break 
-      of gtNone, gtWhitespace: 
+      of gtEof: break
+      of gtNone, gtWhitespace:
         add(result, substr(m.text, g.start, g.length + g.start - 1))
       else:
         dispA(d.target, result, "<span class=\"$2\">$1</span>", "\\span$2{$1}", [
@@ -884,36 +893,36 @@ proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) =
     deinitGeneralTokenizer(g)
   dispA(d.target, result, blockEnd, "\n\\end{rstpre}\n")
 
-proc renderContainer(d: PDoc, n: PRstNode, result: var string) = 
+proc renderContainer(d: PDoc, n: PRstNode, result: var string) =
   var tmp = ""
   renderRstToOut(d, n.sons[2], tmp)
   var arg = strip(getArgument(n))
-  if arg == "": 
+  if arg == "":
     dispA(d.target, result, "<div>$1</div>", "$1", [tmp])
   else:
     dispA(d.target, result, "<div class=\"$1\">$2</div>", "$2", [arg, tmp])
-  
-proc texColumns(n: PRstNode): string = 
+
+proc texColumns(n: PRstNode): string =
   result = ""
   for i in countup(1, len(n)): add(result, "|X")
-  
-proc renderField(d: PDoc, n: PRstNode, result: var string) = 
+
+proc renderField(d: PDoc, n: PRstNode, result: var string) =
   var b = false
-  if d.target == outLatex: 
+  if d.target == outLatex:
     var fieldname = addNodes(n.sons[0])
     var fieldval = esc(d.target, strip(addNodes(n.sons[1])))
-    if cmpIgnoreStyle(fieldname, "author") == 0 or 
+    if cmpIgnoreStyle(fieldname, "author") == 0 or
        cmpIgnoreStyle(fieldname, "authors") == 0:
       if d.meta[metaAuthor].len == 0:
         d.meta[metaAuthor] = fieldval
         b = true
-    elif cmpIgnoreStyle(fieldname, "version") == 0: 
+    elif cmpIgnoreStyle(fieldname, "version") == 0:
       if d.meta[metaVersion].len == 0:
         d.meta[metaVersion] = fieldval
         b = true
   if not b:
     renderAux(d, n, "<tr>$1</tr>\n", "$1", result)
-  
+
 proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
   if n == nil: return
   case n.kind
@@ -938,54 +947,54 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
   of rnDefBody: renderAux(d, n, "<dd>$1</dd>\n", "$1\n", result)
   of rnFieldList:
     var tmp = ""
-    for i in countup(0, len(n) - 1): 
+    for i in countup(0, len(n) - 1):
       renderRstToOut(d, n.sons[i], tmp)
-    if tmp.len != 0: 
+    if tmp.len != 0:
       dispA(d.target, result,
           "<table class=\"docinfo\" frame=\"void\" rules=\"none\">" &
           "<col class=\"docinfo-name\" />" &
-          "<col class=\"docinfo-content\" />" & 
+          "<col class=\"docinfo-content\" />" &
           "<tbody valign=\"top\">$1" &
-          "</tbody></table>", 
-          "\\begin{description}$1\\end{description}\n", 
+          "</tbody></table>",
+          "\\begin{description}$1\\end{description}\n",
           [tmp])
   of rnField: renderField(d, n, result)
-  of rnFieldName: 
+  of rnFieldName:
     renderAux(d, n, "<th class=\"docinfo-name\">$1:</th>",
                     "\\item[$1:]", result)
-  of rnFieldBody: 
+  of rnFieldBody:
     renderAux(d, n, "<td>$1</td>", " $1\n", result)
-  of rnIndex: 
+  of rnIndex:
     renderRstToOut(d, n.sons[2], result)
-  of rnOptionList: 
-    renderAux(d, n, "<table frame=\"void\">$1</table>", 
+  of rnOptionList:
+    renderAux(d, n, "<table frame=\"void\">$1</table>",
       "\\begin{description}\n$1\\end{description}\n", result)
-  of rnOptionListItem: 
+  of rnOptionListItem:
     renderAux(d, n, "<tr>$1</tr>\n", "$1", result)
-  of rnOptionGroup: 
+  of rnOptionGroup:
     renderAux(d, n, "<th align=\"left\">$1</th>", "\\item[$1]", result)
-  of rnDescription: 
+  of rnDescription:
     renderAux(d, n, "<td align=\"left\">$1</td>\n", " $1\n", result)
-  of rnOption, rnOptionString, rnOptionArgument: 
+  of rnOption, rnOptionString, rnOptionArgument:
     doAssert false, "renderRstToOut"
   of rnLiteralBlock:
-    renderAux(d, n, "<pre>$1</pre>\n", 
+    renderAux(d, n, "<pre>$1</pre>\n",
                     "\\begin{rstpre}\n$1\n\\end{rstpre}\n", result)
-  of rnQuotedLiteralBlock: 
+  of rnQuotedLiteralBlock:
     doAssert false, "renderRstToOut"
-  of rnLineBlock: 
+  of rnLineBlock:
     renderAux(d, n, "<p>$1</p>", "$1\n\n", result)
-  of rnLineBlockItem: 
+  of rnLineBlockItem:
     renderAux(d, n, "$1<br />", "$1\\\\\n", result)
-  of rnBlockQuote: 
-    renderAux(d, n, "<blockquote><p>$1</p></blockquote>\n", 
+  of rnBlockQuote:
+    renderAux(d, n, "<blockquote><p>$1</p></blockquote>\n",
                     "\\begin{quote}$1\\end{quote}\n", result)
-  of rnTable, rnGridTable: 
-    renderAux(d, n, 
-      "<table border=\"1\" class=\"docutils\">$1</table>", 
+  of rnTable, rnGridTable:
+    renderAux(d, n,
+      "<table border=\"1\" class=\"docutils\">$1</table>",
       "\\begin{table}\\begin{rsttab}{" &
         texColumns(n) & "|}\n\\hline\n$1\\end{rsttab}\\end{table}", result)
-  of rnTableRow: 
+  of rnTableRow:
     if len(n) >= 1:
       if d.target == outLatex:
         #var tmp = ""
@@ -998,25 +1007,25 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
         result.add("<tr>")
         renderAux(d, n, result)
         result.add("</tr>\n")
-  of rnTableDataCell: 
+  of rnTableDataCell:
     renderAux(d, n, "<td>$1</td>", "$1", result)
-  of rnTableHeaderCell: 
+  of rnTableHeaderCell:
     renderAux(d, n, "<th>$1</th>", "\\textbf{$1}", result)
-  of rnLabel: 
+  of rnLabel:
     doAssert false, "renderRstToOut" # used for footnotes and other
-  of rnFootnote: 
+  of rnFootnote:
     doAssert false, "renderRstToOut" # a footnote
-  of rnCitation: 
+  of rnCitation:
     doAssert false, "renderRstToOut" # similar to footnote
-  of rnRef: 
+  of rnRef:
     var tmp = ""
     renderAux(d, n, tmp)
     dispA(d.target, result,
       "<a class=\"reference external\" href=\"#$2\">$1</a>",
       "$1\\ref{$2}", [tmp, rstnodeToRefname(n)])
-  of rnStandaloneHyperlink: 
-    renderAux(d, n, 
-      "<a class=\"reference external\" href=\"$1\">$1</a>", 
+  of rnStandaloneHyperlink:
+    renderAux(d, n,
+      "<a class=\"reference external\" href=\"$1\">$1</a>",
       "\\href{$1}{$1}", result)
   of rnHyperlink:
     var tmp0 = ""
@@ -1033,11 +1042,11 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
   of rnRawLatex:
     if d.target == outLatex:
       result.add addNodes(lastSon(n))
-      
+
   of rnImage, rnFigure: renderImage(d, n, result)
   of rnCodeBlock: renderCodeBlock(d, n, result)
   of rnContainer: renderContainer(d, n, result)
-  of rnSubstitutionReferences, rnSubstitutionDef: 
+  of rnSubstitutionReferences, rnSubstitutionDef:
     renderAux(d, n, "|$1|", "|$1|", result)
   of rnDirective:
     renderAux(d, n, "", "", result)
@@ -1054,15 +1063,15 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
   of rnStrongEmphasis:
     renderAux(d, n, "<strong>$1</strong>", "\\textbf{$1}", result)
   of rnTripleEmphasis:
-    renderAux(d, n, "<strong><em>$1</em></strong>", 
+    renderAux(d, n, "<strong><em>$1</em></strong>",
                     "\\textbf{emph{$1}}", result)
   of rnInterpretedText:
     renderAux(d, n, "<cite>$1</cite>", "\\emph{$1}", result)
   of rnIdx:
     renderIndexTerm(d, n, result)
-  of rnInlineLiteral: 
-    renderAux(d, n, 
-      "<tt class=\"docutils literal\"><span class=\"pre\">$1</span></tt>", 
+  of rnInlineLiteral:
+    renderAux(d, n,
+      "<tt class=\"docutils literal\"><span class=\"pre\">$1</span></tt>",
       "\\texttt{$1}", result)
   of rnSmiley: renderSmiley(d, n, result)
   of rnLeaf: result.add(esc(d.target, n.text))
@@ -1073,55 +1082,55 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
 
 # -----------------------------------------------------------------------------
 
-proc getVarIdx(varnames: openArray[string], id: string): int = 
-  for i in countup(0, high(varnames)): 
-    if cmpIgnoreStyle(varnames[i], id) == 0: 
+proc getVarIdx(varnames: openArray[string], id: string): int =
+  for i in countup(0, high(varnames)):
+    if cmpIgnoreStyle(varnames[i], id) == 0:
       return i
   result = -1
 
-proc formatNamedVars*(frmt: string, varnames: openArray[string], 
-                      varvalues: openArray[string]): string = 
+proc formatNamedVars*(frmt: string, varnames: openArray[string],
+                      varvalues: openArray[string]): string =
   var i = 0
   var L = len(frmt)
   result = ""
   var num = 0
-  while i < L: 
-    if frmt[i] == '$': 
+  while i < L:
+    if frmt[i] == '$':
       inc(i)                  # skip '$'
       case frmt[i]
-      of '#': 
+      of '#':
         add(result, varvalues[num])
         inc(num)
         inc(i)
-      of '$': 
+      of '$':
         add(result, "$")
         inc(i)
-      of '0'..'9': 
+      of '0'..'9':
         var j = 0
-        while true: 
+        while true:
           j = (j * 10) + ord(frmt[i]) - ord('0')
           inc(i)
-          if i > L-1 or frmt[i] notin {'0'..'9'}: break 
+          if i > L-1 or frmt[i] notin {'0'..'9'}: break
         if j > high(varvalues) + 1:
           raise newException(ValueError, "invalid index: " & $j)
         num = j
         add(result, varvalues[j - 1])
-      of 'A'..'Z', 'a'..'z', '\x80'..'\xFF': 
+      of 'A'..'Z', 'a'..'z', '\x80'..'\xFF':
         var id = ""
-        while true: 
+        while true:
           add(id, frmt[i])
           inc(i)
-          if frmt[i] notin {'A'..'Z', '_', 'a'..'z', '\x80'..'\xFF'}: break 
+          if frmt[i] notin {'A'..'Z', '_', 'a'..'z', '\x80'..'\xFF'}: break
         var idx = getVarIdx(varnames, id)
-        if idx >= 0: 
+        if idx >= 0:
           add(result, varvalues[idx])
         else:
           raise newException(ValueError, "unknown substitution var: " & id)
-      of '{': 
+      of '{':
         var id = ""
         inc(i)
-        while frmt[i] != '}': 
-          if frmt[i] == '\0': 
+        while frmt[i] != '}':
+          if frmt[i] == '\0':
             raise newException(ValueError, "'}' expected")
           add(id, frmt[i])
           inc(i)
@@ -1129,12 +1138,12 @@ proc formatNamedVars*(frmt: string, varnames: openArray[string],
                               # search for the variable:
         var idx = getVarIdx(varnames, id)
         if idx >= 0: add(result, varvalues[idx])
-        else: 
+        else:
           raise newException(ValueError, "unknown substitution var: " & id)
       else:
         raise newException(ValueError, "unknown substitution: $" & $frmt[i])
     var start = i
-    while i < L: 
+    while i < L:
       if frmt[i] != '$': inc(i)
       else: break
     if i-1 >= start: add(result, substr(frmt, start, i - 1))
@@ -1143,7 +1152,7 @@ proc formatNamedVars*(frmt: string, varnames: openArray[string],
 proc defaultConfig*(): StringTableRef =
   ## Returns a default configuration for embedded HTML generation.
   ##
-  ## The returned ``StringTableRef`` contains the paramters used by the HTML
+  ## The returned ``StringTableRef`` contains the parameters used by the HTML
   ## engine to build the final output. For information on what these parameters
   ## are and their purpose, please look up the file ``config/nimdoc.cfg``
   ## bundled with the compiler.
@@ -1154,10 +1163,10 @@ proc defaultConfig*(): StringTableRef =
   ## pages, while this proc returns just the content for procs like
   ## ``rstToHtml`` to generate the bare minimum HTML.
   result = newStringTable(modeStyleInsensitive)
-  
+
   template setConfigVar(key, val: expr) =
     result[key] = val
-  
+
   # If you need to modify these values, it might be worth updating the template
   # file in config/nimdoc.cfg.
   setConfigVar("split.item.toc", "20")
@@ -1205,7 +1214,7 @@ $content
 
 # ---------- forum ---------------------------------------------------------
 
-proc rstToHtml*(s: string, options: TRstParseOptions, 
+proc rstToHtml*(s: string, options: TRstParseOptions,
                 config: StringTableRef): string =
   ## Converts an input rst string into embeddable HTML.
   ##
@@ -1227,13 +1236,13 @@ proc rstToHtml*(s: string, options: TRstParseOptions,
   ## output you have to create your own ``TRstGenerator`` with
   ## ``initRstGenerator`` and related procs.
 
-  proc myFindFile(filename: string): string = 
+  proc myFindFile(filename: string): string =
     # we don't find any files in online mode:
     result = ""
 
   const filen = "input"
   var d: TRstGenerator
-  initRstGenerator(d, outHtml, config, filen, options, myFindFile, 
+  initRstGenerator(d, outHtml, config, filen, options, myFindFile,
                    rst.defaultMsgHandler)
   var dummyHasToc = false
   var rst = rstParse(s, filen, 0, 1, dummyHasToc, options)
@@ -1242,5 +1251,6 @@ proc rstToHtml*(s: string, options: TRstParseOptions,
 
 
 when isMainModule:
-  echo rstToHtml("*Hello* **world**!", {},
-    newStringTable(modeStyleInsensitive))
+  assert rstToHtml("*Hello* **world**!", {},
+    newStringTable(modeStyleInsensitive)) ==
+    "<em>Hello</em> <strong>world</strong>!"
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index deb120372..0c7b84090 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -70,17 +70,20 @@ const
   STDIN_FILENO* = 0  ## File number of stdin;
   STDOUT_FILENO* = 1 ## File number of stdout;
 
-when defined(endb):
-  # to not break bootstrapping again ...
-  type
-    TDIR* {.importc: "DIR", header: "<dirent.h>",
-            final, pure, incompleteStruct.} = object
-      ## A type representing a directory stream.
-else:
-  type
-    TDIR* {.importc: "DIR", header: "<dirent.h>",
-            final, pure.} = object
-      ## A type representing a directory stream.
+  DT_UNKNOWN* = 0 ## Unknown file type.
+  DT_FIFO* = 1    ## Named pipe, or FIFO.
+  DT_CHR* = 2     ## Character device.
+  DT_DIR* = 4     ## Directory.
+  DT_BLK* = 6     ## Block device.
+  DT_REG* = 8     ## Regular file.
+  DT_LNK* = 10    ## Symbolic link.
+  DT_SOCK* = 12   ## UNIX domain socket.
+  DT_WHT* = 14
+
+type
+  TDIR* {.importc: "DIR", header: "<dirent.h>",
+          incompleteStruct.} = object
+    ## A type representing a directory stream.
 
 type
   SocketHandle* = distinct cint # The type used to represent socket descriptors
@@ -91,6 +94,12 @@ type
   Tdirent* {.importc: "struct dirent",
              header: "<dirent.h>", final, pure.} = object ## dirent_t struct
     d_ino*: Tino  ## File serial number.
+    when defined(linux) or defined(macosx) or defined(bsd):
+      d_reclen*: cshort ## Length of this record. (not POSIX)
+      d_type*: int8 ## Type of file; not supported by all filesystem types.
+                    ## (not POSIX)
+      when defined(linux) or defined(bsd):
+        d_off*: TOff  ## Not an offset. Value that ``telldir()`` would return.
     d_name*: array [0..255, char] ## Name of entry.
 
   Tflock* {.importc: "struct flock", final, pure,
@@ -1405,14 +1414,6 @@ var
     ## Report status of stopped child process.
   WEXITSTATUS* {.importc, header: "<sys/wait.h>".}: cint
     ## Return exit status.
-  WIFCONTINUED* {.importc, header: "<sys/wait.h>".}: cint
-    ## True if child has been continued.
-  WIFEXITED* {.importc, header: "<sys/wait.h>".}: cint
-    ## True if child exited normally.
-  WIFSIGNALED* {.importc, header: "<sys/wait.h>".}: cint
-    ## True if child exited due to uncaught signal.
-  WIFSTOPPED* {.importc, header: "<sys/wait.h>".}: cint
-    ## True if child is currently stopped.
   WSTOPSIG* {.importc, header: "<sys/wait.h>".}: cint
     ## Return signal number that caused process to stop.
   WTERMSIG* {.importc, header: "<sys/wait.h>".}: cint
@@ -1559,6 +1560,14 @@ var
   MSG_OOB* {.importc, header: "<sys/socket.h>".}: cint
     ## Out-of-band data.
 
+proc WIFCONTINUED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
+  ## True if child has been continued.
+proc WIFEXITED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
+  ## True if child exited normally.
+proc WIFSIGNALED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
+  ## True if child exited due to uncaught signal.
+proc WIFSTOPPED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
+  ## True if child is currently stopped.
 
 when defined(linux):
   var
@@ -1570,9 +1579,12 @@ else:
 
 
 when defined(macosx):
+  # We can't use the NOSIGNAL flag in the ``send`` function, it has no effect
+  # Instead we should use SO_NOSIGPIPE in setsockopt
+  const
+    MSG_NOSIGNAL* = 0'i32
   var
-    MSG_HAVEMORE* {.importc, header: "<sys/socket.h>".}: cint
-    MSG_NOSIGNAL* = MSG_HAVEMORE
+    SO_NOSIGPIPE* {.importc, header: "<sys/socket.h>".}: cint
 else:
   var
     MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint
@@ -1739,7 +1751,10 @@ when hasSpawnH:
   when defined(linux):
     # better be safe than sorry; Linux has this flag, macosx doesn't, don't
     # know about the other OSes
-    var POSIX_SPAWN_USEVFORK* {.importc, header: "<spawn.h>".}: cint
+
+    # Non-GNU systems like TCC and musl-libc  don't define __USE_GNU, so we
+    # can't get the magic number from spawn.h
+    const POSIX_SPAWN_USEVFORK* = cint(0x40)
   else:
     # macosx lacks this, so we define the constant to be 0 to not affect
     # OR'ing of flags:
diff --git a/lib/posix/termios.nim b/lib/posix/termios.nim
new file mode 100644
index 000000000..710b2fa6b
--- /dev/null
+++ b/lib/posix/termios.nim
@@ -0,0 +1,261 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+{.deadCodeElim: on.}
+import posix
+
+type
+  Speed* = cuint
+  Tcflag* = cuint
+
+const
+  NCCS* = 32
+
+type
+  Termios* {.importc: "struct termios", header: "<termios.h>".} = object
+    c_iflag*: Tcflag        # input mode flags
+    c_oflag*: Tcflag        # output mode flags
+    c_cflag*: Tcflag        # control mode flags
+    c_lflag*: Tcflag        # local mode flags
+    c_line*: cuchar         # line discipline
+    c_cc*: array[NCCS, cuchar]  # control characters
+
+# cc characters
+
+const
+  VINTR* = 0
+  VQUIT* = 1
+  VERASE* = 2
+  VKILL* = 3
+  VEOF* = 4
+  VTIME* = 5
+  VMIN* = 6
+  VSWTC* = 7
+  VSTART* = 8
+  VSTOP* = 9
+  VSUSP* = 10
+  VEOL* = 11
+  VREPRINT* = 12
+  VDISCARD* = 13
+  VWERASE* = 14
+  VLNEXT* = 15
+  VEOL2* = 16
+
+# iflag bits
+
+const
+  IGNBRK* = 1
+  BRKINT* = 2
+  IGNPAR* = 4
+  PARMRK* = 10
+  INPCK* = 20
+  ISTRIP* = 40
+  INLCR* = 100
+  IGNCR* = 200
+  ICRNL* = 400
+  IUCLC* = 1000
+  IXON* = 2000
+  IXANY* = 4000
+  IXOFF* = 10000
+  IMAXBEL* = 20000
+  IUTF8* = 40000
+
+# oflag bits
+
+const
+  OPOST* = 1
+  OLCUC* = 2
+  ONLCR* = 4
+  OCRNL* = 10
+  ONOCR* = 20
+  ONLRET* = 40
+  OFILL* = 100
+  OFDEL* = 200
+  NLDLY* = 400
+  NL0* = 0
+  NL1* = 400
+  CRDLY* = 3000
+  CR0* = 0
+  CR1* = 1000
+  CR2* = 2000
+  CR3* = 3000
+  TABDLY* = 14000
+  TAB0* = 0
+  TAB1* = 4000
+  TAB2* = 10000
+  TAB3* = 14000
+  BSDLY* = 20000
+  BS0* = 0
+  BS1* = 20000
+  FFDLY* = 0o000000100000
+  FF0* = 0
+  FF1* = 0o000000100000
+  VTDLY* = 40000
+  VT0* = 0
+  VT1* = 40000
+  XTABS* = 14000
+
+# cflag bit meaning
+
+const
+  CBAUD* = 10017
+  B0* = 0
+  B50* = 1
+  B75* = 2
+  B110* = 3
+  B134* = 4
+  B150* = 5
+  B200* = 6
+  B300* = 7
+  B600* = 10
+  B1200* = 11
+  B1800* = 12
+  B2400* = 13
+  B4800* = 14
+  B9600* = 15
+  B19200* = 16
+  B38400* = 17
+  EXTA* = B19200
+  EXTB* = B38400
+  CSIZE* = 60
+  CS5* = 0
+  CS6* = 20
+  CS7* = 40
+  CS8* = 60
+  CSTOPB* = 100
+  CREAD* = 200
+  PARENB* = 400
+  PARODD* = 1000
+  HUPCL* = 2000
+  CLOCAL* = 4000
+  CBAUDEX* = 10000
+  B57600* = 10001
+  B115200* = 10002
+  B230400* = 10003
+  B460800* = 10004
+  B500000* = 10005
+  B576000* = 10006
+  B921600* = 10007
+  B1000000* = 10010
+  B1152000* = 10011
+  B1500000* = 10012
+  B2000000* = 10013
+  B2500000* = 10014
+  B3000000* = 10015
+  B3500000* = 10016
+  B4000000* = 10017
+  MAX_BAUD* = B4000000
+  CIBAUD* = 2003600000
+  CMSPAR* = 0o010000000000
+  CRTSCTS* = 0o020000000000
+
+# lflag bits
+
+const
+  ISIG* = 1
+  ICANON* = 2
+  XCASE* = 4
+  ECHO* = 10
+  ECHOE* = 20
+  ECHOK* = 40
+  ECHONL* = 100
+  NOFLSH* = 200
+  TOSTOP* = 400
+  ECHOCTL* = 1000
+  ECHOPRT* = 2000
+  ECHOKE* = 4000
+  FLUSHO* = 10000
+  PENDIN* = 40000
+  IEXTEN* = 0o000000100000
+  EXTPROC* = 0o000000200000
+
+# tcflow() and TCXONC use these
+
+const
+  TCOOFF* = 0
+  TCOON* = 1
+  TCIOFF* = 2
+  TCION* = 3
+
+# tcflush() and TCFLSH use these
+
+const
+  TCIFLUSH* = 0
+  TCOFLUSH* = 1
+  TCIOFLUSH* = 2
+
+# tcsetattr uses these
+
+const
+  TCSANOW* = 0
+  TCSADRAIN* = 1
+  TCSAFLUSH* = 2
+
+# Compare a character C to a value VAL from the `cc' array in a
+#   `struct termios'.  If VAL is _POSIX_VDISABLE, no character can match it.
+
+template cceq*(val, c: expr): expr =
+  c == val and val != POSIX_VDISABLE
+
+# Return the output baud rate stored in *TERMIOS_P.
+
+proc cfGetOspeed*(termios: ptr Termios): Speed {.importc: "cfgetospeed",
+    header: "<termios.h>".}
+# Return the input baud rate stored in *TERMIOS_P.
+
+proc cfGetIspeed*(termios: ptr Termios): Speed {.importc: "cfgetispeed",
+    header: "<termios.h>".}
+# Set the output baud rate stored in *TERMIOS_P to SPEED.
+
+proc cfSetOspeed*(termios: ptr Termios; speed: Speed): cint {.
+    importc: "cfsetospeed", header: "<termios.h>".}
+# Set the input baud rate stored in *TERMIOS_P to SPEED.
+
+proc cfSetIspeed*(termios: ptr Termios; speed: Speed): cint {.
+    importc: "cfsetispeed", header: "<termios.h>".}
+# Set both the input and output baud rates in *TERMIOS_OP to SPEED.
+
+proc cfSetSpeed*(termios: ptr Termios; speed: Speed): cint {.
+    importc: "cfsetspeed", header: "<termios.h>".}
+# Put the state of FD into *TERMIOS_P.
+
+proc tcGetAttr*(fd: cint; termios: ptr Termios): cint {.
+    importc: "tcgetattr", header: "<termios.h>".}
+# Set the state of FD to *TERMIOS_P.
+#   Values for OPTIONAL_ACTIONS (TCSA*) are in <bits/termios.h>.
+
+proc tcSetAttr*(fd: cint; optional_actions: cint; termios: ptr Termios): cint {.
+    importc: "tcsetattr", header: "<termios.h>".}
+# Set *TERMIOS_P to indicate raw mode.
+
+proc cfMakeRaw*(termios: ptr Termios) {.importc: "cfmakeraw",
+    header: "<termios.h>".}
+# Send zero bits on FD.
+
+proc tcSendBreak*(fd: cint; duration: cint): cint {.importc: "tcsendbreak",
+    header: "<termios.h>".}
+# Wait for pending output to be written on FD.
+#
+#   This function is a cancellation point and therefore not marked with
+#  .
+
+proc tcDrain*(fd: cint): cint {.importc: "tcdrain", header: "<termios.h>".}
+# Flush pending data on FD.
+#   Values for QUEUE_SELECTOR (TC{I,O,IO}FLUSH) are in <bits/termios.h>.
+
+proc tcFlush*(fd: cint; queue_selector: cint): cint {.importc: "tcflush",
+    header: "<termios.h>".}
+# Suspend or restart transmission on FD.
+#   Values for ACTION (TC[IO]{OFF,ON}) are in <bits/termios.h>.
+
+proc tcFlow*(fd: cint; action: cint): cint {.importc: "tcflow",
+    header: "<termios.h>".}
+# Get process group ID for session leader for controlling terminal FD.
+
+proc tcGetSid*(fd: cint): TPid {.importc: "tcgetsid", header: "<termios.h>".}
diff --git a/lib/pure/actors.nim b/lib/pure/actors.nim
index f2c50ce4c..294c24741 100644
--- a/lib/pure/actors.nim
+++ b/lib/pure/actors.nim
@@ -200,7 +200,7 @@ template schedule =
   if minIdx >= 0:
     p.actors[minIdx].i.send(t)
   else:
-    raise newException(EDeadThread, "cannot send message; thread died")
+    raise newException(DeadThreadError, "cannot send message; thread died")
 
 proc spawn*[TIn, TOut](p: var TActorPool[TIn, TOut], input: TIn,
                        action: proc (input: TIn): TOut {.thread.}
@@ -221,7 +221,7 @@ proc spawn*[TIn](p: var TActorPool[TIn, void], input: TIn,
   setupTask()
   schedule()
   
-when isMainModule:
+when not defined(testing) and isMainModule:
   var
     a: TActorPool[int, void]
   createActorPool(a)
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 0358a9a81..f7ccb9234 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -11,20 +11,20 @@
 
 type
   SortOrder* = enum   ## sort order
-    Descending, Ascending 
+    Descending, Ascending
 
 {.deprecated: [TSortOrder: SortOrder].}
 
 
-proc `*`*(x: int, order: SortOrder): int {.inline.} = 
+proc `*`*(x: int, order: SortOrder): int {.inline.} =
   ## flips `x` if ``order == Descending``;
   ## if ``order == Ascending`` then `x` is returned.
-  ## `x` is supposed to be the result of a comparator, ie ``< 0`` for 
+  ## `x` is supposed to be the result of a comparator, ie ``< 0`` for
   ## *less than*, ``== 0`` for *equal*, ``> 0`` for *greater than*.
   var y = order.ord - 1
   result = (x xor y) - y
 
-proc reverse*[T](a: var openArray[T], first, last: int) =
+proc reverse*[T](a: var openArray[T], first, last: Natural) =
   ## reverses the array ``a[first..last]``.
   var x = first
   var y = last
@@ -37,11 +37,11 @@ proc reverse*[T](a: var openArray[T]) =
   ## reverses the array `a`.
   reverse(a, 0, a.high)
 
-proc reversed*[T](a: openArray[T], first, last: int): seq[T] =
+proc reversed*[T](a: openArray[T], first, last: Natural): seq[T] =
   ## returns the reverse of the array `a[first..last]`.
   result = newSeq[T](last - first + 1)
-  var x = first
-  var y = last
+  var x = first.int
+  var y = last.int
   while x <= last:
     result[x] = a[y]
     dec(y)
@@ -73,14 +73,15 @@ const
   onlySafeCode = true
 
 proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int {.closure.}): int =
-  ## same as binarySearch except that if key is not in `a` then this 
+  ## same as binarySearch except that if key is not in `a` then this
   ## returns the location where `key` would be if it were. In other
-  ## words if you have a sorted sequence and you call insert(thing, elm, lowerBound(thing, elm))
-  ## the sequence will still be sorted
+  ## words if you have a sorted sequence and you call
+  ## insert(thing, elm, lowerBound(thing, elm))
+  ## the sequence will still be sorted.
+  ##
+  ## `cmp` is the comparator function to use, the expected return values are
+  ## the same as that of system.cmp.
   ##
-  ## `cmp` is the comparator function to use, the expected return values are the same as
-  ## that of system.cmp
-  ## 
   ## example::
   ##
   ##   var arr = @[1,2,3,5,6,7,8,9]
@@ -102,9 +103,9 @@ proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int {.closure.})
       count = step
 
 proc lowerBound*[T](a: openArray[T], key: T): int = lowerBound(a, key, cmp[T])
-proc merge[T](a, b: var openArray[T], lo, m, hi: int, 
+proc merge[T](a, b: var openArray[T], lo, m, hi: int,
               cmp: proc (x, y: T): int {.closure.}, order: SortOrder) =
-  template `<-` (a, b: expr) = 
+  template `<-` (a, b: expr) =
     when false:
       a = b
     elif onlySafeCode:
@@ -151,10 +152,10 @@ proc merge[T](a, b: var openArray[T], lo, m, hi: int,
 proc sort*[T](a: var openArray[T],
               cmp: proc (x, y: T): int {.closure.},
               order = SortOrder.Ascending) =
-  ## Default Nim sort. The sorting is guaranteed to be stable and 
+  ## Default Nim sort. The sorting is guaranteed to be stable and
   ## the worst case is guaranteed to be O(n log n).
   ## The current implementation uses an iterative
-  ## mergesort to achieve this. It uses a temporary sequence of 
+  ## mergesort to achieve this. It uses a temporary sequence of
   ## length ``a.len div 2``. Currently Nim does not support a
   ## sensible default argument for ``cmp``, so you have to provide one
   ## of your own. However, the ``system.cmp`` procs can be used:
@@ -187,6 +188,48 @@ proc sort*[T](a: var openArray[T],
       dec(m, s*2)
     s = s*2
 
+proc sorted*[T](a: openArray[T], cmp: proc(x, y: T): int {.closure.},
+                order = SortOrder.Ascending): seq[T] =
+  ## returns `a` sorted by `cmp` in the specified `order`.
+  result = newSeq[T](a.len)
+  for i in 0 .. a.high:
+    result[i] = a[i]
+  sort(result, cmp, order)
+
+template sortedByIt*(seq1, op: expr): expr =
+  ## Convenience template around the ``sorted`` proc to reduce typing.
+  ##
+  ## The template injects the ``it`` variable which you can use directly in an
+  ## expression. Example:
+  ##
+  ## .. code-block:: nim
+  ##
+  ##   type Person = tuple[name: string, age: int]
+  ##   var
+  ##     p1: Person = (name: "p1", age: 60)
+  ##     p2: Person = (name: "p2", age: 20)
+  ##     p3: Person = (name: "p3", age: 30)
+  ##     p4: Person = (name: "p4", age: 30)
+  ##
+  ##   people = @[p1,p2,p4,p3]
+  ##
+  ##   echo people.sortedByIt(it.name)
+  ##
+  ## Because the underlying ``cmp()`` is defined for tuples you can do
+  ## a nested sort like in the following example:
+  ##
+  ## .. code-block:: nim
+  ##
+  ##   echo people.sortedByIt((it.age, it.name))
+  ##
+  var result {.gensym.} = sorted(seq1, proc(x, y: type(seq1[0])): int =
+    var it {.inject.} = x
+    let a = op
+    it = y
+    let b = op
+    result = cmp(a, b))
+  result
+
 proc product*[T](x: openArray[seq[T]]): seq[seq[T]] =
   ## produces the Cartesian product of the array. Warning: complexity
   ## may explode.
@@ -210,13 +253,72 @@ proc product*[T](x: openArray[seq[T]]): seq[seq[T]] =
   while true:
     while indexes[index] == -1:
       indexes[index] = initial[index]
-      index +=1
+      index += 1
       if index == x.len: return
-      indexes[index] -=1
+      indexes[index] -= 1
     for ni, i in indexes:
       next[ni] = x[ni][i]
     var res: seq[T]
     shallowCopy(res, next)
     result.add(res)
     index = 0
-    indexes[index] -=1
+    indexes[index] -= 1
+
+proc nextPermutation*[T](x: var openarray[T]): bool {.discardable.} =
+  ## Calculates the next lexicographic permutation, directly modifying ``x``.
+  ## The result is whether a permutation happened, otherwise we have reached
+  ## the last-ordered permutation.
+  ##
+  ## .. code-block:: nim
+  ##
+  ##     var v = @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+  ##     v.nextPermutation()
+  ##     echo v
+  if x.len < 2:
+    return false
+
+  var i = x.high
+  while i > 0 and x[i-1] >= x[i]:
+    dec i
+
+  if i == 0:
+    return false
+
+  var j = x.high
+  while j >= i and x[j] <= x[i-1]:
+    dec j
+
+  swap x[j], x[i-1]
+  x.reverse(i, x.high)
+
+  result = true
+
+proc prevPermutation*[T](x: var openarray[T]): bool {.discardable.} =
+  ## Calculates the previous lexicographic permutation, directly modifying
+  ## ``x``.  The result is whether a permutation happened, otherwise we have
+  ## reached the first-ordered permutation.
+  ##
+  ## .. code-block:: nim
+  ##
+  ##     var v = @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8]
+  ##     v.prevPermutation()
+  ##     echo v
+  if x.len < 2:
+    return false
+
+  var i = x.high
+  while i > 0 and x[i-1] <= x[i]:
+    dec i
+
+  if i == 0:
+    return false
+
+  x.reverse(i, x.high)
+
+  var j = x.high
+  while j >= i and x[j-1] < x[i-1]:
+    dec j
+
+  swap x[i-1], x[j]
+
+  result = true
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index 4bdce9cfb..a4d7a1632 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -121,7 +121,7 @@ export Port, SocketFlag
 ##
 ## Limitations/Bugs
 ## ----------------
-## 
+##
 ## * ``except`` statement (without `try`) does not work inside async procedures.
 ## * The effect system (``raises: []``) does not work with async procedures.
 ## * Can't await in a ``except`` body
@@ -379,7 +379,7 @@ when defined(windows) or defined(nimdoc):
     if p.handles.len == 0 and p.timers.len == 0:
       raise newException(ValueError,
         "No handles or timers registered in dispatcher.")
-    
+
     let llTimeout =
       if timeout ==  -1: winlean.INFINITE
       else: timeout.int32
@@ -436,12 +436,12 @@ when defined(windows) or defined(nimdoc):
     if not initPointer(dummySock, getAcceptExSockAddrsPtr, WSAID_GETACCEPTEXSOCKADDRS):
       raiseOSError(osLastError())
 
-  proc connectEx(s: SocketHandle, name: ptr SockAddr, namelen: cint, 
+  proc connectEx(s: SocketHandle, name: ptr SockAddr, namelen: cint,
                   lpSendBuffer: pointer, dwSendDataLength: Dword,
                   lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool =
     if connectExPtr.isNil: raise newException(ValueError, "Need to initialise ConnectEx().")
     let fun =
-      cast[proc (s: SocketHandle, name: ptr SockAddr, namelen: cint, 
+      cast[proc (s: SocketHandle, name: ptr SockAddr, namelen: cint,
          lpSendBuffer: pointer, dwSendDataLength: Dword,
          lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool {.stdcall,gcsafe.}](connectExPtr)
 
@@ -475,7 +475,7 @@ when defined(windows) or defined(nimdoc):
                  dwRemoteAddressLength: Dword, LocalSockaddr: ptr ptr SockAddr,
                  LocalSockaddrLength: LPInt, RemoteSockaddr: ptr ptr SockAddr,
                 RemoteSockaddrLength: LPInt) {.stdcall,gcsafe.}](getAcceptExSockAddrsPtr)
-    
+
     fun(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
                   dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength,
                   RemoteSockaddr, RemoteSockaddrLength)
@@ -514,7 +514,7 @@ when defined(windows) or defined(nimdoc):
             else:
               retFuture.fail(newException(OSError, osErrorMsg(errcode)))
       )
-      
+
       var ret = connectEx(socket.SocketHandle, it.ai_addr,
                           sizeof(Sockaddr_in).cint, nil, 0, nil,
                           cast[POVERLAPPED](ol))
@@ -565,7 +565,7 @@ when defined(windows) or defined(nimdoc):
     var dataBuf: TWSABuf
     dataBuf.buf = cast[cstring](alloc0(size))
     dataBuf.len = size
-    
+
     var bytesReceived: Dword
     var flagsio = flags.toOSFlags().Dword
     var ol = PCustomOverlapped()
@@ -606,15 +606,15 @@ when defined(windows) or defined(nimdoc):
           retFuture.fail(newException(OSError, osErrorMsg(err)))
     elif ret == 0 and bytesReceived == 0 and dataBuf.buf[0] == '\0':
       # We have to ensure that the buffer is empty because WSARecv will tell
-      # us immediatelly when it was disconnected, even when there is still
+      # us immediately when it was disconnected, even when there is still
       # data in the buffer.
       # We want to give the user as much data as we can. So we only return
       # the empty string (which signals a disconnection) when there is
       # nothing left to read.
       retFuture.complete("")
-      # TODO: "For message-oriented sockets, where a zero byte message is often 
-      # allowable, a failure with an error code of WSAEDISCON is used to 
-      # indicate graceful closure." 
+      # TODO: "For message-oriented sockets, where a zero byte message is often
+      # allowable, a failure with an error code of WSAEDISCON is used to
+      # indicate graceful closure."
       # ~ http://msdn.microsoft.com/en-us/library/ms741688%28v=vs.85%29.aspx
     else:
       # Request to read completed immediately.
@@ -634,6 +634,93 @@ when defined(windows) or defined(nimdoc):
       # free ``ol``.
     return retFuture
 
+  proc recvInto*(socket: TAsyncFD, buf: cstring, size: int,
+                flags = {SocketFlag.SafeDisconn}): Future[int] =
+    ## Reads **up to** ``size`` bytes from ``socket`` into ``buf``, which must
+    ## at least be of that size. Returned future will complete once all the
+    ## data requested is read, a part of the data has been read, or the socket
+    ## has disconnected in which case the future will complete with a value of
+    ## ``0``.
+    ##
+    ## **Warning**: The ``Peek`` socket flag is not supported on Windows.
+
+
+    # Things to note:
+    #   * When WSARecv completes immediately then ``bytesReceived`` is very
+    #     unreliable.
+    #   * Still need to implement message-oriented socket disconnection,
+    #     '\0' in the message currently signifies a socket disconnect. Who
+    #     knows what will happen when someone sends that to our socket.
+    verifyPresence(socket)
+    assert SocketFlag.Peek notin flags, "Peek not supported on Windows."
+
+    var retFuture = newFuture[int]("recvInto")
+
+    #buf[] = '\0'
+    var dataBuf: TWSABuf
+    dataBuf.buf = buf
+    dataBuf.len = size
+
+    var bytesReceived: Dword
+    var flagsio = flags.toOSFlags().Dword
+    var ol = PCustomOverlapped()
+    GC_ref(ol)
+    ol.data = TCompletionData(fd: socket, cb:
+      proc (fd: TAsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
+        if not retFuture.finished:
+          if errcode == OSErrorCode(-1):
+            if bytesCount == 0 and dataBuf.buf[0] == '\0':
+              retFuture.complete(0)
+            else:
+              retFuture.complete(bytesCount)
+          else:
+            if flags.isDisconnectionError(errcode):
+              retFuture.complete(0)
+            else:
+              retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+        if dataBuf.buf != nil:
+          dataBuf.buf = nil
+    )
+
+    let ret = WSARecv(socket.SocketHandle, addr dataBuf, 1, addr bytesReceived,
+                      addr flagsio, cast[POVERLAPPED](ol), nil)
+    if ret == -1:
+      let err = osLastError()
+      if err.int32 != ERROR_IO_PENDING:
+        if dataBuf.buf != nil:
+          dataBuf.buf = nil
+        GC_unref(ol)
+        if flags.isDisconnectionError(err):
+          retFuture.complete(0)
+        else:
+          retFuture.fail(newException(OSError, osErrorMsg(err)))
+    elif ret == 0 and bytesReceived == 0 and dataBuf.buf[0] == '\0':
+      # We have to ensure that the buffer is empty because WSARecv will tell
+      # us immediately when it was disconnected, even when there is still
+      # data in the buffer.
+      # We want to give the user as much data as we can. So we only return
+      # the empty string (which signals a disconnection) when there is
+      # nothing left to read.
+      retFuture.complete(0)
+      # TODO: "For message-oriented sockets, where a zero byte message is often
+      # allowable, a failure with an error code of WSAEDISCON is used to
+      # indicate graceful closure."
+      # ~ http://msdn.microsoft.com/en-us/library/ms741688%28v=vs.85%29.aspx
+    else:
+      # Request to read completed immediately.
+      # From my tests bytesReceived isn't reliable.
+      let realSize =
+        if bytesReceived == 0:
+          size
+        else:
+          bytesReceived
+      assert realSize <= size
+      retFuture.complete(realSize)
+      # We don't deallocate ``ol`` here because even though this completed
+      # immediately poll will still be notified about its completion and it will
+      # free ``ol``.
+    return retFuture
+
   proc send*(socket: TAsyncFD, data: string,
              flags = {SocketFlag.SafeDisconn}): Future[void] =
     ## Sends ``data`` to ``socket``. The returned future will complete once all
@@ -748,7 +835,7 @@ when defined(windows) or defined(nimdoc):
 
     # http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
     let ret = acceptEx(socket.SocketHandle, clientSock, addr lpOutputBuf[0],
-                       dwReceiveDataLength, 
+                       dwReceiveDataLength,
                        dwLocalAddressLength,
                        dwRemoteAddressLength,
                        addr dwBytesReceived, cast[POVERLAPPED](ol))
@@ -803,7 +890,7 @@ else:
   else:
     from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK,
                       MSG_NOSIGNAL
-  
+
   type
     TAsyncFD* = distinct cint
     TCallback = proc (fd: TAsyncFD): bool {.closure,gcsafe.}
@@ -841,6 +928,8 @@ else:
   proc newAsyncRawSocket*(domain: cint, typ: cint, protocol: cint): TAsyncFD =
     result = newRawSocket(domain, typ, protocol).TAsyncFD
     result.SocketHandle.setBlocking(false)
+    when defined(macosx):
+        result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
     register(result)
 
   proc newAsyncRawSocket*(domain: Domain = AF_INET,
@@ -848,8 +937,10 @@ else:
                protocol: Protocol = IPPROTO_TCP): TAsyncFD =
     result = newRawSocket(domain, typ, protocol).TAsyncFD
     result.SocketHandle.setBlocking(false)
+    when defined(macosx):
+        result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
     register(result)
-  
+
   proc closeSocket*(sock: TAsyncFD) =
     let disp = getGlobalDispatcher()
     sock.SocketHandle.close()
@@ -864,20 +955,24 @@ else:
       raise newException(ValueError, "File descriptor not registered.")
     p.selector[fd.SocketHandle].data.PData.readCBs.add(cb)
     update(fd, p.selector[fd.SocketHandle].events + {EvRead})
-  
+
   proc addWrite*(fd: TAsyncFD, cb: TCallback) =
     let p = getGlobalDispatcher()
     if fd.SocketHandle notin p.selector:
       raise newException(ValueError, "File descriptor not registered.")
     p.selector[fd.SocketHandle].data.PData.writeCBs.add(cb)
     update(fd, p.selector[fd.SocketHandle].events + {EvWrite})
-  
+
   proc poll*(timeout = 500) =
     let p = getGlobalDispatcher()
     for info in p.selector.select(timeout):
       let data = PData(info.key.data)
       assert data.fd == info.key.fd.TAsyncFD
       #echo("In poll ", data.fd.cint)
+      if EvError in info.events:
+        closeSocket(data.fd)
+        continue
+
       if EvRead in info.events:
         # Callback may add items to ``data.readCBs`` which causes issues if
         # we are iterating over ``data.readCBs`` at the same time. We therefore
@@ -888,7 +983,7 @@ else:
           if not cb(data.fd):
             # Callback wants to be called again.
             data.readCBs.add(cb)
-      
+
       if EvWrite in info.events:
         let currentCBs = data.writeCBs
         data.writeCBs = @[]
@@ -896,7 +991,7 @@ else:
           if not cb(data.fd):
             # Callback wants to be called again.
             data.writeCBs.add(cb)
-      
+
       if info.key in p.selector:
         var newEvents: set[Event]
         if data.readCBs.len != 0: newEvents = {EvRead}
@@ -909,16 +1004,16 @@ else:
         discard
 
     processTimers(p)
-  
+
   proc connect*(socket: TAsyncFD, address: string, port: Port,
     af = AF_INET): Future[void] =
     var retFuture = newFuture[void]("connect")
-    
+
     proc cb(fd: TAsyncFD): bool =
       # We have connected.
       retFuture.complete()
       return true
-    
+
     var aiList = getAddrInfo(address, port, af)
     var success = false
     var lastError: OSErrorCode
@@ -948,14 +1043,13 @@ else:
   proc recv*(socket: TAsyncFD, size: int,
              flags = {SocketFlag.SafeDisconn}): Future[string] =
     var retFuture = newFuture[string]("recv")
-    
+
     var readBuffer = newString(size)
 
     proc cb(sock: TAsyncFD): bool =
       result = true
       let res = recv(sock.SocketHandle, addr readBuffer[0], size.cint,
                      flags.toOSFlags())
-      #echo("recv cb res: ", res)
       if res < 0:
         let lastError = osLastError()
         if lastError.int32 notin {EINTR, EWOULDBLOCK, EAGAIN}:
@@ -976,12 +1070,36 @@ else:
     addRead(socket, cb)
     return retFuture
 
+  proc recvInto*(socket: TAsyncFD, buf: cstring, size: int,
+                  flags = {SocketFlag.SafeDisconn}): Future[int] =
+    var retFuture = newFuture[int]("recvInto")
+
+    proc cb(sock: TAsyncFD): bool =
+      result = true
+      let res = recv(sock.SocketHandle, buf, size.cint,
+                     flags.toOSFlags())
+      if res < 0:
+        let lastError = osLastError()
+        if lastError.int32 notin {EINTR, EWOULDBLOCK, EAGAIN}:
+          if flags.isDisconnectionError(lastError):
+            retFuture.complete(0)
+          else:
+            retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+        else:
+          result = false # We still want this callback to be called.
+      else:
+        retFuture.complete(res)
+    # TODO: The following causes a massive slowdown.
+    #if not cb(socket):
+    addRead(socket, cb)
+    return retFuture
+
   proc send*(socket: TAsyncFD, data: string,
              flags = {SocketFlag.SafeDisconn}): Future[void] =
     var retFuture = newFuture[void]("send")
-    
+
     var written = 0
-    
+
     proc cb(sock: TAsyncFD): bool =
       result = true
       let netSize = data.len-written
@@ -1060,6 +1178,17 @@ proc accept*(socket: TAsyncFD,
 
 # -- Await Macro
 
+proc skipUntilStmtList(node: NimNode): NimNode {.compileTime.} =
+  # Skips a nest of StmtList's.
+  result = node
+  if node[0].kind == nnkStmtList:
+    result = skipUntilStmtList(node[0])
+
+proc skipStmtList(node: NimNode): NimNode {.compileTime.} =
+  result = node
+  if node[0].kind == nnkStmtList:
+    result = node[0]
+
 template createCb(retFutureSym, iteratorNameSym,
                    name: expr): stmt {.immediate.} =
   var nameIterVar = iteratorNameSym
@@ -1083,11 +1212,11 @@ template createCb(retFutureSym, iteratorNameSym,
   cb()
   #{.pop.}
 proc generateExceptionCheck(futSym,
-    tryStmt, rootReceiver, fromNode: PNimrodNode): PNimrodNode {.compileTime.} =
+    tryStmt, rootReceiver, fromNode: NimNode): NimNode {.compileTime.} =
   if tryStmt.kind == nnkNilLit:
     result = rootReceiver
   else:
-    var exceptionChecks: seq[tuple[cond, body: PNimrodNode]] = @[]
+    var exceptionChecks: seq[tuple[cond, body: NimNode]] = @[]
     let errorNode = newDotExpr(futSym, newIdentNode("error"))
     for i in 1 .. <tryStmt.len:
       let exceptBranch = tryStmt[i]
@@ -1095,7 +1224,7 @@ proc generateExceptionCheck(futSym,
         exceptionChecks.add((newIdentNode("true"), exceptBranch[0]))
       else:
         var exceptIdentCount = 0
-        var ifCond: PNimrodNode
+        var ifCond: NimNode
         for i in 0 .. <exceptBranch.len:
           let child = exceptBranch[i]
           if child.kind == nnkIdent:
@@ -1129,10 +1258,10 @@ proc generateExceptionCheck(futSym,
     )
     result.add elseNode
 
-template createVar(result: var PNimrodNode, futSymName: string,
-                   asyncProc: PNimrodNode,
+template createVar(result: var NimNode, futSymName: string,
+                   asyncProc: NimNode,
                    valueReceiver, rootReceiver: expr,
-                   fromNode: PNimrodNode) =
+                   fromNode: NimNode) =
   result = newNimNode(nnkStmtList, fromNode)
   var futSym = genSym(nskVar, "future")
   result.add newVarStmt(futSym, asyncProc) # -> var future<x> = y
@@ -1140,9 +1269,9 @@ template createVar(result: var PNimrodNode, futSymName: string,
   valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future<x>.read
   result.add generateExceptionCheck(futSym, tryStmt, rootReceiver, fromNode)
 
-proc processBody(node, retFutureSym: PNimrodNode,
+proc processBody(node, retFutureSym: NimNode,
                  subTypeIsVoid: bool,
-                 tryStmt: PNimrodNode): PNimrodNode {.compileTime.} =
+                 tryStmt: NimNode): NimNode {.compileTime.} =
   #echo(node.treeRepr)
   result = node
   case node.kind
@@ -1168,7 +1297,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
         result = newNimNode(nnkYieldStmt, node).add(node[1]) # -> yield x
       of nnkCall, nnkCommand:
         # await foo(p, x)
-        var futureValue: PNimrodNode
+        var futureValue: NimNode
         result.createVar("future" & $node[1][0].toStrLit, node[1], futureValue,
                   futureValue, node)
       else:
@@ -1207,33 +1336,60 @@ proc processBody(node, retFutureSym: PNimrodNode,
   of nnkTryStmt:
     # try: await x; except: ...
     result = newNimNode(nnkStmtList, node)
-    proc processForTry(n: PNimrodNode, i: var int,
-                       res: PNimrodNode): bool {.compileTime.} =
+    template wrapInTry(n, tryBody: expr) =
+      var temp = n
+      n[0] = tryBody
+      tryBody = temp
+
+      # Transform ``except`` body.
+      # TODO: Could we perform some ``await`` transformation here to get it
+      # working in ``except``?
+      tryBody[1] = processBody(n[1], retFutureSym, subTypeIsVoid, nil)
+
+    proc processForTry(n: NimNode, i: var int,
+                       res: NimNode): bool {.compileTime.} =
+      ## Transforms the body of the tryStmt. Does not transform the
+      ## body in ``except``.
+      ## Returns true if the tryStmt node was transformed into an ifStmt.
       result = false
-      while i < n[0].len:
-        var processed = processBody(n[0][i], retFutureSym, subTypeIsVoid, n)
-        if processed.kind != n[0][i].kind or processed.len != n[0][i].len:
+      var skipped = n.skipStmtList()
+      while i < skipped.len:
+        var processed = processBody(skipped[i], retFutureSym,
+                                    subTypeIsVoid, n)
+
+        # Check if we transformed the node into an exception check.
+        # This suggests skipped[i] contains ``await``.
+        if processed.kind != skipped[i].kind or processed.len != skipped[i].len:
+          processed = processed.skipUntilStmtList()
           expectKind(processed, nnkStmtList)
           expectKind(processed[2][1], nnkElse)
           i.inc
-          discard processForTry(n, i, processed[2][1][0])
+
+          if not processForTry(n, i, processed[2][1][0]):
+            # We need to wrap the nnkElse nodes back into a tryStmt.
+            # As they are executed if an exception does not happen
+            # inside the awaited future.
+            # The following code will wrap the nodes inside the
+            # original tryStmt.
+            wrapInTry(n, processed[2][1][0])
+
           res.add processed
           result = true
         else:
-          res.add n[0][i]
+          res.add skipped[i]
           i.inc
     var i = 0
     if not processForTry(node, i, result):
-      var temp = node
-      temp[0] = result
-      result = temp
+      # If the tryStmt hasn't been transformed we can just put the body
+      # back into it.
+      wrapInTry(node, result)
     return
   else: discard
 
   for i in 0 .. <result.len:
-    result[i] = processBody(result[i], retFutureSym, subTypeIsVoid, tryStmt)
+    result[i] = processBody(result[i], retFutureSym, subTypeIsVoid, nil)
 
-proc getName(node: PNimrodNode): string {.compileTime.} =
+proc getName(node: NimNode): string {.compileTime.} =
   case node.kind
   of nnkPostfix:
     return $node[1].ident
@@ -1273,29 +1429,40 @@ macro async*(prc: stmt): stmt {.immediate.} =
     if returnType.kind == nnkEmpty: newIdentNode("void")
     else: returnType[1]
   outerProcBody.add(
-    newVarStmt(retFutureSym, 
+    newVarStmt(retFutureSym,
       newCall(
         newNimNode(nnkBracketExpr, prc[6]).add(
           newIdentNode(!"newFuture"), # TODO: Strange bug here? Remove the `!`.
           subRetType),
       newLit(prc[0].getName)))) # Get type from return type of this proc
-  
-  # -> iterator nameIter(): FutureBase {.closure.} = 
+
+  # -> iterator nameIter(): FutureBase {.closure.} =
+  # ->   {.push warning[resultshadowed]: off.}
   # ->   var result: T
+  # ->   {.pop.}
   # ->   <proc_body>
   # ->   complete(retFuture, result)
   var iteratorNameSym = genSym(nskIterator, $prc[0].getName & "Iter")
   var procBody = prc[6].processBody(retFutureSym, subtypeIsVoid, nil)
   if not subtypeIsVoid:
-    procBody.insert(0, newNimNode(nnkVarSection, prc[6]).add(
+    procBody.insert(0, newNimNode(nnkPragma).add(newIdentNode("push"),
+      newNimNode(nnkExprColonExpr).add(newNimNode(nnkBracketExpr).add(
+        newIdentNode("warning"), newIdentNode("resultshadowed")),
+      newIdentNode("off")))) # -> {.push warning[resultshadowed]: off.}
+
+    procBody.insert(1, newNimNode(nnkVarSection, prc[6]).add(
       newIdentDefs(newIdentNode("result"), returnType[1]))) # -> var result: T
+
+    procBody.insert(2, newNimNode(nnkPragma).add(
+      newIdentNode("pop"))) # -> {.pop.})
+
     procBody.add(
       newCall(newIdentNode("complete"),
         retFutureSym, newIdentNode("result"))) # -> complete(retFuture, result)
   else:
     # -> complete(retFuture)
     procBody.add(newCall(newIdentNode("complete"), retFutureSym))
-  
+
   var closureIterator = newProc(iteratorNameSym, [newIdentNode("FutureBase")],
                                 procBody, nnkIteratorDef)
   closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure"))
@@ -1309,7 +1476,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
 
   # -> return retFuture
   outerProcBody.add newNimNode(nnkReturnStmt, prc[6][prc[6].len-1]).add(retFutureSym)
-  
+
   result = prc
 
   # Remove the 'async' pragma.
@@ -1325,7 +1492,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   result[6] = outerProcBody
 
   #echo(treeRepr(result))
-  #if prc[0].getName == "catch":
+  #if prc[0].getName == "test":
   #  echo(toStrLit(result))
 
 proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
@@ -1335,7 +1502,7 @@ proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
   ## If a full line is read ``\r\L`` is not
   ## added to ``line``, however if solely ``\r\L`` is read then ``line``
   ## will be set to it.
-  ## 
+  ##
   ## If the socket is disconnected, ``line`` will be set to ``""``.
   ##
   ## If the socket is disconnected in the middle of a line (before ``\r\L``
@@ -1346,7 +1513,7 @@ proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
   ##
   ## **Note**: This procedure is mostly used for testing. You likely want to
   ## use ``asyncnet.recvLine`` instead.
-  
+
   template addNLIfEmpty(): stmt =
     if result.len == 0:
       result.add("\c\L")
diff --git a/lib/pure/asyncdispatch.nimrod.cfg b/lib/pure/asyncdispatch.nim.cfg
index e88f8eec3..e88f8eec3 100644
--- a/lib/pure/asyncdispatch.nimrod.cfg
+++ b/lib/pure/asyncdispatch.nim.cfg
diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim
index c09cb5a35..25e121183 100644
--- a/lib/pure/asyncfile.nim
+++ b/lib/pure/asyncfile.nim
@@ -1,13 +1,13 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## This module implements asynchronous file handling.
+## This module implements asynchronous file reading and writing.
 ##
 ## .. code-block:: Nim
 ##    import asyncfile, asyncdispatch, os
@@ -24,18 +24,18 @@
 
 import asyncdispatch, os
 
-when defined(windows):
+when defined(windows) or defined(nimdoc):
   import winlean
 else:
   import posix
 
 type
-  AsyncFile = ref object
+  AsyncFile* = ref object
     fd: TAsyncFd
     offset: int64
 
-when defined(windows):
-  proc getDesiredAccess(mode: TFileMode): int32 =
+when defined(windows) or defined(nimdoc):
+  proc getDesiredAccess(mode: FileMode): int32 =
     case mode
     of fmRead:
       result = GENERIC_READ
@@ -44,7 +44,7 @@ when defined(windows):
     of fmReadWrite, fmReadWriteExisting:
       result = GENERIC_READ or GENERIC_WRITE
 
-  proc getCreationDisposition(mode: TFileMode, filename: string): int32 =
+  proc getCreationDisposition(mode: FileMode, filename: string): int32 =
     case mode
     of fmRead, fmReadWriteExisting:
       OPEN_EXISTING
@@ -54,7 +54,7 @@ when defined(windows):
       else:
         CREATE_NEW
 else:
-  proc getPosixFlags(mode: TFileMode): cint =
+  proc getPosixFlags(mode: FileMode): cint =
     case mode
     of fmRead:
       result = O_RDONLY
@@ -70,18 +70,18 @@ else:
 
 proc getFileSize(f: AsyncFile): int64 =
   ## Retrieves the specified file's size.
-  when defined(windows):
+  when defined(windows) or defined(nimdoc):
     var high: DWord
     let low = getFileSize(f.fd.THandle, addr high)
     if low == INVALID_FILE_SIZE:
-      raiseOSError()
+      raiseOSError(osLastError())
     return (high shl 32) or low
 
 proc openAsync*(filename: string, mode = fmRead): AsyncFile =
   ## Opens a file specified by the path in ``filename`` using
   ## the specified ``mode`` asynchronously.
   new result
-  when defined(windows):
+  when defined(windows) or defined(nimdoc):
     let flags = FILE_FLAG_OVERLAPPED or FILE_ATTRIBUTE_NORMAL
     let desiredAccess = getDesiredAccess(mode)
     let creationDisposition = getCreationDisposition(mode, filename)
@@ -95,7 +95,7 @@ proc openAsync*(filename: string, mode = fmRead): AsyncFile =
           nil, creationDisposition, flags, 0).TAsyncFd
 
     if result.fd.THandle == INVALID_HANDLE_VALUE:
-      raiseOSError()
+      raiseOSError(osLastError())
 
     register(result.fd)
 
@@ -108,7 +108,7 @@ proc openAsync*(filename: string, mode = fmRead): AsyncFile =
     let perm = S_IRUSR or S_IWUSR or S_IRGRP or S_IWGRP or S_IROTH
     result.fd = open(filename, flags, perm).TAsyncFD
     if result.fd.cint == -1:
-      raiseOSError()
+      raiseOSError(osLastError())
 
     register(result.fd)
 
@@ -120,7 +120,7 @@ proc read*(f: AsyncFile, size: int): Future[string] =
   ## returned.
   var retFuture = newFuture[string]("asyncfile.read")
 
-  when defined(windows):
+  when defined(windows) or defined(nimdoc):
     var buffer = alloc0(size)
 
     var ol = PCustomOverlapped()
@@ -185,7 +185,7 @@ proc read*(f: AsyncFile, size: int): Future[string] =
       if res < 0:
         let lastError = osLastError()
         if lastError.int32 != EAGAIN:
-          retFuture.fail(newException(EOS, osErrorMsg(lastError)))
+          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
         else:
           result = false # We still want this callback to be called.
       elif res == 0:
@@ -224,10 +224,10 @@ proc setFilePos*(f: AsyncFile, pos: int64) =
   ## Sets the position of the file pointer that is used for read/write
   ## operations. The file's first byte has the index zero. 
   f.offset = pos
-  when not defined(windows):
+  when not defined(windows) and not defined(nimdoc):
     let ret = lseek(f.fd.cint, pos, SEEK_SET)
     if ret == -1:
-      raiseOSError()
+      raiseOSError(osLastError())
 
 proc readAll*(f: AsyncFile): Future[string] {.async.} =
   ## Reads all data from the specified file.
@@ -245,7 +245,7 @@ proc write*(f: AsyncFile, data: string): Future[void] =
   ## specified file.
   var retFuture = newFuture[void]("asyncfile.write")
   var copy = data
-  when defined(windows):
+  when defined(windows) or defined(nimdoc):
     var buffer = alloc0(data.len)
     copyMem(buffer, addr copy[0], data.len)
 
@@ -299,7 +299,7 @@ proc write*(f: AsyncFile, data: string): Future[void] =
       if res < 0:
         let lastError = osLastError()
         if lastError.int32 != EAGAIN:
-          retFuture.fail(newException(EOS, osErrorMsg(lastError)))
+          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
         else:
           result = false # We still want this callback to be called.
       else:
@@ -316,10 +316,10 @@ proc write*(f: AsyncFile, data: string): Future[void] =
 
 proc close*(f: AsyncFile) =
   ## Closes the file specified.
-  when defined(windows):
+  when defined(windows) or defined(nimdoc):
     if not closeHandle(f.fd.THandle).bool:
-      raiseOSError()
+      raiseOSError(osLastError())
   else:
     if close(f.fd.cint) == -1:
-      raiseOSError()
+      raiseOSError(osLastError())
 
diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim
index fc38dc31a..daf69d59f 100644
--- a/lib/pure/asyncftpclient.nim
+++ b/lib/pure/asyncftpclient.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
@@ -61,8 +61,8 @@ proc pasv(ftp: AsyncFtpClient) {.async.} =
   assertReply(pasvMsg, "227")
   var betweenParens = captureBetween(pasvMsg.string, '(', ')')
   var nums = betweenParens.split(',')
-  var ip = nums[0.. -3]
-  var port = nums[-2.. -1]
+  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("."), Port(properPort.toU16))
   ftp.dsockConnected = true
@@ -149,7 +149,7 @@ proc createDir*(ftp: AsyncFtpClient, dir: string, recursive = false){.async.} =
     assertReply reply, "257"
 
 proc chmod*(ftp: AsyncFtpClient, path: string,
-            permissions: set[TFilePermission]) {.async.} =
+            permissions: set[FilePermission]) {.async.} =
   ## Changes permission of ``path`` to ``permissions``.
   var userOctal = 0
   var groupOctal = 0
@@ -188,7 +188,7 @@ proc retrText*(ftp: AsyncFtpClient, file: string): Future[string] {.async.} =
 
   result = await ftp.getLines()
 
-proc getFile(ftp: AsyncFtpClient, file: TFile, total: BiggestInt,
+proc getFile(ftp: AsyncFtpClient, file: File, total: BiggestInt,
              onProgressChanged: ProgressChangedProc) {.async.} =
   assert ftp.dsockConnected
   var progress = 0
@@ -240,7 +240,7 @@ proc retrFile*(ftp: AsyncFtpClient, file, dest: string,
 
   await getFile(ftp, destFile, fileSize, onProgressChanged)
 
-proc doUpload(ftp: AsyncFtpClient, file: TFile,
+proc doUpload(ftp: AsyncFtpClient, file: File,
               onProgressChanged: ProgressChangedProc) {.async.} =
   assert ftp.dsockConnected
 
@@ -300,7 +300,7 @@ proc newAsyncFtpClient*(address: string, port = Port(21),
   result.dsockConnected = false
   result.csock = newAsyncSocket()
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
   proc main(ftp: AsyncFtpClient) {.async.} =
     await ftp.connect()
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index 0b18e6bcc..279cedb5d 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -17,12 +17,13 @@
 ## as the response body.
 ##
 ## .. code-block::nim
+##    import asynchttpserver, asyncdispatch
+##
 ##    var server = newAsyncHttpServer()
 ##    proc cb(req: Request) {.async.} =
 ##      await req.respond(Http200, "Hello World")
 ##
-##    asyncCheck server.serve(Port(8080), cb)
-##    runForever()
+##    waitFor server.serve(Port(8080), cb)
 
 import strtabs, asyncnet, asyncdispatch, parseutils, uri, strutils
 type
@@ -107,22 +108,19 @@ proc sendHeaders*(req: Request, headers: StringTableRef): Future[void] =
   addHeaders(msg, headers)
   return req.client.send(msg)
 
-proc respond*(req: Request, code: HttpCode,
-        content: string, headers = newStringTable()) {.async.} =
+proc respond*(req: Request, code: HttpCode, content: string,
+              headers: StringTableRef = nil): Future[void] =
   ## Responds to the request with the specified ``HttpCode``, headers and
   ## content.
   ##
   ## This procedure will **not** close the client socket.
-  var customHeaders = headers
-  customHeaders["Content-Length"] = $content.len
   var msg = "HTTP/1.1 " & $code & "\c\L"
-  msg.addHeaders(customHeaders)
-  await req.client.send(msg & "\c\L" & content)
 
-proc newRequest(): Request =
-  result.headers = newStringTable(modeCaseInsensitive)
-  result.hostname = ""
-  result.body = ""
+  if headers != nil:
+    msg.addHeaders(headers)
+  msg.add("Content-Length: " & $content.len & "\c\L\c\L")
+  msg.add(content)
+  result = req.client.send(msg)
 
 proc parseHeader(line: string): tuple[key, value: string] =
   var i = 0
@@ -147,59 +145,65 @@ proc sendStatus(client: AsyncSocket, status: string): Future[void] =
 proc processClient(client: AsyncSocket, address: string,
                    callback: proc (request: Request):
                       Future[void] {.closure, gcsafe.}) {.async.} =
+  var request: Request
+  request.url = initUri()
+  request.headers = newStringTable(modeCaseInsensitive)
+  var line = newStringOfCap(80)
+  var key, value = ""
+
   while not client.isClosed:
     # GET /path HTTP/1.1
     # Header: val
     # \n
-    var request = newRequest()
-    request.hostname = address
+    request.headers.clear(modeCaseInsensitive)
+    request.hostname.shallowCopy(address)
     assert client != nil
     request.client = client
 
     # First line - GET /path HTTP/1.1
-    let line = await client.recvLine() # TODO: Timeouts.
+    line.setLen(0)
+    await client.recvLineInto(addr line) # TODO: Timeouts.
     if line == "":
       client.close()
       return
-    let lineParts = line.split(' ')
-    if lineParts.len != 3:
-      await request.respond(Http400, "Invalid request. Got: " & line)
-      continue
 
-    let reqMethod = lineParts[0]
-    let path = lineParts[1]
-    let protocol = lineParts[2]
+    var i = 0
+    for linePart in line.split(' '):
+      case i
+      of 0: request.reqMethod.shallowCopy(linePart.normalize)
+      of 1: parseUri(linePart, request.url)
+      of 2:
+        try:
+          request.protocol = parseProtocol(linePart)
+        except ValueError:
+          asyncCheck request.respond(Http400,
+            "Invalid request protocol. Got: " & linePart)
+          continue
+      else:
+        await request.respond(Http400, "Invalid request. Got: " & line)
+        continue
+      inc i
 
     # Headers
-    var i = 0
     while true:
       i = 0
-      let headerLine = await client.recvLine()
-      if headerLine == "":
-        client.close(); return
-      if headerLine == "\c\L": break
-      # TODO: Compiler crash
-      #let (key, value) = parseHeader(headerLine)
-      let kv = parseHeader(headerLine)
-      request.headers[kv.key] = kv.value
+      line.setLen(0)
+      await client.recvLineInto(addr line)
 
-    request.reqMethod = reqMethod
-    request.url = parseUri(path)
-    try:
-      request.protocol = protocol.parseProtocol()
-    except ValueError:
-      asyncCheck request.respond(Http400, "Invalid request protocol. Got: " &
-          protocol)
-      continue
+      if line == "":
+        client.close(); return
+      if line == "\c\L": break
+      let (key, value) = parseHeader(line)
+      request.headers[key] = value
 
-    if reqMethod.normalize == "post":
+    if request.reqMethod == "post":
       # Check for Expect header
       if request.headers.hasKey("Expect"):
         if request.headers["Expect"].toLower == "100-continue":
           await client.sendStatus("100 Continue")
         else:
           await client.sendStatus("417 Expectation Failed")
-    
+
       # Read the body
       # - Check for Content-length header
       if request.headers.hasKey("Content-Length"):
@@ -213,11 +217,11 @@ proc processClient(client: AsyncSocket, address: string,
         await request.respond(Http400, "Bad Request. No Content-Length.")
         continue
 
-    case reqMethod.normalize
+    case request.reqMethod
     of "get", "post", "head", "put", "delete", "trace", "options", "connect", "patch":
       await callback(request)
     else:
-      await request.respond(Http400, "Invalid request method. Got: " & reqMethod)
+      await request.respond(Http400, "Invalid request method. Got: " & request.reqMethod)
 
     # Persistent connections
     if (request.protocol == HttpVer11 and
@@ -245,7 +249,7 @@ proc serve*(server: AsyncHttpServer, port: Port,
     server.socket.setSockOpt(OptReuseAddr, true)
   server.socket.bindAddr(port, address)
   server.socket.listen()
-  
+
   while true:
     # TODO: Causes compiler crash.
     #var (address, client) = await server.socket.acceptAddr()
@@ -258,7 +262,7 @@ proc close*(server: AsyncHttpServer) =
   ## Terminates the async http server instance.
   server.socket.close()
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   proc main =
     var server = newAsyncHttpServer()
     proc cb(req: Request) {.async.} =
diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim
index d40c3849e..6ae2c608b 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/pure/asyncio.nim
@@ -18,8 +18,8 @@ import sockets, os
 ## This module implements an asynchronous event loop together with asynchronous
 ## sockets which use this event loop.
 ## It is akin to Python's asyncore module. Many modules that use sockets
-## have an implementation for this module, those modules should all have a 
-## ``register`` function which you should use to add the desired objects to a 
+## have an implementation for this module, those modules should all have a
+## ``register`` function which you should use to add the desired objects to a
 ## dispatcher which you created so
 ## that you can receive the events associated with that module's object.
 ##
@@ -27,19 +27,19 @@ import sockets, os
 ## function in a while loop.
 ##
 ## **Note:** Most modules have tasks which need to be ran regularly, this is
-## why you should not call ``poll`` with a infinite timeout, or even a 
+## why you should not call ``poll`` with a infinite timeout, or even a
 ## very long one. In most cases the default timeout is fine.
 ##
 ## **Note:** This module currently only supports select(), this is limited by
 ## FD_SETSIZE, which is usually 1024. So you may only be able to use 1024
 ## sockets at a time.
-## 
+##
 ## Most (if not all) modules that use asyncio provide a userArg which is passed
 ## on with the events. The type that you set userArg to must be inheriting from
 ## ``RootObj``!
 ##
-## **Note:** If you want to provide async ability to your module please do not 
-## use the ``Delegate`` object, instead use ``AsyncSocket``. It is possible 
+## **Note:** If you want to provide async ability to your module please do not
+## use the ``Delegate`` object, instead use ``AsyncSocket``. It is possible
 ## that in the future this type's fields will not be exported therefore breaking
 ## your code.
 ##
@@ -59,11 +59,11 @@ import sockets, os
 ## socket which will give you the client which is connecting. You should then
 ## set any events that you want to use on that client and add it to your dispatcher
 ## using the ``register`` procedure.
-## 
+##
 ## An example ``handleAccept`` follows:
-## 
+##
 ## .. code-block:: nim
-##   
+##
 ##    var disp = newDispatcher()
 ##    ...
 ##    proc handleAccept(s: AsyncSocket) =
@@ -74,7 +74,7 @@ import sockets, os
 ##      client.handleRead = ...
 ##      disp.register(client)
 ##    ...
-## 
+##
 ## For client sockets you should only be interested in the ``handleRead`` and
 ## ``handleConnect`` events. The former gets called whenever the socket has
 ## received messages and can be read from and the latter gets called whenever
@@ -83,14 +83,14 @@ import sockets, os
 ##
 ## Getting a blocking client from an AsyncSocket
 ## =============================================
-## 
+##
 ## If you need a asynchronous server socket but you wish to process the clients
 ## synchronously then you can use the ``getSocket`` converter to get
 ## a ``Socket`` from the ``AsyncSocket`` object, this can then be combined
 ## with ``accept`` like so:
 ##
 ## .. code-block:: nim
-##    
+##
 ##    proc handleAccept(s: AsyncSocket) =
 ##      var client: Socket
 ##      getSocket(s).accept(client)
@@ -113,11 +113,11 @@ type
     handleWrite*: proc (h: RootRef) {.nimcall, gcsafe.}
     handleError*: proc (h: RootRef) {.nimcall, gcsafe.}
     hasDataBuffered*: proc (h: RootRef): bool {.nimcall, gcsafe.}
-    
+
     open*: bool
     task*: proc (h: RootRef) {.nimcall, gcsafe.}
     mode*: FileMode
-    
+
   Delegate* = ref DelegateObj
 
   Dispatcher* = ref DispatcherObj
@@ -144,7 +144,7 @@ type
     deleg: Delegate
 
   SocketStatus* = enum
-    SockIdle, SockConnecting, SockConnected, SockListening, SockClosed, 
+    SockIdle, SockConnecting, SockConnected, SockListening, SockClosed,
     SockUDPBound
 
 {.deprecated: [TDelegate: DelegateObj, PDelegate: Delegate,
@@ -176,8 +176,8 @@ proc newAsyncSocket(): AsyncSocket =
   result.lineBuffer = "".TaintedString
   result.sendBuffer = ""
 
-proc asyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, 
-                  protocol: Protocol = IPPROTO_TCP, 
+proc asyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
+                  protocol: Protocol = IPPROTO_TCP,
                   buffered = true): AsyncSocket =
   ## Initialises an AsyncSocket object. If a socket cannot be initialised
   ## EOS is raised.
@@ -236,7 +236,7 @@ proc asyncSockHandleWrite(h: RootRef) =
     if AsyncSocket(h).socket.isSSL and not
          AsyncSocket(h).socket.gotHandshake:
       return
-  
+
   if AsyncSocket(h).info == SockConnecting:
     AsyncSocket(h).handleConnect(AsyncSocket(h))
     AsyncSocket(h).info = SockConnected
@@ -256,10 +256,10 @@ proc asyncSockHandleWrite(h: RootRef) =
           # do nothing instead.
           discard
         elif bytesSent != sock.sendBuffer.len:
-          sock.sendBuffer = sock.sendBuffer[bytesSent .. -1]
+          sock.sendBuffer = sock.sendBuffer[bytesSent .. ^1]
         elif bytesSent == sock.sendBuffer.len:
           sock.sendBuffer = ""
-        
+
         if AsyncSocket(h).handleWrite != nil:
           AsyncSocket(h).handleWrite(AsyncSocket(h))
       except OSError:
@@ -284,7 +284,7 @@ when defined(ssl):
       else:
         # handshake will set socket's ``sslNoHandshake`` field.
         discard AsyncSocket(h).socket.handshake()
-        
+
 
 proc asyncSockTask(h: RootRef) =
   when defined(ssl):
@@ -377,9 +377,9 @@ proc acceptAddr*(server: AsyncSocket, client: var AsyncSocket,
 
   if c == invalidSocket: raiseSocketError(server.socket)
   c.setBlocking(false) # TODO: Needs to be tested.
-  
+
   # deleg.open is set in ``toDelegate``.
-  
+
   client.socket = c
   client.lineBuffer = "".TaintedString
   client.sendBuffer = ""
@@ -393,7 +393,7 @@ proc accept*(server: AsyncSocket, client: var AsyncSocket) =
 proc acceptAddr*(server: AsyncSocket): tuple[sock: AsyncSocket,
                                               address: string] {.deprecated.} =
   ## Equivalent to ``sockets.acceptAddr``.
-  ## 
+  ##
   ## **Deprecated since version 0.9.0:** Please use the function above.
   var client = newAsyncSocket()
   var address: string = ""
@@ -441,17 +441,17 @@ proc isConnected*(s: AsyncSocket): bool =
   ## Determines whether ``s`` is connected.
   return s.info == SockConnected
 proc isListening*(s: AsyncSocket): bool =
-  ## Determines whether ``s`` is listening for incoming connections.  
+  ## Determines whether ``s`` is listening for incoming connections.
   return s.info == SockListening
 proc isConnecting*(s: AsyncSocket): bool =
-  ## Determines whether ``s`` is connecting.  
+  ## Determines whether ``s`` is connecting.
   return s.info == SockConnecting
 proc isClosed*(s: AsyncSocket): bool =
   ## Determines whether ``s`` has been closed.
   return s.info == SockClosed
 proc isSendDataBuffered*(s: AsyncSocket): bool =
   ## Determines whether ``s`` has data waiting to be sent, i.e. whether this
-  ## socket's sendBuffer contains data. 
+  ## socket's sendBuffer contains data.
   return s.sendBuffer.len != 0
 
 proc setHandleWrite*(s: AsyncSocket,
@@ -550,7 +550,7 @@ proc send*(sock: AsyncSocket, data: string) =
     sock.sendBuffer.add(data)
     sock.deleg.mode = fmReadWrite
   elif bytesSent != data.len:
-    sock.sendBuffer.add(data[bytesSent .. -1])
+    sock.sendBuffer.add(data[bytesSent .. ^1])
     sock.deleg.mode = fmReadWrite
 
 proc timeValFromMilliseconds(timeout = 500): Timeval =
@@ -561,10 +561,10 @@ proc timeValFromMilliseconds(timeout = 500): Timeval =
 
 proc createFdSet(fd: var TFdSet, s: seq[Delegate], m: var int) =
   FD_ZERO(fd)
-  for i in items(s): 
+  for i in items(s):
     m = max(m, int(i.fd))
     FD_SET(i.fd, fd)
-   
+
 proc pruneSocketSet(s: var seq[Delegate], fd: var TFdSet) =
   var i = 0
   var L = s.len
@@ -576,16 +576,16 @@ proc pruneSocketSet(s: var seq[Delegate], fd: var TFdSet) =
       inc(i)
   setLen(s, L)
 
-proc select(readfds, writefds, exceptfds: var seq[Delegate], 
+proc select(readfds, writefds, exceptfds: var seq[Delegate],
              timeout = 500): int =
   var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout)
-  
+
   var rd, wr, ex: TFdSet
   var m = 0
   createFdSet(rd, readfds, m)
   createFdSet(wr, writefds, m)
   createFdSet(ex, exceptfds, m)
-  
+
   if timeout != -1:
     result = int(select(cint(m+1), addr(rd), addr(wr), addr(ex), addr(tv)))
   else:
@@ -599,7 +599,7 @@ proc poll*(d: Dispatcher, timeout: int = 500): bool =
   ## This function checks for events on all the delegates in the `PDispatcher`.
   ## It then proceeds to call the correct event handler.
   ##
-  ## This function returns ``True`` if there are file descriptors that are still 
+  ## This function returns ``True`` if there are file descriptors that are still
   ## open, otherwise ``False``. File descriptors that have been
   ## closed are immediately removed from the dispatcher automatically.
   ##
@@ -611,7 +611,7 @@ proc poll*(d: Dispatcher, timeout: int = 500): bool =
   var readDg, writeDg, errorDg: seq[Delegate] = @[]
   var len = d.delegates.len
   var dc = 0
-  
+
   while dc < len:
     let deleg = d.delegates[dc]
     if (deleg.mode != fmWrite or deleg.mode != fmAppend) and deleg.open:
@@ -625,20 +625,20 @@ proc poll*(d: Dispatcher, timeout: int = 500): bool =
       # File/socket has been closed. Remove it from dispatcher.
       d.delegates[dc] = d.delegates[len-1]
       dec len
-      
+
   d.delegates.setLen(len)
-  
+
   var hasDataBufferedCount = 0
   for d in d.delegates:
     if d.hasDataBuffered(d.deleVal):
       hasDataBufferedCount.inc()
       d.handleRead(d.deleVal)
   if hasDataBufferedCount > 0: return true
-  
+
   if readDg.len() == 0 and writeDg.len() == 0:
     ## TODO: Perhaps this shouldn't return if errorDg has something?
     return false
-  
+
   if select(readDg, writeDg, errorDg, timeout) != 0:
     for i in 0..len(d.delegates)-1:
       if i > len(d.delegates)-1: break # One delegate might've been removed.
@@ -651,7 +651,7 @@ proc poll*(d: Dispatcher, timeout: int = 500): bool =
         deleg.handleWrite(deleg.deleVal)
       if deleg notin errorDg:
         deleg.handleError(deleg.deleVal)
-  
+
   # Execute tasks
   for i in items(d.delegates):
     i.task(i.deleVal)
@@ -660,11 +660,11 @@ proc len*(disp: Dispatcher): int =
   ## Retrieves the amount of delegates in ``disp``.
   return disp.delegates.len
 
-when isMainModule:
+when not defined(testing) and isMainModule:
 
   proc testConnect(s: AsyncSocket, no: int) =
     echo("Connected! " & $no)
-  
+
   proc testRead(s: AsyncSocket, no: int) =
     echo("Reading! " & $no)
     var data = ""
@@ -675,38 +675,38 @@ when isMainModule:
     echo(data)
     echo("Finished reading! " & $no)
 
-  proc testAccept(s: AsyncSocket, disp: PDispatcher, no: int) =
+  proc testAccept(s: AsyncSocket, disp: Dispatcher, no: int) =
     echo("Accepting client! " & $no)
     var client: AsyncSocket
     new(client)
     var address = ""
     s.acceptAddr(client, address)
     echo("Accepted ", address)
-    client.handleRead = 
+    client.handleRead =
       proc (s: AsyncSocket) =
         testRead(s, 2)
     disp.register(client)
 
   proc main =
     var d = newDispatcher()
-    
+
     var s = asyncSocket()
-    s.connect("amber.tenthbit.net", TPort(6667))
-    s.handleConnect = 
+    s.connect("amber.tenthbit.net", Port(6667))
+    s.handleConnect =
       proc (s: AsyncSocket) =
         testConnect(s, 1)
-    s.handleRead = 
+    s.handleRead =
       proc (s: AsyncSocket) =
         testRead(s, 1)
     d.register(s)
-    
+
     var server = asyncSocket()
     server.handleAccept =
-      proc (s: AsyncSocket) = 
+      proc (s: AsyncSocket) =
         testAccept(s, d, 78)
-    server.bindAddr(TPort(5555))
+    server.bindAddr(Port(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 76b2bc46c..aadbde824 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -24,7 +24,7 @@
 ##
 ## Chat server
 ## ^^^^^^^^^^^
-## 
+##
 ## The following example demonstrates a simple chat server.
 ##
 ## .. code-block::nim
@@ -182,26 +182,30 @@ proc connect*(socket: AsyncSocket, address: string, port: Port,
       sslSetConnectState(socket.sslHandle)
       sslLoop(socket, flags, sslDoHandshake(socket.sslHandle))
 
-proc readInto(buf: cstring, size: int, socket: AsyncSocket,
-              flags: set[SocketFlag]): Future[int] {.async.} =
+template readInto(buf: cstring, size: int, socket: AsyncSocket,
+                  flags: set[SocketFlag]): int =
+  ## Reads **up to** ``size`` bytes from ``socket`` into ``buf``. Note that
+  ## this is a template and not a proc.
+  var res = 0
   if socket.isSsl:
     when defined(ssl):
       # SSL mode.
       sslLoop(socket, flags,
         sslRead(socket.sslHandle, buf, size.cint))
-      result = opResult
+      res = opResult
   else:
-    var data = await recv(socket.fd.TAsyncFD, size, flags)
-    if data.len != 0:
-      copyMem(buf, addr data[0], data.len)
+    var recvIntoFut = recvInto(socket.fd.TAsyncFD, buf, size, flags)
+    yield recvIntoFut
     # Not in SSL mode.
-    result = data.len
+    res = recvIntoFut.read()
+  res
 
-proc readIntoBuf(socket: AsyncSocket,
-    flags: set[SocketFlag]): Future[int] {.async.} =
-  result = await readInto(addr socket.buffer[0], BufferSize, socket, flags)
+template readIntoBuf(socket: AsyncSocket,
+    flags: set[SocketFlag]): int =
+  var size = readInto(addr socket.buffer[0], BufferSize, socket, flags)
   socket.currPos = 0
-  socket.bufLen = result
+  socket.bufLen = size
+  size
 
 proc recv*(socket: AsyncSocket, size: int,
            flags = {SocketFlag.SafeDisconn}): Future[string] {.async.} =
@@ -222,10 +226,11 @@ proc recv*(socket: AsyncSocket, size: int,
   ## to be read then the future will complete with a value of ``""``.
   if socket.isBuffered:
     result = newString(size)
+    shallow(result)
     let originalBufPos = socket.currPos
 
     if socket.bufLen == 0:
-      let res = await socket.readIntoBuf(flags - {SocketFlag.Peek})
+      let res = socket.readIntoBuf(flags - {SocketFlag.Peek})
       if res == 0:
         result.setLen(0)
         return
@@ -236,7 +241,7 @@ proc recv*(socket: AsyncSocket, size: int,
         if SocketFlag.Peek in flags:
           # We don't want to get another buffer if we're peeking.
           break
-        let res = await socket.readIntoBuf(flags - {SocketFlag.Peek})
+        let res = socket.readIntoBuf(flags - {SocketFlag.Peek})
         if res == 0:
           break
 
@@ -251,7 +256,7 @@ proc recv*(socket: AsyncSocket, size: int,
     result.setLen(read)
   else:
     result = newString(size)
-    let read = await readInto(addr result[0], size, socket, flags)
+    let read = readInto(addr result[0], size, socket, flags)
     result.setLen(read)
 
 proc send*(socket: AsyncSocket, data: string,
@@ -302,15 +307,14 @@ proc accept*(socket: AsyncSocket,
         retFut.complete(future.read.client)
   return retFut
 
-proc recvLine*(socket: AsyncSocket,
-    flags = {SocketFlag.SafeDisconn}): Future[string] {.async.} =
-  ## Reads a line of data from ``socket``. Returned future will complete once
-  ## a full line is read or an error occurs.
+proc recvLineInto*(socket: AsyncSocket, resString: ptr string,
+    flags = {SocketFlag.SafeDisconn}) {.async.} =
+  ## Reads a line of data from ``socket`` into ``resString``.
   ##
   ## If a full line is read ``\r\L`` is not
   ## added to ``line``, however if solely ``\r\L`` is read then ``line``
   ## will be set to it.
-  ## 
+  ##
   ## If the socket is disconnected, ``line`` will be set to ``""``.
   ##
   ## If the socket is disconnected in the middle of a line (before ``\r\L``
@@ -318,27 +322,32 @@ proc recvLine*(socket: AsyncSocket,
   ## The partial line **will be lost**.
   ##
   ## **Warning**: The ``Peek`` flag is not yet implemented.
-  ## 
-  ## **Warning**: ``recvLine`` on unbuffered sockets assumes that the protocol
-  ## uses ``\r\L`` to delimit a new line.
-  template addNLIfEmpty(): stmt =
-    if result.len == 0:
-      result.add("\c\L")
+  ##
+  ## **Warning**: ``recvLineInto`` on unbuffered sockets assumes that the
+  ## protocol uses ``\r\L`` to delimit a new line.
+  ##
+  ## **Warning**: ``recvLineInto`` currently uses a raw pointer to a string for
+  ## performance reasons. This will likely change soon to use FutureVars.
   assert SocketFlag.Peek notin flags ## TODO:
+  result = newFuture[void]("asyncnet.recvLineInto")
+
+  template addNLIfEmpty(): stmt =
+    if resString[].len == 0:
+      resString[].add("\c\L")
+
   if socket.isBuffered:
-    result = ""
     if socket.bufLen == 0:
-      let res = await socket.readIntoBuf(flags)
+      let res = socket.readIntoBuf(flags)
       if res == 0:
         return
 
     var lastR = false
     while true:
       if socket.currPos >= socket.bufLen:
-        let res = await socket.readIntoBuf(flags)
+        let res = socket.readIntoBuf(flags)
         if res == 0:
-          result = ""
-          break
+          resString[].setLen(0)
+          return
 
       case socket.buffer[socket.currPos]
       of '\r':
@@ -353,24 +362,53 @@ proc recvLine*(socket: AsyncSocket,
           socket.currPos.inc()
           return
         else:
-          result.add socket.buffer[socket.currPos]
+          resString[].add socket.buffer[socket.currPos]
       socket.currPos.inc()
   else:
-    result = ""
     var c = ""
     while true:
-      c = await recv(socket, 1, flags)
+      let recvFut = recv(socket, 1, flags)
+      c = recvFut.read()
       if c.len == 0:
-        return ""
+        resString[].setLen(0)
+        return
       if c == "\r":
-        c = await recv(socket, 1, flags) # Skip \L
+        let recvFut = recv(socket, 1, flags) # Skip \L
+        c = recvFut.read()
         assert c == "\L"
         addNLIfEmpty()
         return
       elif c == "\L":
         addNLIfEmpty()
         return
-      add(result.string, c)
+      resString[].add c
+
+proc recvLine*(socket: AsyncSocket,
+    flags = {SocketFlag.SafeDisconn}): Future[string] {.async.} =
+  ## Reads a line of data from ``socket``. Returned future will complete once
+  ## a full line is read or an error occurs.
+  ##
+  ## If a full line is read ``\r\L`` is not
+  ## added to ``line``, however if solely ``\r\L`` is read then ``line``
+  ## will be set to it.
+  ##
+  ## If the socket is disconnected, ``line`` will be set to ``""``.
+  ##
+  ## If the socket is disconnected in the middle of a line (before ``\r\L``
+  ## is read) then line will be set to ``""``.
+  ## The partial line **will be lost**.
+  ##
+  ## **Warning**: The ``Peek`` flag is not yet implemented.
+  ##
+  ## **Warning**: ``recvLine`` on unbuffered sockets assumes that the protocol
+  ## uses ``\r\L`` to delimit a new line.
+  template addNLIfEmpty(): stmt =
+    if result.len == 0:
+      result.add("\c\L")
+  assert SocketFlag.Peek notin flags ## TODO:
+
+  result = ""
+  await socket.recvLineInto(addr result, flags)
 
 proc listen*(socket: AsyncSocket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} =
   ## Marks ``socket`` as accepting connections.
@@ -458,7 +496,7 @@ proc isClosed*(socket: AsyncSocket): bool =
   ## Determines whether the socket has been closed.
   return socket.closed
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   type
     TestCases = enum
       HighClient, LowClient, LowServer
@@ -500,11 +538,11 @@ when isMainModule:
         proc (future: Future[void]) =
           echo("Send")
           client.close()
-      
+
       var f = accept(sock)
       f.callback = onAccept
-      
+
     var f = accept(sock)
     f.callback = onAccept
   runForever()
-    
+
diff --git a/lib/pure/basic2d.nim b/lib/pure/basic2d.nim
index f2fc1566b..a344cd053 100644
--- a/lib/pure/basic2d.nim
+++ b/lib/pure/basic2d.nim
@@ -18,7 +18,7 @@ import strutils
 ##
 ## Quick start example:
 ##   
-##   # Create a matrix wich first rotates, then scales and at last translates
+##   # Create a matrix which first rotates, then scales and at last translates
 ##   
 ##   var m:TMatrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0)
 ##   
@@ -256,7 +256,7 @@ proc `$`* (t:TMatrix2d):string {.noInit.} =
 
 proc isUniform*(t:TMatrix2d,tol=1.0e-6):bool=
   ## Checks if the transform is uniform, that is 
-  ## perpendicular axes of equal lenght, which means (for example)
+  ## perpendicular axes of equal length, which means (for example)
   ## it cannot transform a circle into an ellipse.
   ## `tol` is used as tolerance for both equal length comparison 
   ## and perp. comparison.
@@ -305,7 +305,7 @@ proc equals*(m1:TMatrix2d,m2:TMatrix2d,tol=1.0e-6):bool=
     abs(m1.ty-m2.ty)<=tol
     
 proc `=~`*(m1,m2:TMatrix2d):bool=
-  ## Checks if `m1`and `m2` is aproximately equal, using a
+  ## Checks if `m1`and `m2` is approximately equal, using a
   ## tolerance of 1e-6.
   equals(m1,m2)
 
diff --git a/lib/pure/basic3d.nim b/lib/pure/basic3d.nim
index c00764fc5..5a943dd05 100644
--- a/lib/pure/basic3d.nim
+++ b/lib/pure/basic3d.nim
@@ -16,33 +16,33 @@ import times
 ## Vectors are implemented as direction vectors, ie. when transformed with a matrix
 ## the translation part of matrix is ignored. The coordinate system used is
 ## right handed, because its compatible with 2d coordinate system (rotation around
-## zaxis equals 2d rotation). 
+## zaxis equals 2d rotation).
 ## Operators `+` , `-` , `*` , `/` , `+=` , `-=` , `*=` and `/=` are implemented
 ## for vectors and scalars.
 ##
 ##
 ## Quick start example:
-##   
-##   # Create a matrix wich first rotates, then scales and at last translates
-##   
+##
+##   # Create a matrix which first rotates, then scales and at last translates
+##
 ##   var m:TMatrix3d=rotate(PI,vector3d(1,1,2.5)) & scale(2.0) & move(100.0,200.0,300.0)
-##   
+##
 ##   # Create a 3d point at (100,150,200) and a vector (5,2,3)
-##   
-##   var pt:TPoint3d=point3d(100.0,150.0,200.0) 
-##   
+##
+##   var pt:TPoint3d=point3d(100.0,150.0,200.0)
+##
 ##   var vec:TVector3d=vector3d(5.0,2.0,3.0)
-##   
-##   
+##
+##
 ##   pt &= m # transforms pt in place
-##   
+##
 ##   var pt2:TPoint3d=pt & m #concatenates pt with m and returns a new point
-##   
+##
 ##   var vec2:TVector3d=vec & m #concatenates vec with m and returns a new vector
 
 
 
-type 
+type
   TMatrix3d* =object
     ## Implements a row major 3d matrix, which means
     ## transformations are applied the order they are concatenated.
@@ -53,12 +53,12 @@ type
     ## [ tx ty tz tw ]
     ax*,ay*,az*,aw*,  bx*,by*,bz*,bw*,  cx*,cy*,cz*,cw*,  tx*,ty*,tz*,tw*:float
   TPoint3d* = object
-    ## Implements a non-homegeneous 2d point stored as 
+    ## Implements a non-homegeneous 2d point stored as
     ## an `x` , `y` and `z` coordinate.
     x*,y*,z*:float
-  TVector3d* = object 
-    ## Implements a 3d **direction vector** stored as 
-    ## an `x` , `y` and `z` coordinate. Direction vector means, 
+  TVector3d* = object
+    ## Implements a 3d **direction vector** stored as
+    ## an `x` , `y` and `z` coordinate. Direction vector means,
     ## that when transforming a vector with a matrix, the translational
     ## part of the matrix is ignored.
     x*,y*,z*:float
@@ -67,7 +67,7 @@ type
 
 # Some forward declarations
 proc matrix3d*(ax,ay,az,aw,bx,by,bz,bw,cx,cy,cz,cw,tx,ty,tz,tw:float):TMatrix3d {.noInit.}
-  ## Creates a new 4x4 3d transformation matrix. 
+  ## Creates a new 4x4 3d transformation matrix.
   ## `ax` , `ay` , `az` is the local x axis.
   ## `bx` , `by` , `bz` is the local y axis.
   ## `cx` , `cy` , `cz` is the local z axis.
@@ -76,7 +76,7 @@ proc vector3d*(x,y,z:float):TVector3d {.noInit,inline.}
   ## Returns a new 3d vector (`x`,`y`,`z`)
 proc point3d*(x,y,z:float):TPoint3d {.noInit,inline.}
   ## Returns a new 4d point (`x`,`y`,`z`)
-proc tryNormalize*(v:var TVector3d):bool 
+proc tryNormalize*(v:var TVector3d):bool
   ## Modifies `v` to have a length of 1.0, keeping its angle.
   ## If `v` has zero length (and thus no angle), it is left unmodified and false is
   ## returned, otherwise true is returned.
@@ -85,7 +85,7 @@ proc tryNormalize*(v:var TVector3d):bool
 
 let
   IDMATRIX*:TMatrix3d=matrix3d(
-    1.0,0.0,0.0,0.0, 
+    1.0,0.0,0.0,0.0,
     0.0,1.0,0.0,0.0,
     0.0,0.0,1.0,0.0,
     0.0,0.0,0.0,1.0)
@@ -114,20 +114,20 @@ proc safeArccos(v:float):float=
   ## due to rounding issues
   return arccos(clamp(v,-1.0,1.0))
 
-template makeBinOpVector(s:expr)= 
+template makeBinOpVector(s:expr)=
   ## implements binary operators + , - , * and / for vectors
-  proc s*(a,b:TVector3d):TVector3d {.inline,noInit.} = 
+  proc s*(a,b:TVector3d):TVector3d {.inline,noInit.} =
     vector3d(s(a.x,b.x),s(a.y,b.y),s(a.z,b.z))
-  proc s*(a:TVector3d,b:float):TVector3d {.inline,noInit.}  = 
+  proc s*(a:TVector3d,b:float):TVector3d {.inline,noInit.}  =
     vector3d(s(a.x,b),s(a.y,b),s(a.z,b))
-  proc s*(a:float,b:TVector3d):TVector3d {.inline,noInit.}  = 
+  proc s*(a:float,b:TVector3d):TVector3d {.inline,noInit.}  =
     vector3d(s(a,b.x),s(a,b.y),s(a,b.z))
-  
-template makeBinOpAssignVector(s:expr)= 
+
+template makeBinOpAssignVector(s:expr)=
   ## implements inplace binary operators += , -= , /= and *= for vectors
-  proc s*(a:var TVector3d,b:TVector3d) {.inline.} = 
+  proc s*(a:var TVector3d,b:TVector3d) {.inline.} =
     s(a.x,b.x) ; s(a.y,b.y) ; s(a.z,b.z)
-  proc s*(a:var TVector3d,b:float) {.inline.} = 
+  proc s*(a:var TVector3d,b:float) {.inline.} =
     s(a.x,b) ; s(a.y,b) ; s(a.z,b)
 
 
@@ -188,20 +188,20 @@ proc scale*(s:float):TMatrix3d {.noInit.} =
 
 proc scale*(s:float,org:TPoint3d):TMatrix3d {.noInit.} =
   ## Returns a new scaling matrix using, `org` as scale origin.
-  result.setElements(s,0,0,0, 0,s,0,0, 0,0,s,0, 
+  result.setElements(s,0,0,0, 0,s,0,0, 0,0,s,0,
     org.x-s*org.x,org.y-s*org.y,org.z-s*org.z,1.0)
 
 proc stretch*(sx,sy,sz:float):TMatrix3d {.noInit.} =
   ## Returns new a stretch matrix, which is a
   ## scale matrix with non uniform scale in x,y and z.
   result.setElements(sx,0,0,0, 0,sy,0,0, 0,0,sz,0, 0,0,0,1)
-    
+
 proc stretch*(sx,sy,sz:float,org:TPoint3d):TMatrix3d {.noInit.} =
   ## Returns a new stretch matrix, which is a
   ## scale matrix with non uniform scale in x,y and z.
   ## `org` is used as stretch origin.
   result.setElements(sx,0,0,0, 0,sy,0,0, 0,0,sz,0, org.x-sx*org.x,org.y-sy*org.y,org.z-sz*org.z,1)
-    
+
 proc move*(dx,dy,dz:float):TMatrix3d {.noInit.} =
   ## Returns a new translation matrix.
   result.setElements(1,0,0,0, 0,1,0,0, 0,0,1,0, dx,dy,dz,1)
@@ -235,7 +235,7 @@ proc rotate*(angle:float,axis:TVector3d):TMatrix3d {.noInit.}=
     uvomc=normax.x*normax.y*omc
     uwomc=normax.x*normax.z*omc
     vwomc=normax.y*normax.z*omc
-    
+
   result.setElements(
     u2+(1.0-u2)*cs, uvomc+wsi, uwomc-vsi, 0.0,
     uvomc-wsi, v2+(1.0-v2)*cs, vwomc+usi, 0.0,
@@ -248,11 +248,11 @@ proc rotate*(angle:float,org:TPoint3d,axis:TVector3d):TMatrix3d {.noInit.}=
 
   # see PDF document http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.pdf
   # for how this is computed
-  
+
   var normax=axis
   if not normax.tryNormalize: #simplifies matrix computation below a lot
     raise newException(DivByZeroError,"Cannot rotate around zero length axis")
-  
+
   let
     u=normax.x
     v=normax.y
@@ -272,7 +272,7 @@ proc rotate*(angle:float,org:TPoint3d,axis:TVector3d):TMatrix3d {.noInit.}=
     uvomc=normax.x*normax.y*omc
     uwomc=normax.x*normax.z*omc
     vwomc=normax.y*normax.z*omc
-    
+
   result.setElements(
     u2+(v2+w2)*cs, uvomc+wsi, uwomc-vsi, 0.0,
     uvomc-wsi, v2+(u2+w2)*cs, vwomc+usi, 0.0,
@@ -305,7 +305,7 @@ proc rotateY*(angle:float):TMatrix3d {.noInit.}=
     0,1,0,0,
     s,0,c,0,
     0,0,0,1)
-    
+
 proc rotateZ*(angle:float):TMatrix3d {.noInit.}=
   ## Creates a matrix that rotates around the z-axis with `angle` radians,
   ## which is also called a 'yaw' matrix.
@@ -317,19 +317,19 @@ proc rotateZ*(angle:float):TMatrix3d {.noInit.}=
     -s,c,0,0,
     0,0,1,0,
     0,0,0,1)
-    
+
 proc isUniform*(m:TMatrix3d,tol=1.0e-6):bool=
-  ## Checks if the transform is uniform, that is 
-  ## perpendicular axes of equal lenght, which means (for example)
+  ## Checks if the transform is uniform, that is
+  ## perpendicular axes of equal length, which means (for example)
   ## it cannot transform a sphere into an ellipsoid.
-  ## `tol` is used as tolerance for both equal length comparison 
+  ## `tol` is used as tolerance for both equal length comparison
   ## and perpendicular comparison.
-  
+
   #dot product=0 means perpendicular coord. system, check xaxis vs yaxis and  xaxis vs zaxis
   if abs(m.ax*m.bx+m.ay*m.by+m.az*m.bz)<=tol and # x vs y
     abs(m.ax*m.cx+m.ay*m.cy+m.az*m.cz)<=tol and #x vs z
     abs(m.bx*m.cx+m.by*m.cy+m.bz*m.cz)<=tol: #y vs z
-    
+
     #subtract squared lengths of axes to check if uniform scaling:
     let
       sqxlen=(m.ax*m.ax+m.ay*m.ay+m.az*m.az)
@@ -340,16 +340,16 @@ proc isUniform*(m:TMatrix3d,tol=1.0e-6):bool=
   return false
 
 
-    
+
 proc mirror*(planeperp:TVector3d):TMatrix3d {.noInit.}=
   ## Creates a matrix that mirrors over the plane that has `planeperp` as normal,
   ## and passes through origo. `planeperp` does not need to be normalized.
-  
+
   # https://en.wikipedia.org/wiki/Transformation_matrix
   var n=planeperp
   if not n.tryNormalize:
     raise newException(DivByZeroError,"Cannot mirror over a plane with a zero length normal")
-  
+
   let
     a=n.x
     b=n.y
@@ -357,7 +357,7 @@ proc mirror*(planeperp:TVector3d):TMatrix3d {.noInit.}=
     ab=a*b
     ac=a*c
     bc=b*c
-  
+
   result.setElements(
     1-2*a*a , -2*ab,-2*ac,0,
     -2*ab , 1-2*b*b, -2*bc, 0,
@@ -376,7 +376,7 @@ proc mirror*(org:TPoint3d,planeperp:TVector3d):TMatrix3d {.noInit.}=
   var n=planeperp
   if not n.tryNormalize:
     raise newException(DivByZeroError,"Cannot mirror over a plane with a zero length normal")
-  
+
   let
     a=n.x
     b=n.y
@@ -390,7 +390,7 @@ proc mirror*(org:TPoint3d,planeperp:TVector3d):TMatrix3d {.noInit.}=
     tx=org.x
     ty=org.y
     tz=org.z
-  
+
   result.setElements(
     1-2*aa , -2*ab,-2*ac,0,
     -2*ab , 1-2*bb, -2*bc, 0,
@@ -402,8 +402,8 @@ proc mirror*(org:TPoint3d,planeperp:TVector3d):TMatrix3d {.noInit.}=
 
 proc determinant*(m:TMatrix3d):float=
   ## Computes the determinant of matrix `m`.
-  
-  # This computation is gotten from ratsimp(optimize(determinant(m))) 
+
+  # This computation is gotten from ratsimp(optimize(determinant(m)))
   # in maxima CAS
   let
     O1=m.cx*m.tw-m.cw*m.tx
@@ -423,10 +423,10 @@ proc inverse*(m:TMatrix3d):TMatrix3d {.noInit.}=
   ## Computes the inverse of matrix `m`. If the matrix
   ## determinant is zero, thus not invertible, a EDivByZero
   ## will be raised.
-  
+
   # this computation comes from optimize(invert(m)) in maxima CAS
-  
-  let 
+
+  let
     det=m.determinant
     O2=m.cy*m.tw-m.cw*m.ty
     O3=m.cz*m.tw-m.cw*m.tz
@@ -464,7 +464,7 @@ proc inverse*(m:TMatrix3d):TMatrix3d {.noInit.}=
 proc equals*(m1:TMatrix3d,m2:TMatrix3d,tol=1.0e-6):bool=
   ## Checks if all elements of `m1`and `m2` is equal within
   ## a given tolerance `tol`.
-  return 
+  return
     abs(m1.ax-m2.ax)<=tol and
     abs(m1.ay-m2.ay)<=tol and
     abs(m1.az-m2.az)<=tol and
@@ -483,14 +483,14 @@ proc equals*(m1:TMatrix3d,m2:TMatrix3d,tol=1.0e-6):bool=
     abs(m1.tw-m2.tw)<=tol
 
 proc `=~`*(m1,m2:TMatrix3d):bool=
-  ## Checks if `m1` and `m2` is aproximately equal, using a
+  ## Checks if `m1` and `m2` is approximately equal, using a
   ## tolerance of 1e-6.
   equals(m1,m2)
-  
+
 proc transpose*(m:TMatrix3d):TMatrix3d {.noInit.}=
   ## Returns the transpose of `m`
   result.setElements(m.ax,m.bx,m.cx,m.tx,m.ay,m.by,m.cy,m.ty,m.az,m.bz,m.cz,m.tz,m.aw,m.bw,m.cw,m.tw)
-  
+
 proc getXAxis*(m:TMatrix3d):TVector3d {.noInit.}=
   ## Gets the local x axis of `m`
   result.x=m.ax
@@ -509,26 +509,26 @@ proc getZAxis*(m:TMatrix3d):TVector3d {.noInit.}=
   result.y=m.cy
   result.z=m.cz
 
-    
+
 proc `$`*(m:TMatrix3d):string=
   ## String representation of `m`
-  return rtos(m.ax) & "," & rtos(m.ay) & "," &rtos(m.az) & "," & rtos(m.aw) &
-    "\n" & rtos(m.bx) & "," & rtos(m.by) & "," &rtos(m.bz) & "," & rtos(m.bw) &
-    "\n" & rtos(m.cx) & "," & rtos(m.cy) & "," &rtos(m.cz) & "," & rtos(m.cw) &
-    "\n" & rtos(m.tx) & "," & rtos(m.ty) & "," &rtos(m.tz) & "," & rtos(m.tw)
-    
+  return rtos(m.ax) & "," & rtos(m.ay) & "," & rtos(m.az) & "," & rtos(m.aw) &
+    "\n" & rtos(m.bx) & "," & rtos(m.by) & "," & rtos(m.bz) & "," & rtos(m.bw) &
+    "\n" & rtos(m.cx) & "," & rtos(m.cy) & "," & rtos(m.cz) & "," & rtos(m.cw) &
+    "\n" & rtos(m.tx) & "," & rtos(m.ty) & "," & rtos(m.tz) & "," & rtos(m.tw)
+
 proc apply*(m:TMatrix3d, x,y,z:var float, translate=false)=
   ## Applies transformation `m` onto `x` , `y` , `z` , optionally
   ## using the translation part of the matrix.
-  let 
+  let
     oldx=x
     oldy=y
     oldz=z
-    
+
   x=m.cx*oldz+m.bx*oldy+m.ax*oldx
   y=m.cy*oldz+m.by*oldy+m.ay*oldx
   z=m.cz*oldz+m.bz*oldy+m.az*oldx
-    
+
   if translate:
     x+=m.tx
     y+=m.ty
@@ -552,13 +552,13 @@ proc `len=`*(v:var TVector3d,newlen:float) {.noInit.} =
   ## an arbitrary vector of the requested length is returned.
 
   let fac=newlen/v.len
-  
+
   if newlen==0.0:
     v.x=0.0
     v.y=0.0
     v.z=0.0
     return
-  
+
   if fac==Inf or fac==NegInf:
     #to short for float accuracy
     #do as good as possible:
@@ -588,7 +588,7 @@ proc `&` *(v:TVector3d,m:TMatrix3d):TVector3d {.noInit.} =
   ## Concatenate vector `v` with a transformation matrix.
   ## Transforming a vector ignores the translational part
   ## of the matrix.
-  
+
   #               | AX AY AZ AW |
   # | X Y Z 1 | * | BX BY BZ BW |
   #               | CX CY CZ CW |
@@ -605,12 +605,12 @@ proc `&=` *(v:var TVector3d,m:TMatrix3d) {.noInit.} =
   ## Applies transformation `m` onto `v` in place.
   ## Transforming a vector ignores the translational part
   ## of the matrix.
-  
+
   #               | AX AY AZ AW |
   # | X Y Z 1 | * | BX BY BZ BW |
   #               | CX CY CZ CW |
   #               | 0  0  0  1  |
-  
+
   let
     newx=m.cx*v.z+m.bx*v.y+m.ax*v.x
     newy=m.cy*v.z+m.by*v.y+m.ay*v.x
@@ -620,38 +620,38 @@ proc `&=` *(v:var TVector3d,m:TMatrix3d) {.noInit.} =
 
 proc transformNorm*(v:var TVector3d,m:TMatrix3d)=
   ## Applies a normal direction transformation `m` onto `v` in place.
-  ## The resulting vector is *not* normalized.  Transforming a vector ignores the 
-  ## translational part of the matrix. If the matrix is not invertible 
+  ## The resulting vector is *not* normalized.  Transforming a vector ignores the
+  ## translational part of the matrix. If the matrix is not invertible
   ## (determinant=0), an EDivByZero will be raised.
 
   # transforming a normal is done by transforming
   # by the transpose of the inverse of the original matrix
-  
+
   # Major reason this simple function is here is that this function can be optimized in the future,
   # (possibly by hardware) as well as having a consistent API with the 2d version.
   v&=transpose(inverse(m))
-  
+
 proc transformInv*(v:var TVector3d,m:TMatrix3d)=
-  ## Applies the inverse of `m` on vector `v`. Transforming a vector ignores 
-  ## the translational part of the matrix.  Transforming a vector ignores the 
+  ## Applies the inverse of `m` on vector `v`. Transforming a vector ignores
+  ## the translational part of the matrix.  Transforming a vector ignores the
   ## translational part of the matrix.
   ## If the matrix is not invertible (determinant=0), an EDivByZero
   ## will be raised.
-  
+
   # Major reason this simple function is here is that this function can be optimized in the future,
   # (possibly by hardware) as well as having a consistent API with the 2d version.
   v&=m.inverse
- 
+
 proc transformNormInv*(vec:var TVector3d,m:TMatrix3d)=
   ## Applies an inverse normal direction transformation `m` onto `v` in place.
-  ## This is faster than creating an inverse 
-  ## matrix and transformNorm(...) it. Transforming a vector ignores the 
+  ## This is faster than creating an inverse
+  ## matrix and transformNorm(...) it. Transforming a vector ignores the
   ## translational part of the matrix.
-  
+
   # see vector2d:s equivalent for a deeper look how/why this works
   vec&=m.transpose
 
-proc tryNormalize*(v:var TVector3d):bool= 
+proc tryNormalize*(v:var TVector3d):bool=
   ## Modifies `v` to have a length of 1.0, keeping its angle.
   ## If `v` has zero length (and thus no angle), it is left unmodified and false is
   ## returned, otherwise true is returned.
@@ -663,26 +663,26 @@ proc tryNormalize*(v:var TVector3d):bool=
   v.x/=mag
   v.y/=mag
   v.z/=mag
-  
+
   return true
 
-proc normalize*(v:var TVector3d) {.inline.}= 
+proc normalize*(v:var TVector3d) {.inline.}=
   ## Modifies `v` to have a length of 1.0, keeping its angle.
   ## If  `v` has zero length, an EDivByZero will be raised.
   if not tryNormalize(v):
     raise newException(DivByZeroError,"Cannot normalize zero length vector")
 
 proc rotate*(vec:var TVector3d,angle:float,axis:TVector3d)=
-  ## Rotates `vec` in place, with `angle` radians over `axis`, which passes 
+  ## Rotates `vec` in place, with `angle` radians over `axis`, which passes
   ## through origo.
 
   # see PDF document http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.pdf
   # for how this is computed
-  
+
   var normax=axis
   if not normax.tryNormalize:
     raise newException(DivByZeroError,"Cannot rotate around zero length axis")
-  
+
   let
     cs=cos(angle)
     si=sin(angle)
@@ -694,11 +694,11 @@ proc rotate*(vec:var TVector3d,angle:float,axis:TVector3d)=
     y=vec.y
     z=vec.z
     uxyzomc=(u*x+v*y+w*z)*omc
-  
+
   vec.x=u*uxyzomc+x*cs+(v*z-w*y)*si
   vec.y=v*uxyzomc+y*cs+(w*x-u*z)*si
   vec.z=w*uxyzomc+z*cs+(u*y-v*x)*si
-  
+
 proc scale*(v:var TVector3d,s:float)=
   ## Scales the vector in place with factor `s`
   v.x*=s
@@ -713,12 +713,12 @@ proc stretch*(v:var TVector3d,sx,sy,sz:float)=
 
 proc mirror*(v:var TVector3d,planeperp:TVector3d)=
   ## Computes the mirrored vector of `v` over the plane
-  ## that has `planeperp` as normal direction. 
+  ## that has `planeperp` as normal direction.
   ## `planeperp` does not need to be normalized.
-  
+
   var n=planeperp
   n.normalize
-  
+
   let
     x=v.x
     y=v.y
@@ -729,7 +729,7 @@ proc mirror*(v:var TVector3d,planeperp:TVector3d)=
     ac=a*c
     ab=a*b
     bc=b*c
-  
+
   v.x= -2*(ac*z+ab*y+a*a*x)+x
   v.y= -2*(bc*z+b*b*y+ab*x)+y
   v.z= -2*(c*c*z+bc*y+ac*x)+z
@@ -740,7 +740,7 @@ proc `-` *(v:TVector3d):TVector3d=
   result.x= -v.x
   result.y= -v.y
   result.z= -v.z
-    
+
 # declare templated binary operators
 makeBinOpVector(`+`)
 makeBinOpVector(`-`)
@@ -752,7 +752,7 @@ makeBinOpAssignVector(`*=`)
 makeBinOpAssignVector(`/=`)
 
 proc dot*(v1,v2:TVector3d):float {.inline.}=
-  ## Computes the dot product of two vectors. 
+  ## Computes the dot product of two vectors.
   ## Returns 0.0 if the vectors are perpendicular.
   return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z
 
@@ -769,12 +769,12 @@ proc cross*(v1,v2:TVector3d):TVector3d {.inline.}=
 proc equals*(v1,v2:TVector3d,tol=1.0e-6):bool=
   ## Checks if two vectors approximately equals with a tolerance.
   return abs(v2.x-v1.x)<=tol and abs(v2.y-v1.y)<=tol and abs(v2.z-v1.z)<=tol
-  
+
 proc `=~` *(v1,v2:TVector3d):bool=
-  ## Checks if two vectors approximately equals with a 
+  ## Checks if two vectors approximately equals with a
   ## hardcoded tolerance 1e-6
   equals(v1,v2)
-  
+
 proc angleTo*(v1,v2:TVector3d):float=
   ## Returns the smallest angle between v1 and v2,
   ## which is in range 0-PI
@@ -788,7 +788,7 @@ proc angleTo*(v1,v2:TVector3d):float=
 proc arbitraryAxis*(norm:TVector3d):TMatrix3d {.noInit.}=
   ## Computes the rotation matrix that would transform
   ## world z vector into `norm`. The inverse of this matrix
-  ## is useful to tranform a planar 3d object to 2d space.
+  ## is useful to transform a planar 3d object to 2d space.
   ## This is the same algorithm used to interpret DXF and DWG files.
   const lim=1.0/64.0
   var ax,ay,az:TVector3d
@@ -801,7 +801,7 @@ proc arbitraryAxis*(norm:TVector3d):TMatrix3d {.noInit.}=
   ay=cross(norm,ax)
   ay.normalize()
   az=cross(ax,ay)
-  
+
   result.setElements(
     ax.x,ax.y,ax.z,0.0,
     ay.x,ay.y,ay.z,0.0,
@@ -811,20 +811,20 @@ proc arbitraryAxis*(norm:TVector3d):TMatrix3d {.noInit.}=
 proc bisect*(v1,v2:TVector3d):TVector3d {.noInit.}=
   ## Computes the bisector between v1 and v2 as a normalized vector.
   ## If one of the input vectors has zero length, a normalized version
-  ## of the other is returned. If both input vectors has zero length, 
-  ## an arbitrary normalized vector `v1`is returned.
+  ## of the other is returned. If both input vectors has zero length,
+  ## an arbitrary normalized vector `v1` is returned.
   var
     vmag1=v1.len
     vmag2=v2.len
-    
-  # zero length vector equals arbitrary vector, just change 
+
+  # zero length vector equals arbitrary vector, just change
   # magnitude to one to avoid zero division
-  if vmag1==0.0: 
+  if vmag1==0.0:
     if vmag2==0: #both are zero length return any normalized vector
       return XAXIS
     vmag1=1.0
-  if vmag2==0.0: vmag2=1.0    
-    
+  if vmag2==0.0: vmag2=1.0
+
   let
     x1=v1.x/vmag1
     y1=v1.y/vmag1
@@ -832,14 +832,14 @@ proc bisect*(v1,v2:TVector3d):TVector3d {.noInit.}=
     x2=v2.x/vmag2
     y2=v2.y/vmag2
     z2=v2.z/vmag2
-    
+
   result.x=(x1 + x2) * 0.5
   result.y=(y1 + y2) * 0.5
   result.z=(z1 + z2) * 0.5
-  
+
   if not result.tryNormalize():
     # This can happen if vectors are colinear. In this special case
-    # there are actually inifinitely many bisectors, we select just 
+    # there are actually inifinitely many bisectors, we select just
     # one of them.
     result=v1.cross(XAXIS)
     if result.sqrLen<1.0e-9:
@@ -857,14 +857,14 @@ proc point3d*(x,y,z:float):TPoint3d=
   result.x=x
   result.y=y
   result.z=z
- 
+
 proc sqrDist*(a,b:TPoint3d):float=
   ## Computes the squared distance between `a`and `b`
   let dx=b.x-a.x
   let dy=b.y-a.y
   let dz=b.z-a.z
   result=dx*dx+dy*dy+dz*dz
-  
+
 proc dist*(a,b:TPoint3d):float {.inline.}=
   ## Computes the absolute distance between `a`and `b`
   result=sqrt(sqrDist(a,b))
@@ -876,7 +876,7 @@ proc `$` *(p:TPoint3d):string=
   result.add(rtos(p.y))
   result.add(",")
   result.add(rtos(p.z))
-  
+
 proc `&`*(p:TPoint3d,m:TMatrix3d):TPoint3d=
   ## Concatenates a point `p` with a transform `m`,
   ## resulting in a new, transformed point.
@@ -893,18 +893,18 @@ proc `&=` *(p:var TPoint3d,m:TMatrix3d)=
   p.x=m.cx*z+m.bx*y+m.ax*x+m.tx
   p.y=m.cy*z+m.by*y+m.ay*x+m.ty
   p.z=m.cz*z+m.bz*y+m.az*x+m.tz
-    
+
 proc transformInv*(p:var TPoint3d,m:TMatrix3d)=
   ## Applies the inverse of transformation `m` onto `p` in place.
   ## If the matrix is not invertable (determinant=0) , EDivByZero will
   ## be raised.
-  
+
   # can possibly be more optimized in the future so use this function when possible
   p&=inverse(m)
 
 
 proc `+`*(p:TPoint3d,v:TVector3d):TPoint3d {.noInit,inline.} =
-  ## Adds a vector `v` to a point `p`, resulting 
+  ## Adds a vector `v` to a point `p`, resulting
   ## in a new point.
   result.x=p.x+v.x
   result.y=p.y+v.y
@@ -917,7 +917,7 @@ proc `+=`*(p:var TPoint3d,v:TVector3d) {.noInit,inline.} =
   p.z+=v.z
 
 proc `-`*(p:TPoint3d,v:TVector3d):TPoint3d {.noInit,inline.} =
-  ## Subtracts a vector `v` from a point `p`, resulting 
+  ## Subtracts a vector `v` from a point `p`, resulting
   ## in a new point.
   result.x=p.x-v.x
   result.y=p.y-v.y
@@ -933,37 +933,37 @@ proc `-=`*(p:var TPoint3d,v:TVector3d) {.noInit,inline.} =
   ## Subtracts a vector `v` from a point `p` in place.
   p.x-=v.x
   p.y-=v.y
-  p.z-=v.z  
+  p.z-=v.z
 
 proc equals(p1,p2:TPoint3d,tol=1.0e-6):bool {.inline.}=
   ## Checks if two points approximately equals with a tolerance.
   return abs(p2.x-p1.x)<=tol and abs(p2.y-p1.y)<=tol and abs(p2.z-p1.z)<=tol
 
 proc `=~`*(p1,p2:TPoint3d):bool {.inline.}=
-  ## Checks if two vectors approximately equals with a 
+  ## Checks if two vectors approximately equals with a
   ## hardcoded tolerance 1e-6
   equals(p1,p2)
 
 proc rotate*(p:var TPoint3d,rad:float,axis:TVector3d)=
-  ## Rotates point `p` in place `rad` radians about an axis 
+  ## Rotates point `p` in place `rad` radians about an axis
   ## passing through origo.
-  
+
   var v=vector3d(p.x,p.y,p.z)
   v.rotate(rad,axis) # reuse this code here since doing the same thing and quite complicated
   p.x=v.x
   p.y=v.y
   p.z=v.z
-    
+
 proc rotate*(p:var TPoint3d,angle:float,org:TPoint3d,axis:TVector3d)=
-  ## Rotates point `p` in place `rad` radians about an axis 
+  ## Rotates point `p` in place `rad` radians about an axis
   ## passing through `org`
-  
+
   # see PDF document http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.pdf
   # for how this is computed
-  
+
   var normax=axis
   normax.normalize
-  
+
   let
     cs=cos(angle)
     omc=1.0-cs
@@ -987,17 +987,17 @@ proc rotate*(p:var TPoint3d,angle:float,org:TPoint3d,axis:TVector3d)=
     bv=b*v
     cw=c*w
     uxmvymwz=ux-vy-wz
-    
+
   p.x=(a*(vv+ww)-u*(bv+cw-uxmvymwz))*omc + x*cs + (b*w+v*z-c*v-w*y)*si
   p.y=(b*(uu+ww)-v*(au+cw-uxmvymwz))*omc + y*cs + (c*u-a*w+w*x-u*z)*si
   p.z=(c*(uu+vv)-w*(au+bv-uxmvymwz))*omc + z*cs + (a*v+u*y-b*u-v*x)*si
-  
+
 proc scale*(p:var TPoint3d,fac:float) {.inline.}=
   ## Scales a point in place `fac` times with world origo as origin.
   p.x*=fac
   p.y*=fac
   p.z*=fac
-  
+
 proc scale*(p:var TPoint3d,fac:float,org:TPoint3d){.inline.}=
   ## Scales the point in place `fac` times with `org` as origin.
   p.x=(p.x - org.x) * fac + org.x
@@ -1005,7 +1005,7 @@ proc scale*(p:var TPoint3d,fac:float,org:TPoint3d){.inline.}=
   p.z=(p.z - org.z) * fac + org.z
 
 proc stretch*(p:var TPoint3d,facx,facy,facz:float){.inline.}=
-  ## Scales a point in place non uniformly `facx` , `facy` , `facz` times 
+  ## Scales a point in place non uniformly `facx` , `facy` , `facz` times
   ## with world origo as origin.
   p.x*=facx
   p.y*=facy
@@ -1017,7 +1017,7 @@ proc stretch*(p:var TPoint3d,facx,facy,facz:float,org:TPoint3d){.inline.}=
   p.x=(p.x - org.x) * facx + org.x
   p.y=(p.y - org.y) * facy + org.y
   p.z=(p.z - org.z) * facz + org.z
-  
+
 
 proc move*(p:var TPoint3d,dx,dy,dz:float){.inline.}=
   ## Translates a point `dx` , `dy` , `dz` in place.
@@ -1033,7 +1033,7 @@ proc move*(p:var TPoint3d,v:TVector3d){.inline.}=
 
 proc area*(a,b,c:TPoint3d):float {.inline.}=
   ## Computes the area of the triangle thru points `a` , `b` and `c`
-  
+
   # The area of a planar 3d quadliteral is the magnitude of the cross
   # product of two edge vectors. Taking this time 0.5 gives the triangle area.
   return cross(b-a,c-a).len*0.5
diff --git a/lib/pure/browsers.nim b/lib/pure/browsers.nim
index 52035ee48..c6a603318 100644
--- a/lib/pure/browsers.nim
+++ b/lib/pure/browsers.nim
@@ -42,7 +42,7 @@ proc openDefaultBrowser*(url: string) =
     for b in getEnv("BROWSER").string.split(PathSep):
       try:
         # we use ``startProcess`` here because we don't want to block!
-        discard startProcess(command=b, args=[url], options={poUseShell})
+        discard startProcess(command=b, args=[url], options={poUsePath})
         return
       except OSError:
         discard
diff --git a/lib/pure/collections/LockFreeHash.nim b/lib/pure/collections/LockFreeHash.nim
index 5640838b1..0df97c685 100644
--- a/lib/pure/collections/LockFreeHash.nim
+++ b/lib/pure/collections/LockFreeHash.nim
@@ -404,7 +404,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
     #echo("tomb old slot then set in new table") 
     nextTable = copySlotAndCheck(table,idx)
     return setVal(nextTable, key, val, expVal, match)
-  # Finaly ready to add new val to table
+  # Finally ready to add new val to table
   while true:
     if match and oldVal != expVal:
       #echo("set failed, no match  oldVal= " & $oldVal & " expVal= " & $expVal)
@@ -525,7 +525,7 @@ proc get*[K,V](table: var PConcTable[K,V], key: var K): V =
 
 
 #Tests ----------------------------
-when isMainModule:
+when not defined(testing) and isMainModule:
   import locks, times, mersenne
   
   const 
diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim
index 8f506409b..7e3f23851 100644
--- a/lib/pure/collections/critbits.nim
+++ b/lib/pure/collections/critbits.nim
@@ -12,7 +12,7 @@
 ## by Adam Langley.
 
 type
-  NodeObj[T] = object {.pure, final, acyclic.}
+  NodeObj[T] = object {.acyclic.}
     byte: int ## byte index of the difference
     otherbits: char
     case isLeaf: bool
@@ -23,11 +23,10 @@ type
         val: T
     
   Node[T] = ref NodeObj[T]
-  CritBitTree*[T] = object {.
-      pure, final.} ## The crit bit tree can either be used
-                    ## as a mapping from strings to
-                    ## some type ``T`` or as a set of
-                    ## strings if ``T`` is void.
+  CritBitTree*[T] = object ## The crit bit tree can either be used
+                           ## as a mapping from strings to
+                           ## some type ``T`` or as a set of
+                           ## strings if ``T`` is void.
     root: Node[T]
     count: int
 
@@ -175,7 +174,7 @@ proc excl*[T](c: var CritBitTree[T], key: string) =
 iterator leaves[T](n: Node[T]): Node[T] =
   if n != nil:
     # XXX actually we could compute the necessary stack size in advance:
-    # it's rougly log2(c.count).
+    # it's roughly log2(c.count).
     var stack = @[n]
     while stack.len > 0: 
       var it = stack.pop
@@ -287,18 +286,19 @@ proc `$`*[T](c: CritBitTree[T]): string =
     result.add("}")
 
 when isMainModule:
+  import sequtils
+
   var r: CritBitTree[void]
   r.incl "abc"
   r.incl "xyz"
   r.incl "def"
   r.incl "definition"
   r.incl "prefix"
+
   doAssert r.contains"def"
-  #r.del "def"
 
-  for w in r.items:
-    echo w
-    
-  for w in r.itemsWithPrefix("de"):
-    echo w
+  r.excl "def"
+
+  assert toSeq(r.items) == @["abc", "definition", "prefix", "xyz"]
 
+  assert toSeq(r.itemsWithPrefix("de")) == @["definition"]
diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim
index 5d9c3f445..25f6616a6 100644
--- a/lib/pure/collections/intsets.nim
+++ b/lib/pure/collections/intsets.nim
@@ -8,18 +8,18 @@
 #
 
 ## The ``intsets`` module implements an efficient int set implemented as a
-## sparse bit set.
+## `sparse bit set`:idx:.
 ## **Note**: Since Nim currently does not allow the assignment operator to
 ## be overloaded, ``=`` for int sets performs some rather meaningless shallow
 ## copy; use ``assign`` to get a deep copy.
 
 import
-  os, hashes, math
+  hashes, math
 
 type
   BitScalar = int
 
-const 
+const
   InitIntSetSize = 8         # must be a power of two!
   TrunkShift = 9
   BitsPerTrunk = 1 shl TrunkShift # needs to be a power of 2 and
@@ -31,11 +31,11 @@ const
 
 type
   PTrunk = ref TTrunk
-  TTrunk {.final.} = object 
+  TTrunk {.final.} = object
     next: PTrunk             # all nodes are connected with this pointer
     key: int                 # start address at bit 0
     bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector
-  
+
   TTrunkSeq = seq[PTrunk]
   IntSet* = object ## an efficient set of 'int' implemented as a sparse bit set
     counter, max: int
@@ -44,42 +44,42 @@ type
 
 {.deprecated: [TIntSet: IntSet].}
 
-proc mustRehash(length, counter: int): bool {.inline.} = 
+proc mustRehash(length, counter: int): bool {.inline.} =
   assert(length > counter)
   result = (length * 2 < counter * 3) or (length - counter < 4)
 
-proc nextTry(h, maxHash: THash): THash {.inline.} = 
-  result = ((5 * h) + 1) and maxHash 
+proc nextTry(h, maxHash: THash): THash {.inline.} =
+  result = ((5 * h) + 1) and maxHash
 
-proc intSetGet(t: IntSet, key: int): PTrunk = 
+proc intSetGet(t: IntSet, key: int): PTrunk =
   var h = key and t.max
-  while t.data[h] != nil: 
-    if t.data[h].key == key: 
+  while t.data[h] != nil:
+    if t.data[h].key == key:
       return t.data[h]
     h = nextTry(h, t.max)
   result = nil
 
-proc intSetRawInsert(t: IntSet, data: var TTrunkSeq, desc: PTrunk) = 
+proc intSetRawInsert(t: IntSet, data: var TTrunkSeq, desc: PTrunk) =
   var h = desc.key and t.max
-  while data[h] != nil: 
+  while data[h] != nil:
     assert(data[h] != desc)
     h = nextTry(h, t.max)
   assert(data[h] == nil)
   data[h] = desc
 
-proc intSetEnlarge(t: var IntSet) = 
+proc intSetEnlarge(t: var IntSet) =
   var n: TTrunkSeq
   var oldMax = t.max
   t.max = ((t.max + 1) * 2) - 1
   newSeq(n, t.max + 1)
-  for i in countup(0, oldMax): 
+  for i in countup(0, oldMax):
     if t.data[i] != nil: intSetRawInsert(t, n, t.data[i])
   swap(t.data, n)
 
-proc intSetPut(t: var IntSet, key: int): PTrunk = 
+proc intSetPut(t: var IntSet, key: int): PTrunk =
   var h = key and t.max
-  while t.data[h] != nil: 
-    if t.data[h].key == key: 
+  while t.data[h] != nil:
+    if t.data[h].key == key:
       return t.data[h]
     h = nextTry(h, t.max)
   if mustRehash(t.max + 1, t.counter): intSetEnlarge(t)
@@ -94,43 +94,43 @@ proc intSetPut(t: var IntSet, key: int): PTrunk =
   t.data[h] = result
 
 proc contains*(s: IntSet, key: int): bool =
-  ## returns true iff `key` is in `s`.  
+  ## returns true iff `key` is in `s`.
   var t = intSetGet(s, `shr`(key, TrunkShift))
-  if t != nil: 
+  if t != nil:
     var u = key and TrunkMask
     result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
-  else: 
+  else:
     result = false
-  
-proc incl*(s: var IntSet, key: int) = 
+
+proc incl*(s: var IntSet, key: int) =
   ## includes an element `key` in `s`.
   var t = intSetPut(s, `shr`(key, TrunkShift))
   var u = key and TrunkMask
   t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
       `shl`(1, u and IntMask)
 
-proc excl*(s: var IntSet, key: int) = 
+proc excl*(s: var IntSet, key: int) =
   ## excludes `key` from the set `s`.
   var t = intSetGet(s, `shr`(key, TrunkShift))
-  if t != nil: 
+  if t != nil:
     var u = key and TrunkMask
     t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and
         not `shl`(1, u and IntMask)
 
-proc containsOrIncl*(s: var IntSet, key: int): bool = 
+proc containsOrIncl*(s: var IntSet, key: int): bool =
   ## returns true if `s` contains `key`, otherwise `key` is included in `s`
   ## and false is returned.
   var t = intSetGet(s, `shr`(key, TrunkShift))
-  if t != nil: 
+  if t != nil:
     var u = key and TrunkMask
     result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
-    if not result: 
+    if not result:
       t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
           `shl`(1, u and IntMask)
-  else: 
+  else:
     incl(s, key)
     result = false
-    
+
 proc initIntSet*: IntSet =
   ## creates a new int set that is empty.
   newSeq(result.data, InitIntSetSize)
@@ -140,14 +140,14 @@ proc initIntSet*: IntSet =
 
 proc assign*(dest: var IntSet, src: IntSet) =
   ## copies `src` to `dest`. `dest` does not need to be initialized by
-  ## `initIntSet`. 
+  ## `initIntSet`.
   dest.counter = src.counter
   dest.max = src.max
   newSeq(dest.data, src.data.len)
-  
+
   var it = src.head
   while it != nil:
-    
+
     var h = it.key and dest.max
     while dest.data[h] != nil: h = nextTry(h, dest.max)
     assert(dest.data[h] == nil)
@@ -168,7 +168,7 @@ iterator items*(s: IntSet): int {.inline.} =
   while r != nil:
     var i = 0
     while i <= high(r.bits):
-      var w = r.bits[i] 
+      var w = r.bits[i]
       # taking a copy of r.bits[i] here is correct, because
       # modifying operations are not allowed during traversation
       var j = 0
@@ -191,20 +191,28 @@ proc `$`*(s: IntSet): string =
   ## The `$` operator for int sets.
   dollarImpl()
 
-proc empty*(s: IntSet): bool {.inline.} =
+proc empty*(s: IntSet): bool {.inline, deprecated.} =
   ## returns true if `s` is empty. This is safe to call even before
-  ## the set has been initialized with `initIntSet`.
+  ## the set has been initialized with `initIntSet`. Note this never
+  ## worked reliably and so is deprecated.
   result = s.counter == 0
 
 when isMainModule:
+  import sequtils, algorithm
+
   var x = initIntSet()
   x.incl(1)
   x.incl(2)
   x.incl(7)
   x.incl(1056)
-  for e in items(x): echo e
 
-  var y: TIntSet
+  var xs = toSeq(items(x))
+  xs.sort(cmp[int])
+  assert xs == @[1, 2, 7, 1056]
+
+  var y: IntSet
   assign(y, x)
-  for e in items(y): echo e
+  var ys = toSeq(items(y))
+  ys.sort(cmp[int])
+  assert ys == @[1, 2, 7, 1056]
 
diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim
index 929de5973..535d5e21d 100644
--- a/lib/pure/collections/lists.nim
+++ b/lib/pure/collections/lists.nim
@@ -32,7 +32,7 @@ type
     head*, tail*: DoublyLinkedNode[T]
 
   SinglyLinkedRing*[T] = object ## a singly linked ring
-    head*: SinglyLinkedNode[T]
+    head*, tail*: SinglyLinkedNode[T]
   
   DoublyLinkedRing*[T] = object ## a doubly linked ring
     head*: DoublyLinkedNode[T]
@@ -122,6 +122,22 @@ iterator items*[T](L: DoublyLinkedRing[T]): T =
   ## yields every value of `L`.
   itemsRingImpl()
 
+iterator mitems*[T](L: var DoublyLinkedList[T]): var T =
+  ## yields every value of `L` so that you can modify it.
+  itemsListImpl()
+
+iterator mitems*[T](L: var SinglyLinkedList[T]): var T =
+  ## yields every value of `L` so that you can modify it.
+  itemsListImpl()
+
+iterator mitems*[T](L: var SinglyLinkedRing[T]): var T =
+  ## yields every value of `L` so that you can modify it.
+  itemsRingImpl()
+
+iterator mitems*[T](L: var DoublyLinkedRing[T]): var T =
+  ## yields every value of `L` so that you can modify it.
+  itemsRingImpl()
+
 iterator nodes*[T](L: SinglyLinkedList[T]): SinglyLinkedNode[T] = 
   ## iterates over every node of `x`. Removing the current node from the
   ## list during traversal is supported.
@@ -251,13 +267,31 @@ proc remove*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) =
   if n.prev != nil: n.prev.next = n.next
 
 
+proc append*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = 
+  ## appends a node `n` to `L`. Efficiency: O(1).
+  if L.head != nil:
+    n.next = L.head
+    assert(L.tail != nil)
+    L.tail.next = n
+    L.tail = n
+  else:
+    n.next = n
+    L.head = n
+    L.tail = n
+
+proc append*[T](L: var SinglyLinkedRing[T], value: T) = 
+  ## appends a value to `L`. Efficiency: O(1).
+  append(L, newSinglyLinkedNode(value))
+
 proc prepend*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = 
   ## prepends a node `n` to `L`. Efficiency: O(1).
-  if L.head != nil: 
-    n.next = L.head    
-    L.head.next = n
-  else: 
+  if L.head != nil:
+    n.next = L.head
+    assert(L.tail != nil)
+    L.tail.next = n
+  else:
     n.next = n
+    L.tail = n
   L.head = n
 
 proc prepend*[T](L: var SinglyLinkedRing[T], value: T) = 
diff --git a/lib/pure/collections/queues.nim b/lib/pure/collections/queues.nim
index defce657f..af5e7b6cd 100644
--- a/lib/pure/collections/queues.nim
+++ b/lib/pure/collections/queues.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-## Implementation of a queue. The underlying implementation uses a ``seq``.
+## Implementation of a `queue`:idx:. The underlying implementation uses a ``seq``.
 ## Note: For inter thread communication use
 ## a `TChannel <channels.html>`_ instead.
 
@@ -39,6 +39,15 @@ iterator items*[T](q: Queue[T]): T =
     yield q.data[i]
     i = (i + 1) and q.mask
 
+iterator mitems*[T](q: var Queue[T]): var T =
+  ## yields every element of `q`.
+  var i = q.rd
+  var c = q.count
+  while c > 0:
+    dec c
+    yield q.data[i]
+    i = (i + 1) and q.mask
+
 proc add*[T](q: var Queue[T], item: T) =
   ## adds an `item` to the end of the queue `q`.
   var cap = q.mask+1
diff --git a/lib/pure/collections/rtarrays.nim b/lib/pure/collections/rtarrays.nim
index e5d0b0d8a..9d8085643 100644
--- a/lib/pure/collections/rtarrays.nim
+++ b/lib/pure/collections/rtarrays.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index befc9bacb..e9cd2cb3c 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -47,6 +47,24 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] =
       result[i] = itm
       inc(i)
 
+proc repeat*[T](s: seq[T], n: Natural): seq[T] =
+  ## Returns a new sequence with the items of `s` repeated `n` times.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:
+  ##
+  ##   let
+  ##     s = @[1, 2, 3]
+  ##     total = s.repeat(3)
+  ##   assert total == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
+  result = newSeq[T](n * s.len)
+  var o = 0
+  for x in 1..n:
+    for e in s:
+      result[o] = e
+      inc o
+
 proc deduplicate*[T](seq1: seq[T]): seq[T] =
   ## Returns a new sequence without duplicates.
   ##
@@ -63,7 +81,7 @@ proc deduplicate*[T](seq1: seq[T]): seq[T] =
     if not result.contains(itm): result.add(itm)
 
 {.deprecated: [distnct: deduplicate].}
-    
+
 proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] =
   ## Returns a new sequence with a combination of the two input sequences.
   ##
@@ -86,7 +104,7 @@ proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] =
   newSeq(result, m)
   for i in 0 .. m-1: result[i] = (seq1[i], seq2[i])
 
-proc distribute*[T](s: seq[T], num: int, spread = true): seq[seq[T]] =
+proc distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] =
   ## Splits and distributes a sequence `s` into `num` sub sequences.
   ##
   ## Returns a sequence of `num` sequences. For some input values this is the
@@ -113,11 +131,12 @@ proc distribute*[T](s: seq[T], num: int, spread = true): seq[seq[T]] =
   ##   assert numbers.distribute(6)[0] == @[1, 2]
   ##   assert numbers.distribute(6)[5] == @[7]
   assert(not s.isNil, "`s` can't be nil")
-  assert(num > 0, "`num` has to be greater than zero")
   if num < 2:
     result = @[s]
     return
 
+  let num = int(num) # XXX probably only needed because of .. bug
+
   # Create the result and calculate the stride size and the remainder if any.
   result = newSeq[seq[T]](num)
   var
@@ -162,7 +181,7 @@ iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T =
   ##   for n in filter(numbers, proc (x: int): bool = x mod 2 == 0):
   ##     echo($n)
   ##   # echoes 4, 8, 4 in separate lines
-  for i in countup(0, len(seq1) -1):
+  for i in countup(0, len(seq1)-1):
     var item = seq1[i]
     if pred(item): yield seq1[i]
 
@@ -209,7 +228,7 @@ proc delete*[T](s: var seq[T], first=0, last=0) =
   ##   var dest = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1]
   ##   dest.delete(3, 8)
   ##   assert outcome == dest
-  
+
   var i = first
   var j = last+1
   var newLen = len(s)-j+i
@@ -227,12 +246,12 @@ proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) =
   ##
   ##.. code-block::
   ##   var dest = @[1,1,1,1,1,1,1,1]
-  ##   let 
+  ##   let
   ##     src = @[2,2,2,2,2,2]
   ##     outcome = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1]
   ##   dest.insert(src, 3)
   ##   assert dest == outcome
-  
+
   var j = len(dest) - 1
   var i = len(dest) + len(src) - 1
   dest.setLen(i + 1)
@@ -320,7 +339,7 @@ template foldl*(sequence, operation: expr): expr =
   ##
   ## The ``operation`` parameter should be an expression which uses the
   ## variables ``a`` and ``b`` for each step of the fold. Since this is a left
-  ## fold, for non associative binary operations like substraction think that
+  ## fold, for non associative binary operations like subtraction think that
   ## the sequence of numbers 1, 2 and 3 will be parenthesized as (((1) - 2) -
   ## 3).  Example:
   ##
@@ -328,12 +347,12 @@ template foldl*(sequence, operation: expr): expr =
   ##   let
   ##     numbers = @[5, 9, 11]
   ##     addition = foldl(numbers, a + b)
-  ##     substraction = foldl(numbers, a - b)
+  ##     subtraction = foldl(numbers, a - b)
   ##     multiplication = foldl(numbers, a * b)
   ##     words = @["nim", "is", "cool"]
   ##     concatenation = foldl(words, a & b)
   ##   assert addition == 25, "Addition is (((5)+9)+11)"
-  ##   assert substraction == -15, "Substraction is (((5)-9)-11)"
+  ##   assert subtraction == -15, "Subtraction is (((5)-9)-11)"
   ##   assert multiplication == 495, "Multiplication is (((5)*9)*11)"
   ##   assert concatenation == "nimiscool"
   assert sequence.len > 0, "Can't fold empty sequences"
@@ -356,7 +375,7 @@ template foldr*(sequence, operation: expr): expr =
   ##
   ## The ``operation`` parameter should be an expression which uses the
   ## variables ``a`` and ``b`` for each step of the fold. Since this is a right
-  ## fold, for non associative binary operations like substraction think that
+  ## fold, for non associative binary operations like subtraction think that
   ## the sequence of numbers 1, 2 and 3 will be parenthesized as (1 - (2 -
   ## (3))). Example:
   ##
@@ -364,12 +383,12 @@ template foldr*(sequence, operation: expr): expr =
   ##   let
   ##     numbers = @[5, 9, 11]
   ##     addition = foldr(numbers, a + b)
-  ##     substraction = foldr(numbers, a - b)
+  ##     subtraction = foldr(numbers, a - b)
   ##     multiplication = foldr(numbers, a * b)
   ##     words = @["nim", "is", "cool"]
   ##     concatenation = foldr(words, a & b)
   ##   assert addition == 25, "Addition is (5+(9+(11)))"
-  ##   assert substraction == 7, "Substraction is (5-(9-(11)))"
+  ##   assert subtraction == 7, "Subtraction is (5-(9-(11)))"
   ##   assert multiplication == 495, "Multiplication is (5*(9*(11)))"
   ##   assert concatenation == "nimiscool"
   assert sequence.len > 0, "Can't fold empty sequences"
@@ -382,7 +401,7 @@ template foldr*(sequence, operation: expr): expr =
     result = operation
   result
 
-template mapIt*(seq1, typ, pred: expr): expr =
+template mapIt*(seq1, typ, op: expr): expr =
   ## Convenience template around the ``map`` proc to reduce typing.
   ##
   ## The template injects the ``it`` variable which you can use directly in an
@@ -397,10 +416,10 @@ template mapIt*(seq1, typ, pred: expr): expr =
   ##   assert strings == @["4", "8", "12", "16"]
   var result {.gensym.}: seq[typ] = @[]
   for it {.inject.} in items(seq1):
-    result.add(pred)
+    result.add(op)
   result
 
-template mapIt*(varSeq, pred: expr) =
+template mapIt*(varSeq, op: expr) =
   ## Convenience template around the mutable ``map`` proc to reduce typing.
   ##
   ## The template injects the ``it`` variable which you can use directly in an
@@ -413,7 +432,7 @@ template mapIt*(varSeq, pred: expr) =
   ##   assert nums[0] + nums[3] == 15
   for i in 0 .. <len(varSeq):
     let it {.inject.} = varSeq[i]
-    varSeq[i] = pred
+    varSeq[i] = op
 
 template newSeqWith*(len: int, init: expr): expr =
   ## creates a new sequence, calling `init` to initialize each value. Example:
@@ -473,9 +492,8 @@ when isMainModule:
 
   block: # filter iterator test
     let numbers = @[1, 4, 5, 8, 9, 7, 4]
-    for n in filter(numbers, proc (x: int): bool = x mod 2 == 0):
-      echo($n)
-    # echoes 4, 8, 4 in separate lines
+    assert toSeq(filter(numbers, proc (x: int): bool = x mod 2 == 0)) ==
+      @[4, 8, 4]
 
   block: # keepIf test
     var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1]
@@ -507,12 +525,12 @@ when isMainModule:
     let
       numbers = @[5, 9, 11]
       addition = foldl(numbers, a + b)
-      substraction = foldl(numbers, a - b)
+      subtraction = foldl(numbers, a - b)
       multiplication = foldl(numbers, a * b)
       words = @["nim", "is", "cool"]
       concatenation = foldl(words, a & b)
     assert addition == 25, "Addition is (((5)+9)+11)"
-    assert substraction == -15, "Substraction is (((5)-9)-11)"
+    assert subtraction == -15, "Subtraction is (((5)-9)-11)"
     assert multiplication == 495, "Multiplication is (((5)*9)*11)"
     assert concatenation == "nimiscool"
 
@@ -520,12 +538,12 @@ when isMainModule:
     let
       numbers = @[5, 9, 11]
       addition = foldr(numbers, a + b)
-      substraction = foldr(numbers, a - b)
+      subtraction = foldr(numbers, a - b)
       multiplication = foldr(numbers, a * b)
       words = @["nim", "is", "cool"]
       concatenation = foldr(words, a & b)
     assert addition == 25, "Addition is (5+(9+(11)))"
-    assert substraction == 7, "Substraction is (5-(9-(11)))"
+    assert subtraction == 7, "Subtraction is (5-(9-(11)))"
     assert multiplication == 495, "Multiplication is (5*(9*(11)))"
     assert concatenation == "nimiscool"
 
@@ -534,12 +552,12 @@ when isMainModule:
     var dest = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1]
     dest.delete(3, 8)
     assert outcome == dest, """\
-    Deleting range 3-9 from [1,1,1,2,2,2,2,2,2,1,1,1,1,1] 
+    Deleting range 3-9 from [1,1,1,2,2,2,2,2,2,1,1,1,1,1]
     is [1,1,1,1,1,1,1,1]"""
 
   block: # insert tests
     var dest = @[1,1,1,1,1,1,1,1]
-    let 
+    let
       src = @[2,2,2,2,2,2]
       outcome = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1]
     dest.insert(src, 3)
@@ -587,4 +605,15 @@ when isMainModule:
     seq2D[0][1] = true
     doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
 
-  echo "Finished doc tests"
+  block: # repeat tests
+    let
+      a = @[1, 2, 3]
+      b: seq[int] = @[]
+
+    doAssert a.repeat(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
+    doAssert a.repeat(0) == @[]
+    #doAssert a.repeat(-1) == @[] # will not compile!
+    doAssert b.repeat(3) == @[]
+
+  when not defined(testing):
+    echo "Finished doc tests"
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index 92ef3152d..280e0eeba 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -7,7 +7,8 @@
 #    distribution, for details about the copyright.
 #
 
-## The ``sets`` module implements an efficient hash set and ordered hash set.
+## The ``sets`` module implements an efficient `hash set`:idx: and
+## ordered hash set.
 ##
 ## Hash sets are different from the `built in set type
 ## <manual.html#set-type>`_. Sets allow you to store any value that can be
@@ -23,9 +24,12 @@ import
 when not defined(nimhygiene):
   {.pragma: dirty.}
 
+# For "integer-like A" that are too big for intsets/bit-vectors to be practical,
+# it would be best to shrink hcode to the same size as the integer.  Larger
+# codes should never be needed, and this can pack more entries per cache-line.
+# Losing hcode entirely is also possible - if some element value is forbidden.
 type
-  SlotEnum = enum seEmpty, seFilled, seDeleted
-  KeyValuePair[A] = tuple[slot: SlotEnum, key: A]
+  KeyValuePair[A] = tuple[hcode: THash, key: A]
   KeyValuePairSeq[A] = seq[KeyValuePair[A]]
   HashSet* {.myShallow.}[A] = object ## \
     ## A generic hash set.
@@ -37,6 +41,14 @@ type
 
 {.deprecated: [TSet: HashSet].}
 
+# hcode for real keys cannot be zero.  hcode==0 signifies an empty slot.  These
+# two procs retain clarity of that encoding without the space cost of an enum.
+proc isEmpty(hcode: THash): bool {.inline.} =
+  result = hcode == 0
+
+proc isFilled(hcode: THash): bool {.inline.} =
+  result = hcode != 0
+
 proc isValid*[A](s: HashSet[A]): bool =
   ## Returns `true` if the set has been initialized with `initSet <#initSet>`_.
   ##
@@ -93,7 +105,7 @@ iterator items*[A](s: HashSet[A]): A =
   ##   # --> {(a: 1, b: 3), (a: 0, b: 4)}
   assert s.isValid, "The set needs to be initialized."
   for h in 0..high(s.data):
-    if s.data[h].slot == seFilled: yield s.data[h].key
+    if isFilled(s.data[h].hcode): yield s.data[h].key
 
 const
   growthFactor = 2
@@ -102,25 +114,44 @@ proc mustRehash(length, counter: int): bool {.inline.} =
   assert(length > counter)
   result = (length * 2 < counter * 3) or (length - counter < 4)
 
-proc nextTry(h, maxHash: THash): THash {.inline.} =
-  result = ((5 * h) + 1) and maxHash
+proc rightSize*(count: Natural): int {.inline.} =
+  ## Return the value of `initialSize` to support `count` items.
+  ##
+  ## If more items are expected to be added, simply add that
+  ## expected extra amount to the parameter before calling this.
+  ##
+  ## Internally, we want mustRehash(rightSize(x), x) == false.
+  result = nextPowerOfTwo(count * 3 div 2  +  4)
 
-template rawGetImpl() {.dirty.} =
-  var h: THash = hash(key) and high(s.data) # start with real hash value
-  while s.data[h].slot != seEmpty:
-    if s.data[h].key == key and s.data[h].slot == seFilled:
+proc nextTry(h, maxHash: THash): THash {.inline.} =
+  result = (h + 1) and maxHash
+
+template rawGetKnownHCImpl() {.dirty.} =
+  var h: THash = hc and high(s.data)  # start with real hash value
+  while isFilled(s.data[h].hcode):
+    # Compare hc THEN key with boolean short circuit. This makes the common case
+    # zero ==key's for missing (e.g.inserts) and exactly one ==key for present.
+    # It does slow down succeeding lookups by one extra THash cmp&and..usually
+    # just a few clock cycles, generally worth it for any non-integer-like A.
+    if s.data[h].hcode == hc and s.data[h].key == key:  # compare hc THEN key
       return h
     h = nextTry(h, high(s.data))
-  result = -1
+  result = -1 - h                   # < 0 => MISSING; insert idx = -1 - result
+
+template rawGetImpl() {.dirty.} =
+  hc = hash(key)
+  if hc == 0:       # This almost never taken branch should be very predictable.
+    hc = 314159265  # Value doesn't matter; Any non-zero favorite is fine.
+  rawGetKnownHCImpl()
 
 template rawInsertImpl() {.dirty.} =
-  var h: THash = hash(key) and high(data)
-  while data[h].slot == seFilled:
-    h = nextTry(h, high(data))
   data[h].key = key
-  data[h].slot = seFilled
+  data[h].hcode = hc
 
-proc rawGet[A](s: HashSet[A], key: A): int =
+proc rawGetKnownHC[A](s: HashSet[A], key: A, hc: THash): int {.inline.} =
+  rawGetKnownHCImpl()
+
+proc rawGet[A](s: HashSet[A], key: A, hc: var THash): int {.inline.} =
   rawGetImpl()
 
 proc mget*[A](s: var HashSet[A], key: A): var A =
@@ -129,7 +160,8 @@ proc mget*[A](s: var HashSet[A], key: A): var A =
   ## when one overloaded 'hash' and '==' but still needs reference semantics
   ## for sharing.
   assert s.isValid, "The set needs to be initialized."
-  var index = rawGet(s, key)
+  var hc: THash
+  var index = rawGet(s, key, hc)
   if index >= 0: result = s.data[index].key
   else: raise newException(KeyError, "key not found: " & $key)
 
@@ -146,33 +178,43 @@ proc contains*[A](s: HashSet[A], key: A): bool =
   ##   values.excl(2)
   ##   assert(not values.contains(2))
   assert s.isValid, "The set needs to be initialized."
-  var index = rawGet(s, key)
+  var hc: THash
+  var index = rawGet(s, key, hc)
   result = index >= 0
 
-proc rawInsert[A](s: var HashSet[A], data: var KeyValuePairSeq[A], key: A) =
+proc rawInsert[A](s: var HashSet[A], data: var KeyValuePairSeq[A], key: A,
+                  hc: THash, h: THash) =
   rawInsertImpl()
 
 proc enlarge[A](s: var HashSet[A]) =
   var n: KeyValuePairSeq[A]
   newSeq(n, len(s.data) * growthFactor)
-  for i in countup(0, high(s.data)):
-    if s.data[i].slot == seFilled: rawInsert(s, n, s.data[i].key)
-  swap(s.data, n)
+  swap(s.data, n)                   # n is now old seq
+  for i in countup(0, high(n)):
+    if isFilled(n[i].hcode):
+      var j = -1 - rawGetKnownHC(s, n[i].key, n[i].hcode)
+      rawInsert(s, s.data, n[i].key, n[i].hcode, j)
 
 template inclImpl() {.dirty.} =
-  var index = rawGet(s, key)
+  var hc: THash
+  var index = rawGet(s, key, hc)
   if index < 0:
-    if mustRehash(len(s.data), s.counter): enlarge(s)
-    rawInsert(s, s.data, key)
+    if mustRehash(len(s.data), s.counter):
+      enlarge(s)
+      index = rawGetKnownHC(s, key, hc)
+    rawInsert(s, s.data, key, hc, -1 - index)
     inc(s.counter)
 
 template containsOrInclImpl() {.dirty.} =
-  var index = rawGet(s, key)
+  var hc: THash
+  var index = rawGet(s, key, hc)
   if index >= 0:
     result = true
   else:
-    if mustRehash(len(s.data), s.counter): enlarge(s)
-    rawInsert(s, s.data, key)
+    if mustRehash(len(s.data), s.counter):
+      enlarge(s)
+      index = rawGetKnownHC(s, key, hc)
+    rawInsert(s, s.data, key, hc, -1 - index)
     inc(s.counter)
 
 proc incl*[A](s: var HashSet[A], key: A) =
@@ -203,6 +245,11 @@ proc incl*[A](s: var HashSet[A], other: HashSet[A]) =
   assert other.isValid, "The set `other` needs to be initialized."
   for item in other: incl(s, item)
 
+template doWhile(a: expr, b: stmt): stmt =
+  while true:
+    b
+    if not a: break
+
 proc excl*[A](s: var HashSet[A], key: A) =
   ## Excludes `key` from the set `s`.
   ##
@@ -214,10 +261,22 @@ proc excl*[A](s: var HashSet[A], key: A) =
   ##   s.excl(2)
   ##   assert s.len == 3
   assert s.isValid, "The set needs to be initialized."
-  var index = rawGet(s, key)
-  if index >= 0:
-    s.data[index].slot = seDeleted
+  var hc: THash
+  var i = rawGet(s, key, hc)
+  var msk = high(s.data)
+  if i >= 0:
+    s.data[i].hcode = 0
     dec(s.counter)
+    while true:         # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1
+      var j = i         # The correctness of this depends on (h+1) in nextTry,
+      var r = j         # though may be adaptable to other simple sequences.
+      s.data[i].hcode = 0              # mark current EMPTY
+      doWhile ((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)):
+        i = (i + 1) and msk            # increment mod table size
+        if isEmpty(s.data[i].hcode):   # end of collision cluster; So all done
+          return
+        r = s.data[i].hcode and msk    # "home" location of key@i
+      shallowCopy(s.data[j], s.data[i]) # data[j] will be marked EMPTY next loop
 
 proc excl*[A](s: var HashSet[A], other: HashSet[A]) =
   ## Excludes everything in `other` from `s`.
@@ -253,10 +312,10 @@ proc containsOrIncl*[A](s: var HashSet[A], key: A): bool =
 proc init*[A](s: var HashSet[A], initialSize=64) =
   ## Initializes a hash set.
   ##
-  ## The `initialSize` parameter needs to be a power of too. You can use
-  ## `math.nextPowerOfTwo() <math.html#nextPowerOfTwo>`_ to guarantee that at
-  ## runtime. All set variables have to be initialized before you can use them
-  ## with other procs from this module with the exception of `isValid()
+  ## The `initialSize` parameter needs to be a power of two. You can use
+  ## `math.nextPowerOfTwo() <math.html#nextPowerOfTwo>`_ or `rightSize` to
+  ## guarantee that at runtime. All set variables must be initialized before
+  ## use with other procs from this module with the exception of `isValid()
   ## <#isValid,TSet[A]>`_ and `len() <#len,TSet[A]>`_.
   ##
   ## You can call this proc on a previously initialized hash set, which will
@@ -294,7 +353,7 @@ proc toSet*[A](keys: openArray[A]): HashSet[A] =
   ##   var numbers = toSet([1, 2, 3, 4, 5])
   ##   assert numbers.contains(2)
   ##   assert numbers.contains(4)
-  result = initSet[A](nextPowerOfTwo(keys.len+10))
+  result = initSet[A](rightSize(keys.len))
   for key in items(keys): result.incl(key)
 
 template dollarImpl(): stmt {.dirty.} =
@@ -493,7 +552,7 @@ proc map*[A, B](data: HashSet[A], op: proc (x: A): B {.closure.}): HashSet[B] =
 
 type
   OrderedKeyValuePair[A] = tuple[
-    slot: SlotEnum, next: int, key: A]
+    hcode: THash, next: int, key: A]
   OrderedKeyValuePairSeq[A] = seq[OrderedKeyValuePair[A]]
   OrderedSet* {.myShallow.}[A] = object ## \
     ## A generic hash set that remembers insertion order.
@@ -545,7 +604,7 @@ template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
   var h = s.first
   while h >= 0:
     var nxt = s.data[h].next
-    if s.data[h].slot == seFilled: yieldStmt
+    if isFilled(s.data[h].hcode): yieldStmt
     h = nxt
 
 iterator items*[A](s: OrderedSet[A]): A =
@@ -570,7 +629,10 @@ iterator items*[A](s: OrderedSet[A]): A =
   forAllOrderedPairs:
     yield s.data[h].key
 
-proc rawGet[A](s: OrderedSet[A], key: A): int =
+proc rawGetKnownHC[A](s: OrderedSet[A], key: A, hc: THash): int {.inline.} =
+  rawGetKnownHCImpl()
+
+proc rawGet[A](s: OrderedSet[A], key: A, hc: var THash): int {.inline.} =
   rawGetImpl()
 
 proc contains*[A](s: OrderedSet[A], key: A): bool =
@@ -584,11 +646,12 @@ proc contains*[A](s: OrderedSet[A], key: A): bool =
   ##   values.incl(2)
   ##   assert values.contains(2)
   assert s.isValid, "The set needs to be initialized."
-  var index = rawGet(s, key)
+  var hc: THash
+  var index = rawGet(s, key, hc)
   result = index >= 0
 
-proc rawInsert[A](s: var OrderedSet[A], 
-                  data: var OrderedKeyValuePairSeq[A], key: A) =
+proc rawInsert[A](s: var OrderedSet[A], data: var OrderedKeyValuePairSeq[A],
+                  key: A, hc: THash, h: THash) =
   rawInsertImpl()
   data[h].next = -1
   if s.first < 0: s.first = h
@@ -601,12 +664,13 @@ proc enlarge[A](s: var OrderedSet[A]) =
   var h = s.first
   s.first = -1
   s.last = -1
+  swap(s.data, n)
   while h >= 0:
-    var nxt = s.data[h].next
-    if s.data[h].slot == seFilled: 
-      rawInsert(s, n, s.data[h].key)
+    var nxt = n[h].next
+    if isFilled(n[h].hcode):
+      var j = -1 - rawGetKnownHC(s, n[h].key, n[h].hcode)
+      rawInsert(s, s.data, n[h].key, n[h].hcode, j)
     h = nxt
-  swap(s.data, n)
 
 proc incl*[A](s: var OrderedSet[A], key: A) =
   ## Includes an element `key` in `s`.
@@ -654,10 +718,10 @@ proc containsOrIncl*[A](s: var OrderedSet[A], key: A): bool =
 proc init*[A](s: var OrderedSet[A], initialSize=64) =
   ## Initializes an ordered hash set.
   ##
-  ## The `initialSize` parameter needs to be a power of too. You can use
-  ## `math.nextPowerOfTwo() <math.html#nextPowerOfTwo>`_ to guarantee that at
-  ## runtime. All set variables have to be initialized before you can use them
-  ## with other procs from this module with the exception of `isValid()
+  ## The `initialSize` parameter needs to be a power of two. You can use
+  ## `math.nextPowerOfTwo() <math.html#nextPowerOfTwo>`_ or `rightSize` to
+  ## guarantee that at runtime. All set variables must be initialized before
+  ## use with other procs from this module with the exception of `isValid()
   ## <#isValid,TOrderedSet[A]>`_ and `len() <#len,TOrderedSet[A]>`_.
   ##
   ## You can call this proc on a previously initialized ordered hash set to
@@ -697,7 +761,7 @@ proc toOrderedSet*[A](keys: openArray[A]): OrderedSet[A] =
   ##   var numbers = toOrderedSet([1, 2, 3, 4, 5])
   ##   assert numbers.contains(2)
   ##   assert numbers.contains(4)
-  result = initOrderedSet[A](nextPowerOfTwo(keys.len+10))
+  result = initOrderedSet[A](rightSize(keys.len))
   for key in items(keys): result.incl(key)
 
 proc `$`*[A](s: OrderedSet[A]): string =
@@ -725,7 +789,7 @@ proc `==`*[A](s, t: OrderedSet[A]): bool =
   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 isFilled(s.data[h].hcode) and isFilled(s.data[g].hcode):
       if s.data[h].key == s.data[g].key:
         inc compared
       else:
@@ -734,172 +798,179 @@ proc `==`*[A](s, t: OrderedSet[A]): bool =
     g = nxg
   result = compared == s.counter
 
-proc testModule() =
-  ## Internal micro test to validate docstrings and such.
-  block isValidTest:
-    var options: HashSet[string]
-    proc savePreferences(options: HashSet[string]) =
-      assert options.isValid, "Pass an initialized set!"
-    options = initSet[string]()
-    options.savePreferences
-
-  block lenTest:
-    var values: HashSet[int]
-    assert(not values.isValid)
-    assert values.len == 0
-    assert values.card == 0
-
-  block setIterator:
-    type pair = tuple[a, b: int]
-    var a, b = initSet[pair]()
-    a.incl((2, 3))
-    a.incl((3, 2))
-    a.incl((2, 3))
-    for x, y in a.items:
-      b.incl((x - 2, y + 1))
-    assert a.len == b.card
-    assert a.len == 2
-    #echo b
-
-  block setContains:
-    var values = initSet[int]()
-    assert(not values.contains(2))
-    values.incl(2)
-    assert values.contains(2)
-    values.excl(2)
-    assert(not values.contains(2))
-
-    values.incl(4)
-    var others = toSet([6, 7])
-    values.incl(others)
-    assert values.len == 3
-
-    values.init
-    assert values.containsOrIncl(2) == false
-    assert values.containsOrIncl(2) == true
-    var
-      a = toSet([1, 2])
-      b = toSet([1])
-    b.incl(2)
-    assert a == b
-
-  block exclusions:
-    var s = toSet([2, 3, 6, 7])
-    s.excl(2)
-    s.excl(2)
-    assert s.len == 3
-
-    var
-      numbers = toSet([1, 2, 3, 4, 5])
-      even = toSet([2, 4, 6, 8])
-    numbers.excl(even)
-    #echo numbers
-    # --> {1, 3, 5}
-
-  block toSeqAndString:
-    var a = toSet([2, 4, 5])
-    var b = initSet[int]()
-    for x in [2, 4, 5]: b.incl(x)
-    assert($a == $b)
-    #echo a
-    #echo toSet(["no", "esc'aping", "is \" provided"])
-
-  #block orderedToSeqAndString:
-  #  echo toOrderedSet([2, 4, 5])
-  #  echo toOrderedSet(["no", "esc'aping", "is \" provided"])
-
-  block setOperations:
-    var
-      a = toSet(["a", "b"])
-      b = toSet(["b", "c"])
-      c = union(a, b)
-    assert c == toSet(["a", "b", "c"])
-    var d = intersection(a, b)
-    assert d == toSet(["b"])
-    var e = difference(a, b)
-    assert e == toSet(["a"])
-    var f = symmetricDifference(a, b)
-    assert f == toSet(["a", "c"])
-    assert d < a and d < b
-    assert((a < a) == false)
-    assert d <= a and d <= b
-    assert((a <= a))
-    # Alias test.
-    assert a + b == toSet(["a", "b", "c"])
-    assert a * b == toSet(["b"])
-    assert a - b == toSet(["a"])
-    assert a -+- b == toSet(["a", "c"])
-    assert disjoint(a, b) == false
-    assert disjoint(a, b - a) == true
-
-  block mapSet:
-    var a = toSet([1, 2, 3])
-    var b = a.map(proc (x: int): string = $x)
-    assert b == toSet(["1", "2", "3"])
-
-  block isValidTest:
-    var cards: OrderedSet[string]
-    proc saveTarotCards(cards: OrderedSet[string]) =
-      assert cards.isValid, "Pass an initialized set!"
-    cards = initOrderedSet[string]()
-    cards.saveTarotCards
-
-  block lenTest:
-    var values: OrderedSet[int]
-    assert(not values.isValid)
-    assert values.len == 0
-    assert values.card == 0
-
-  block setIterator:
-    type pair = tuple[a, b: int]
-    var a, b = initOrderedSet[pair]()
-    a.incl((2, 3))
-    a.incl((3, 2))
-    a.incl((2, 3))
-    for x, y in a.items:
-      b.incl((x - 2, y + 1))
-    assert a.len == b.card
-    assert a.len == 2
-
-  #block orderedSetIterator:
-  #  var a = initOrderedSet[int]()
-  #  for value in [9, 2, 1, 5, 1, 8, 4, 2]:
-  #    a.incl(value)
-  #  for value in a.items:
-  #    echo "Got ", value
-
-  block setContains:
-    var values = initOrderedSet[int]()
-    assert(not values.contains(2))
-    values.incl(2)
-    assert values.contains(2)
-
-  block toSeqAndString:
-    var a = toOrderedSet([2, 4, 5])
-    var b = initOrderedSet[int]()
-    for x in [2, 4, 5]: b.incl(x)
-    assert($a == $b)
-    assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
-
-  block initBlocks:
-    var a: OrderedSet[int]
-    a.init(4)
-    a.incl(2)
-    a.init
-    assert a.len == 0 and a.isValid
-    a = initOrderedSet[int](4)
-    a.incl(2)
-    assert a.len == 1
-
-    var b: HashSet[int]
-    b.init(4)
-    b.incl(2)
-    b.init
-    assert b.len == 0 and b.isValid
-    b = initSet[int](4)
-    b.incl(2)
-    assert b.len == 1
-
-  echo "Micro tests run successfully."
-
-when isMainModule and not defined(release): testModule()
+when isMainModule and not defined(release):
+  proc testModule() =
+    ## Internal micro test to validate docstrings and such.
+    block isValidTest:
+      var options: HashSet[string]
+      proc savePreferences(options: HashSet[string]) =
+        assert options.isValid, "Pass an initialized set!"
+      options = initSet[string]()
+      options.savePreferences
+
+    block lenTest:
+      var values: HashSet[int]
+      assert(not values.isValid)
+      assert values.len == 0
+      assert values.card == 0
+
+    block setIterator:
+      type pair = tuple[a, b: int]
+      var a, b = initSet[pair]()
+      a.incl((2, 3))
+      a.incl((3, 2))
+      a.incl((2, 3))
+      for x, y in a.items:
+        b.incl((x - 2, y + 1))
+      assert a.len == b.card
+      assert a.len == 2
+      #echo b
+
+    block setContains:
+      var values = initSet[int]()
+      assert(not values.contains(2))
+      values.incl(2)
+      assert values.contains(2)
+      values.excl(2)
+      assert(not values.contains(2))
+
+      values.incl(4)
+      var others = toSet([6, 7])
+      values.incl(others)
+      assert values.len == 3
+
+      values.init
+      assert values.containsOrIncl(2) == false
+      assert values.containsOrIncl(2) == true
+      var
+        a = toSet([1, 2])
+        b = toSet([1])
+      b.incl(2)
+      assert a == b
+
+    block exclusions:
+      var s = toSet([2, 3, 6, 7])
+      s.excl(2)
+      s.excl(2)
+      assert s.len == 3
+
+      var
+        numbers = toSet([1, 2, 3, 4, 5])
+        even = toSet([2, 4, 6, 8])
+      numbers.excl(even)
+      #echo numbers
+      # --> {1, 3, 5}
+
+    block toSeqAndString:
+      var a = toSet([2, 4, 5])
+      var b = initSet[int]()
+      for x in [2, 4, 5]: b.incl(x)
+      assert($a == $b)
+      #echo a
+      #echo toSet(["no", "esc'aping", "is \" provided"])
+
+    #block orderedToSeqAndString:
+    #  echo toOrderedSet([2, 4, 5])
+    #  echo toOrderedSet(["no", "esc'aping", "is \" provided"])
+
+    block setOperations:
+      var
+        a = toSet(["a", "b"])
+        b = toSet(["b", "c"])
+        c = union(a, b)
+      assert c == toSet(["a", "b", "c"])
+      var d = intersection(a, b)
+      assert d == toSet(["b"])
+      var e = difference(a, b)
+      assert e == toSet(["a"])
+      var f = symmetricDifference(a, b)
+      assert f == toSet(["a", "c"])
+      assert d < a and d < b
+      assert((a < a) == false)
+      assert d <= a and d <= b
+      assert((a <= a))
+      # Alias test.
+      assert a + b == toSet(["a", "b", "c"])
+      assert a * b == toSet(["b"])
+      assert a - b == toSet(["a"])
+      assert a -+- b == toSet(["a", "c"])
+      assert disjoint(a, b) == false
+      assert disjoint(a, b - a) == true
+
+    block mapSet:
+      var a = toSet([1, 2, 3])
+      var b = a.map(proc (x: int): string = $x)
+      assert b == toSet(["1", "2", "3"])
+
+    block isValidTest:
+      var cards: OrderedSet[string]
+      proc saveTarotCards(cards: OrderedSet[string]) =
+        assert cards.isValid, "Pass an initialized set!"
+      cards = initOrderedSet[string]()
+      cards.saveTarotCards
+
+    block lenTest:
+      var values: OrderedSet[int]
+      assert(not values.isValid)
+      assert values.len == 0
+      assert values.card == 0
+
+    block setIterator:
+      type pair = tuple[a, b: int]
+      var a, b = initOrderedSet[pair]()
+      a.incl((2, 3))
+      a.incl((3, 2))
+      a.incl((2, 3))
+      for x, y in a.items:
+        b.incl((x - 2, y + 1))
+      assert a.len == b.card
+      assert a.len == 2
+
+    #block orderedSetIterator:
+    #  var a = initOrderedSet[int]()
+    #  for value in [9, 2, 1, 5, 1, 8, 4, 2]:
+    #    a.incl(value)
+    #  for value in a.items:
+    #    echo "Got ", value
+
+    block setContains:
+      var values = initOrderedSet[int]()
+      assert(not values.contains(2))
+      values.incl(2)
+      assert values.contains(2)
+
+    block toSeqAndString:
+      var a = toOrderedSet([2, 4, 5])
+      var b = initOrderedSet[int]()
+      for x in [2, 4, 5]: b.incl(x)
+      assert($a == $b)
+      assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
+
+    block initBlocks:
+      var a: OrderedSet[int]
+      a.init(4)
+      a.incl(2)
+      a.init
+      assert a.len == 0 and a.isValid
+      a = initOrderedSet[int](4)
+      a.incl(2)
+      assert a.len == 1
+
+      var b: HashSet[int]
+      b.init(4)
+      b.incl(2)
+      b.init
+      assert b.len == 0 and b.isValid
+      b = initSet[int](4)
+      b.incl(2)
+      assert b.len == 1
+
+    for i in 0 .. 32:
+      var s = rightSize(i)
+      if s <= i or mustRehash(s, i):
+        echo "performance issue: rightSize() will not elide enlarge() at ", i
+
+    when not defined(testing):
+      echo "Micro tests run successfully."
+
+  testModule()
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index 28b7fde92..232e52c89 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -1,16 +1,17 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## The ``tables`` module implements variants of an efficient hash table that is
+## The ``tables`` module implements variants of an efficient `hash table`:idx:
+## (also often named `dictionary`:idx: in other programming languages) that is
 ## a mapping from keys to values. ``Table`` is the usual hash table,
 ## ``OrderedTable`` is like ``Table`` but remembers insertion order
-## and ``CountTable`` is a mapping from a key to its number of occurances.
+## and ``CountTable`` is a mapping from a key to its number of occurrences.
 ## For consistency with every other data type in Nim these have **value**
 ## semantics, this means that ``=`` performs a copy of the hash table.
 ## For **reference** semantics use the ``Ref`` variant: ``TableRef``,
@@ -70,8 +71,7 @@ import
 {.pragma: myShallow.}
 
 type
-  SlotEnum = enum seEmpty, seFilled, seDeleted
-  KeyValuePair[A, B] = tuple[slot: SlotEnum, key: A, val: B]
+  KeyValuePair[A, B] = tuple[hcode: THash, key: A, val: B]
   KeyValuePairSeq[A, B] = seq[KeyValuePair[A, B]]
   Table* {.myShallow.}[A, B] = object ## generic hash table
     data: KeyValuePairSeq[A, B]
@@ -83,35 +83,43 @@ type
 when not defined(nimhygiene):
   {.pragma: dirty.}
 
+# hcode for real keys cannot be zero.  hcode==0 signifies an empty slot.  These
+# two procs retain clarity of that encoding without the space cost of an enum.
+proc isEmpty(hcode: THash): bool {.inline.} =
+  result = hcode == 0
+
+proc isFilled(hcode: THash): bool {.inline.} =
+  result = hcode != 0
+
 proc len*[A, B](t: Table[A, B]): int =
   ## returns the number of keys in `t`.
   result = t.counter
 
-iterator pairs*[A, B](t: Table[A, B]): tuple[key: A, val: B] =
+iterator pairs*[A, B](t: Table[A, B]): (A, B) =
   ## iterates over any (key, value) pair in the table `t`.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val)
+    if isFilled(t.data[h].hcode): yield (t.data[h].key, t.data[h].val)
 
-iterator mpairs*[A, B](t: var Table[A, B]): tuple[key: A, val: var B] =
+iterator mpairs*[A, B](t: var Table[A, B]): (A, var B) =
   ## iterates over any (key, value) pair in the table `t`. The values
   ## can be modified.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val)
+    if isFilled(t.data[h].hcode): yield (t.data[h].key, t.data[h].val)
 
 iterator keys*[A, B](t: Table[A, B]): A =
   ## iterates over any key in the table `t`.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield t.data[h].key
+    if isFilled(t.data[h].hcode): yield t.data[h].key
 
 iterator values*[A, B](t: Table[A, B]): B =
   ## iterates over any value in the table `t`.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield t.data[h].val
+    if isFilled(t.data[h].hcode): yield t.data[h].val
 
 iterator mvalues*[A, B](t: var Table[A, B]): var B =
   ## iterates over any value in the table `t`. The values can be modified.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield t.data[h].val
+    if isFilled(t.data[h].hcode): yield t.data[h].val
 
 const
   growthFactor = 2
@@ -120,26 +128,57 @@ proc mustRehash(length, counter: int): bool {.inline.} =
   assert(length > counter)
   result = (length * 2 < counter * 3) or (length - counter < 4)
 
+proc rightSize*(count: Natural): int {.inline.} =
+  ## Return the value of `initialSize` to support `count` items.
+  ##
+  ## If more items are expected to be added, simply add that
+  ## expected extra amount to the parameter before calling this.
+  ##
+  ## Internally, we want mustRehash(rightSize(x), x) == false.
+  result = nextPowerOfTwo(count * 3 div 2  +  4)
+
 proc nextTry(h, maxHash: THash): THash {.inline.} =
-  result = ((5 * h) + 1) and maxHash
+  result = (h + 1) and maxHash
+
+template rawGetKnownHCImpl() {.dirty.} =
+  var h: THash = hc and high(t.data)   # start with real hash value
+  while isFilled(t.data[h].hcode):
+    # Compare hc THEN key with boolean short circuit. This makes the common case
+    # zero ==key's for missing (e.g.inserts) and exactly one ==key for present.
+    # It does slow down succeeding lookups by one extra THash cmp&and..usually
+    # just a few clock cycles, generally worth it for any non-integer-like A.
+    if t.data[h].hcode == hc and t.data[h].key == key:
+      return h
+    h = nextTry(h, high(t.data))
+  result = -1 - h                   # < 0 => MISSING; insert idx = -1 - result
 
 template rawGetImpl() {.dirty.} =
-  var h: THash = hash(key) and high(t.data) # start with real hash value
-  while t.data[h].slot != seEmpty:
-    if t.data[h].key == key and t.data[h].slot == seFilled:
-      return h
+  hc = hash(key)
+  if hc == 0:       # This almost never taken branch should be very predictable.
+    hc = 314159265  # Value doesn't matter; Any non-zero favorite is fine.
+  rawGetKnownHCImpl()
+
+template rawGetDeepImpl() {.dirty.} =   # Search algo for unconditional add
+  hc = hash(key)
+  if hc == 0:
+    hc = 314159265
+  var h: THash = hc and high(t.data)
+  while isFilled(t.data[h].hcode):
     h = nextTry(h, high(t.data))
-  result = -1
+  result = h
 
 template rawInsertImpl() {.dirty.} =
-  var h: THash = hash(key) and high(data)
-  while data[h].slot == seFilled:
-    h = nextTry(h, high(data))
   data[h].key = key
   data[h].val = val
-  data[h].slot = seFilled
+  data[h].hcode = hc
+
+proc rawGetKnownHC[A, B](t: Table[A, B], key: A, hc: THash): int {.inline.} =
+  rawGetKnownHCImpl()
+
+proc rawGetDeep[A, B](t: Table[A, B], key: A, hc: var THash): int {.inline.} =
+  rawGetDeepImpl()
 
-proc rawGet[A, B](t: Table[A, B], key: A): int =
+proc rawGet[A, B](t: Table[A, B], key: A, hc: var THash): int {.inline.} =
   rawGetImpl()
 
 proc `[]`*[A, B](t: Table[A, B], key: A): B =
@@ -147,63 +186,91 @@ proc `[]`*[A, B](t: Table[A, B], key: A): B =
   ## default empty value for the type `B` is returned
   ## and no exception is raised. One can check with ``hasKey`` whether the key
   ## exists.
-  var index = rawGet(t, key)
+  var hc: THash
+  var index = rawGet(t, key, hc)
   if index >= 0: result = t.data[index].val
 
 proc mget*[A, B](t: var Table[A, B], key: A): var B =
   ## retrieves the value at ``t[key]``. The value can be modified.
-  ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
-  var index = rawGet(t, key)
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  var hc: THash
+  var index = rawGet(t, key, hc)
   if index >= 0: result = t.data[index].val
-  else: raise newException(KeyError, "key not found: " & $key)
+  else:
+    when compiles($key):
+      raise newException(KeyError, "key not found: " & $key)
+    else:
+      raise newException(KeyError, "key not found")
 
 iterator allValues*[A, B](t: Table[A, B]; key: A): B =
   ## iterates over any value in the table `t` that belongs to the given `key`.
   var h: THash = hash(key) and high(t.data)
-  while t.data[h].slot != seEmpty:
-    if t.data[h].key == key and t.data[h].slot == seFilled:
+  while isFilled(t.data[h].hcode):
+    if t.data[h].key == key:
       yield t.data[h].val
     h = nextTry(h, high(t.data))
 
 proc hasKey*[A, B](t: Table[A, B], key: A): bool =
   ## returns true iff `key` is in the table `t`.
-  result = rawGet(t, key) >= 0
+  var hc: THash
+  result = rawGet(t, key, hc) >= 0
 
 proc rawInsert[A, B](t: var Table[A, B], data: var KeyValuePairSeq[A, B],
-                     key: A, val: B) =
+                     key: A, val: B, hc: THash, h: THash) =
   rawInsertImpl()
 
 proc enlarge[A, B](t: var Table[A, B]) =
   var n: KeyValuePairSeq[A, B]
   newSeq(n, len(t.data) * growthFactor)
-  for i in countup(0, high(t.data)):
-    if t.data[i].slot == seFilled: rawInsert(t, n, t.data[i].key, t.data[i].val)
   swap(t.data, n)
+  for i in countup(0, high(n)):
+    if isFilled(n[i].hcode):
+      var j = -1 - rawGetKnownHC(t, n[i].key, n[i].hcode)
+      rawInsert(t, t.data, n[i].key, n[i].val, n[i].hcode, j)
 
 template addImpl() {.dirty.} =
   if mustRehash(len(t.data), t.counter): enlarge(t)
-  rawInsert(t, t.data, key, val)
+  var hc: THash
+  var j = rawGetDeep(t, key, hc)
+  rawInsert(t, t.data, key, val, hc, j)
+  inc(t.counter)
+
+template maybeRehashPutImpl() {.dirty.} =
+  if mustRehash(len(t.data), t.counter):
+    enlarge(t)
+    index = rawGetKnownHC(t, key, hc)
+  index = -1 - index                  # important to transform for mgetOrPutImpl
+  rawInsert(t, t.data, key, val, hc, index)
   inc(t.counter)
 
 template putImpl() {.dirty.} =
-  var index = rawGet(t, key)
-  if index >= 0:
-    t.data[index].val = val
-  else:
-    addImpl()
-
-when false:
-  # not yet used:
-  template hasKeyOrPutImpl() {.dirty.} =
-    var index = rawGet(t, key)
-    if index >= 0:
-      t.data[index].val = val
-      result = true
-    else:
-      if mustRehash(len(t.data), t.counter): enlarge(t)
-      rawInsert(t, t.data, key, val)
-      inc(t.counter)
-      result = false
+  var hc: THash
+  var index = rawGet(t, key, hc)
+  if index >= 0: t.data[index].val = val
+  else: maybeRehashPutImpl()
+
+template mgetOrPutImpl() {.dirty.} =
+  var hc: THash
+  var index = rawGet(t, key, hc)
+  if index < 0: maybeRehashPutImpl()    # not present: insert (flipping index)
+  result = t.data[index].val            # either way return modifiable val
+
+template hasKeyOrPutImpl() {.dirty.} =
+  var hc: THash
+  var index = rawGet(t, key, hc)
+  if index < 0:
+    result = false
+    maybeRehashPutImpl()
+  else: result = true
+
+proc mgetOrPut*[A, B](t: var Table[A, B], key: A, val: B): var B =
+  ## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
+  ## returning a value which can be modified.
+  mgetOrPutImpl()
+
+proc hasKeyOrPut*[A, B](t: var Table[A, B], key: A, val: B): bool =
+  ## returns true iff `key` is in the table, otherwise inserts `value`.
+  hasKeyOrPutImpl()
 
 proc `[]=`*[A, B](t: var Table[A, B], key: A, val: B) =
   ## puts a (key, value)-pair into `t`.
@@ -212,28 +279,45 @@ proc `[]=`*[A, B](t: var Table[A, B], key: A, val: B) =
 proc add*[A, B](t: var Table[A, B], key: A, val: B) =
   ## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
   addImpl()
-  
+
+template doWhile(a: expr, b: stmt): stmt =
+  while true:
+    b
+    if not a: break
+
 proc del*[A, B](t: var Table[A, B], key: A) =
   ## deletes `key` from hash table `t`.
-  let index = rawGet(t, key)
-  if index >= 0:
-    t.data[index].slot = seDeleted
+  var hc: THash
+  var i = rawGet(t, key, hc)
+  let msk = high(t.data)
+  if i >= 0:
+    t.data[i].hcode = 0
     dec(t.counter)
+    while true:         # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1
+      var j = i         # The correctness of this depends on (h+1) in nextTry,
+      var r = j         # though may be adaptable to other simple sequences.
+      t.data[i].hcode = 0              # mark current EMPTY
+      doWhile ((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)):
+        i = (i + 1) and msk            # increment mod table size
+        if isEmpty(t.data[i].hcode):   # end of collision cluster; So all done
+          return
+        r = t.data[i].hcode and msk    # "home" location of key@i
+      shallowCopy(t.data[j], t.data[i]) # data[j] will be marked EMPTY next loop
 
 proc initTable*[A, B](initialSize=64): Table[A, B] =
   ## creates a new hash table that is empty.
   ##
   ## `initialSize` needs to be a power of two. If you need to accept runtime
   ## values for this you could use the ``nextPowerOfTwo`` proc from the
-  ## `math <math.html>`_ module.
+  ## `math <math.html>`_ module or the ``rightSize`` proc from this module.
   assert isPowerOfTwo(initialSize)
   result.counter = 0
   newSeq(result.data, initialSize)
 
-proc toTable*[A, B](pairs: openArray[tuple[key: A, 
-                    val: B]]): Table[A, B] =
+proc toTable*[A, B](pairs: openArray[(A,
+                    B)]): Table[A, B] =
   ## creates a new hash table that contains the given `pairs`.
-  result = initTable[A, B](nextPowerOfTwo(pairs.len+10))
+  result = initTable[A, B](rightSize(pairs.len))
   for key, val in items(pairs): result[key] = val
 
 template dollarImpl(): stmt {.dirty.} =
@@ -251,7 +335,7 @@ template dollarImpl(): stmt {.dirty.} =
 proc `$`*[A, B](t: Table[A, B]): string =
   ## The `$` operator for hash tables.
   dollarImpl()
-  
+
 template equalsImpl() =
   if s.counter == t.counter:
     # different insertion orders mean different 'data' seqs, so we have
@@ -261,10 +345,10 @@ template equalsImpl() =
       if not t.hasKey(key): return false
       if t[key] != val: return false
     return true
-  
+
 proc `==`*[A, B](s, t: Table[A, B]): bool =
   equalsImpl()
-  
+
 proc indexBy*[A, B, C](collection: A, index: proc(x: B): C): Table[C, B] =
   ## Index the collection with the proc provided.
   # TODO: As soon as supported, change collection: A to collection: A[B]
@@ -276,31 +360,31 @@ proc len*[A, B](t: TableRef[A, B]): int =
   ## returns the number of keys in `t`.
   result = t.counter
 
-iterator pairs*[A, B](t: TableRef[A, B]): tuple[key: A, val: B] =
+iterator pairs*[A, B](t: TableRef[A, B]): (A, B) =
   ## iterates over any (key, value) pair in the table `t`.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val)
+    if isFilled(t.data[h].hcode): yield (t.data[h].key, t.data[h].val)
 
-iterator mpairs*[A, B](t: TableRef[A, B]): tuple[key: A, val: var B] =
+iterator mpairs*[A, B](t: TableRef[A, B]): (A, var B) =
   ## iterates over any (key, value) pair in the table `t`. The values
   ## can be modified.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val)
+    if isFilled(t.data[h].hcode): yield (t.data[h].key, t.data[h].val)
 
 iterator keys*[A, B](t: TableRef[A, B]): A =
   ## iterates over any key in the table `t`.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield t.data[h].key
+    if isFilled(t.data[h].hcode): yield t.data[h].key
 
 iterator values*[A, B](t: TableRef[A, B]): B =
   ## iterates over any value in the table `t`.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield t.data[h].val
+    if isFilled(t.data[h].hcode): yield t.data[h].val
 
 iterator mvalues*[A, B](t: TableRef[A, B]): var B =
   ## iterates over any value in the table `t`. The values can be modified.
   for h in 0..high(t.data):
-    if t.data[h].slot == seFilled: yield t.data[h].val
+    if isFilled(t.data[h].hcode): yield t.data[h].val
 
 proc `[]`*[A, B](t: TableRef[A, B], key: A): B =
   ## retrieves the value at ``t[key]``. If `key` is not in `t`,
@@ -314,6 +398,15 @@ proc mget*[A, B](t: TableRef[A, B], key: A): var B =
   ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
   t[].mget(key)
 
+proc mgetOrPut*[A, B](t: TableRef[A, B], key: A, val: B): var B =
+  ## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
+  ## returning a value which can be modified.
+  t[].mgetOrPut(key, val)
+
+proc hasKeyOrPut*[A, B](t: var TableRef[A, B], key: A, val: B): bool =
+  ## returns true iff `key` is in the table, otherwise inserts `value`.
+  t[].hasKeyOrPut(key, val)
+
 proc hasKey*[A, B](t: TableRef[A, B], key: A): bool =
   ## returns true iff `key` is in the table `t`.
   result = t[].hasKey(key)
@@ -325,7 +418,7 @@ proc `[]=`*[A, B](t: TableRef[A, B], key: A, val: B) =
 proc add*[A, B](t: TableRef[A, B], key: A, val: B) =
   ## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
   t[].add(key, val)
-  
+
 proc del*[A, B](t: TableRef[A, B], key: A) =
   ## deletes `key` from hash table `t`.
   t[].del(key)
@@ -334,7 +427,7 @@ proc newTable*[A, B](initialSize=64): TableRef[A, B] =
   new(result)
   result[] = initTable[A, B](initialSize)
 
-proc newTable*[A, B](pairs: openArray[tuple[key: A, val: B]]): TableRef[A, B] =
+proc newTable*[A, B](pairs: openArray[(A, B)]): TableRef[A, B] =
   ## creates a new hash table that contains the given `pairs`.
   new(result)
   result[] = toTable[A, B](pairs)
@@ -346,7 +439,7 @@ proc `$`*[A, B](t: TableRef[A, B]): string =
 proc `==`*[A, B](s, t: TableRef[A, B]): bool =
   if isNil(s): result = isNil(t)
   elif isNil(t): result = false
-  else: result = equalsImpl()
+  else: equalsImpl()
 
 proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): TableRef[C, B] =
   ## Index the collection with the proc provided.
@@ -359,7 +452,7 @@ proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): TableRef[C, B]
 
 type
   OrderedKeyValuePair[A, B] = tuple[
-    slot: SlotEnum, next: int, key: A, val: B]
+    hcode: THash, next: int, key: A, val: B]
   OrderedKeyValuePairSeq[A, B] = seq[OrderedKeyValuePair[A, B]]
   OrderedTable* {.
       myShallow.}[A, B] = object ## table that remembers insertion order
@@ -377,16 +470,16 @@ template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
   var h = t.first
   while h >= 0:
     var nxt = t.data[h].next
-    if t.data[h].slot == seFilled: yieldStmt
+    if isFilled(t.data[h].hcode): yieldStmt
     h = nxt
 
-iterator pairs*[A, B](t: OrderedTable[A, B]): tuple[key: A, val: B] =
+iterator pairs*[A, B](t: OrderedTable[A, B]): (A, B) =
   ## iterates over any (key, value) pair in the table `t` in insertion
   ## order.
   forAllOrderedPairs:
     yield (t.data[h].key, t.data[h].val)
 
-iterator mpairs*[A, B](t: var OrderedTable[A, B]): tuple[key: A, val: var B] =
+iterator mpairs*[A, B](t: var OrderedTable[A, B]): (A, var B) =
   ## iterates over any (key, value) pair in the table `t` in insertion
   ## order. The values can be modified.
   forAllOrderedPairs:
@@ -408,7 +501,13 @@ iterator mvalues*[A, B](t: var OrderedTable[A, B]): var B =
   forAllOrderedPairs:
     yield t.data[h].val
 
-proc rawGet[A, B](t: OrderedTable[A, B], key: A): int =
+proc rawGetKnownHC[A, B](t: OrderedTable[A, B], key: A, hc: THash): int =
+  rawGetKnownHCImpl()
+
+proc rawGetDeep[A, B](t: OrderedTable[A, B], key: A, hc: var THash): int {.inline.} =
+  rawGetDeepImpl()
+
+proc rawGet[A, B](t: OrderedTable[A, B], key: A, hc: var THash): int =
   rawGetImpl()
 
 proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B =
@@ -416,23 +515,26 @@ proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B =
   ## default empty value for the type `B` is returned
   ## and no exception is raised. One can check with ``hasKey`` whether the key
   ## exists.
-  var index = rawGet(t, key)
+  var hc: THash
+  var index = rawGet(t, key, hc)
   if index >= 0: result = t.data[index].val
 
 proc mget*[A, B](t: var OrderedTable[A, B], key: A): var B =
   ## retrieves the value at ``t[key]``. The value can be modified.
   ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
-  var index = rawGet(t, key)
+  var hc: THash
+  var index = rawGet(t, key, hc)
   if index >= 0: result = t.data[index].val
   else: raise newException(KeyError, "key not found: " & $key)
 
 proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
   ## returns true iff `key` is in the table `t`.
-  result = rawGet(t, key) >= 0
+  var hc: THash
+  result = rawGet(t, key, hc) >= 0
 
-proc rawInsert[A, B](t: var OrderedTable[A, B], 
+proc rawInsert[A, B](t: var OrderedTable[A, B],
                      data: var OrderedKeyValuePairSeq[A, B],
-                     key: A, val: B) =
+                     key: A, val: B, hc: THash, h: THash) =
   rawInsertImpl()
   data[h].next = -1
   if t.first < 0: t.first = h
@@ -445,12 +547,13 @@ proc enlarge[A, B](t: var OrderedTable[A, B]) =
   var h = t.first
   t.first = -1
   t.last = -1
+  swap(t.data, n)
   while h >= 0:
-    var nxt = t.data[h].next
-    if t.data[h].slot == seFilled: 
-      rawInsert(t, n, t.data[h].key, t.data[h].val)
+    var nxt = n[h].next
+    if isFilled(n[h].hcode):
+      var j = -1 - rawGetKnownHC(t, n[h].key, n[h].hcode)
+      rawInsert(t, t.data, n[h].key, n[h].val, n[h].hcode, j)
     h = nxt
-  swap(t.data, n)
 
 proc `[]=`*[A, B](t: var OrderedTable[A, B], key: A, val: B) =
   ## puts a (key, value)-pair into `t`.
@@ -460,30 +563,39 @@ proc add*[A, B](t: var OrderedTable[A, B], key: A, val: B) =
   ## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
   addImpl()
 
+proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): var B =
+  ## retrieves value at ``t[key]`` or puts ``value`` if not present, either way
+  ## returning a value which can be modified.
+  mgetOrPutImpl()
+
+proc hasKeyOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): bool =
+  ## returns true iff `key` is in the table, otherwise inserts `value`.
+  hasKeyOrPutImpl()
+
 proc initOrderedTable*[A, B](initialSize=64): OrderedTable[A, B] =
   ## creates a new ordered hash table that is empty.
   ##
   ## `initialSize` needs to be a power of two. If you need to accept runtime
   ## values for this you could use the ``nextPowerOfTwo`` proc from the
-  ## `math <math.html>`_ module.
+  ## `math <math.html>`_ module or the ``rightSize`` proc from this module.
   assert isPowerOfTwo(initialSize)
   result.counter = 0
   result.first = -1
   result.last = -1
   newSeq(result.data, initialSize)
 
-proc toOrderedTable*[A, B](pairs: openArray[tuple[key: A, 
-                           val: B]]): OrderedTable[A, B] =
+proc toOrderedTable*[A, B](pairs: openArray[(A,
+                           B)]): OrderedTable[A, B] =
   ## creates a new ordered hash table that contains the given `pairs`.
-  result = initOrderedTable[A, B](nextPowerOfTwo(pairs.len+10))
+  result = initOrderedTable[A, B](rightSize(pairs.len))
   for key, val in items(pairs): result[key] = val
 
 proc `$`*[A, B](t: OrderedTable[A, B]): string =
   ## The `$` operator for ordered hash tables.
   dollarImpl()
 
-proc sort*[A, B](t: var OrderedTable[A, B], 
-                 cmp: proc (x,y: tuple[key: A, val: B]): int) =
+proc sort*[A, B](t: var OrderedTable[A, B],
+                 cmp: proc (x,y: (A, B)): int) =
   ## sorts `t` according to `cmp`. This modifies the internal list
   ## that kept the insertion order, so insertion order is lost after this
   ## call but key lookup and insertions remain possible after `sort` (in
@@ -505,7 +617,7 @@ proc sort*[A, B](t: var OrderedTable[A, B],
       while i < insize:
         inc(psize)
         q = t.data[q].next
-        if q < 0: break 
+        if q < 0: break
         inc(i)
       qsize = insize
       while psize > 0 or (qsize > 0 and q >= 0):
@@ -513,7 +625,7 @@ proc sort*[A, B](t: var OrderedTable[A, B],
           e = q; q = t.data[q].next; dec(qsize)
         elif qsize == 0 or q < 0:
           e = p; p = t.data[p].next; dec(psize)
-        elif cmp((t.data[p].key, t.data[p].val), 
+        elif cmp((t.data[p].key, t.data[p].val),
                  (t.data[q].key, t.data[q].val)) <= 0:
           e = p; p = t.data[p].next; dec(psize)
         else:
@@ -536,16 +648,16 @@ template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
   var h = t.first
   while h >= 0:
     var nxt = t.data[h].next
-    if t.data[h].slot == seFilled: yieldStmt
+    if isFilled(t.data[h].hcode): yieldStmt
     h = nxt
 
-iterator pairs*[A, B](t: OrderedTableRef[A, B]): tuple[key: A, val: B] =
+iterator pairs*[A, B](t: OrderedTableRef[A, B]): (A, B) =
   ## iterates over any (key, value) pair in the table `t` in insertion
   ## order.
   forAllOrderedPairs:
     yield (t.data[h].key, t.data[h].val)
 
-iterator mpairs*[A, B](t: OrderedTableRef[A, B]): tuple[key: A, val: var B] =
+iterator mpairs*[A, B](t: OrderedTableRef[A, B]): (A, var B) =
   ## iterates over any (key, value) pair in the table `t` in insertion
   ## order. The values can be modified.
   forAllOrderedPairs:
@@ -579,6 +691,15 @@ proc mget*[A, B](t: OrderedTableRef[A, B], key: A): var B =
   ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
   result = t[].mget(key)
 
+proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): var B =
+  ## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
+  ## returning a value which can be modified.
+  result = t[].mgetOrPut(key, val)
+
+proc hasKeyOrPut*[A, B](t: var OrderedTableRef[A, B], key: A, val: B): bool =
+  ## returns true iff `key` is in the table, otherwise inserts `val`.
+  result = t[].hasKeyOrPut(key, val)
+
 proc hasKey*[A, B](t: OrderedTableRef[A, B], key: A): bool =
   ## returns true iff `key` is in the table `t`.
   result = t[].hasKey(key)
@@ -596,22 +717,21 @@ proc newOrderedTable*[A, B](initialSize=64): OrderedTableRef[A, B] =
   ##
   ## `initialSize` needs to be a power of two. If you need to accept runtime
   ## values for this you could use the ``nextPowerOfTwo`` proc from the
-  ## `math <math.html>`_ module.
+  ## `math <math.html>`_ module or the ``rightSize`` proc from this module.
   new(result)
   result[] = initOrderedTable[A, B]()
 
-proc newOrderedTable*[A, B](pairs: openArray[tuple[key: A, 
-                           val: B]]): OrderedTableRef[A, B] =
+proc newOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTableRef[A, B] =
   ## creates a new ordered hash table that contains the given `pairs`.
-  result = newOrderedTable[A, B](nextPowerOfTwo(pairs.len+10))
+  result = newOrderedTable[A, B](rightSize(pairs.len))
   for key, val in items(pairs): result[key] = val
 
 proc `$`*[A, B](t: OrderedTableRef[A, B]): string =
   ## The `$` operator for ordered hash tables.
   dollarImpl()
 
-proc sort*[A, B](t: OrderedTableRef[A, B], 
-                 cmp: proc (x,y: tuple[key: A, val: B]): int) =
+proc sort*[A, B](t: OrderedTableRef[A, B],
+                 cmp: proc (x,y: (A, B)): int) =
   ## sorts `t` according to `cmp`. This modifies the internal list
   ## that kept the insertion order, so insertion order is lost after this
   ## call but key lookup and insertions remain possible after `sort` (in
@@ -633,12 +753,12 @@ proc len*[A](t: CountTable[A]): int =
   ## returns the number of keys in `t`.
   result = t.counter
 
-iterator pairs*[A](t: CountTable[A]): tuple[key: A, val: int] =
+iterator pairs*[A](t: CountTable[A]): (A, int) =
   ## iterates over any (key, value) pair in the table `t`.
   for h in 0..high(t.data):
     if t.data[h].val != 0: yield (t.data[h].key, t.data[h].val)
 
-iterator mpairs*[A](t: var CountTable[A]): tuple[key: A, val: var int] =
+iterator mpairs*[A](t: var CountTable[A]): (A, var int) =
   ## iterates over any (key, value) pair in the table `t`. The values can
   ## be modified.
   for h in 0..high(t.data):
@@ -664,7 +784,7 @@ proc rawGet[A](t: CountTable[A], key: A): int =
   while t.data[h].val != 0:
     if t.data[h].key == key: return h
     h = nextTry(h, high(t.data))
-  result = -1
+  result = -1 - h                   # < 0 => MISSING; insert idx = -1 - result
 
 proc `[]`*[A](t: CountTable[A], key: A): int =
   ## retrieves the value at ``t[key]``. If `key` is not in `t`,
@@ -701,28 +821,34 @@ proc enlarge[A](t: var CountTable[A]) =
 proc `[]=`*[A](t: var CountTable[A], key: A, val: int) =
   ## puts a (key, value)-pair into `t`. `val` has to be positive.
   assert val > 0
-  putImpl()
+  var h = rawGet(t, key)
+  if h >= 0:
+    t.data[h].val = val
+  else:
+    h = -1 - h
+    t.data[h].key = key
+    t.data[h].val = val
 
 proc initCountTable*[A](initialSize=64): CountTable[A] =
   ## creates a new count table that is empty.
   ##
   ## `initialSize` needs to be a power of two. If you need to accept runtime
   ## values for this you could use the ``nextPowerOfTwo`` proc from the
-  ## `math <math.html>`_ module.
+  ## `math <math.html>`_ module or the ``rightSize`` proc in this module.
   assert isPowerOfTwo(initialSize)
   result.counter = 0
   newSeq(result.data, initialSize)
 
 proc toCountTable*[A](keys: openArray[A]): CountTable[A] =
   ## creates a new count table with every key in `keys` having a count of 1.
-  result = initCountTable[A](nextPowerOfTwo(keys.len+10))
+  result = initCountTable[A](rightSize(keys.len))
   for key in items(keys): result[key] = 1
 
 proc `$`*[A](t: CountTable[A]): string =
   ## The `$` operator for count tables.
   dollarImpl()
 
-proc inc*[A](t: var CountTable[A], key: A, val = 1) = 
+proc inc*[A](t: var CountTable[A], key: A, val = 1) =
   ## increments `t[key]` by `val`.
   var index = rawGet(t, key)
   if index >= 0:
@@ -775,12 +901,12 @@ proc len*[A](t: CountTableRef[A]): int =
   ## returns the number of keys in `t`.
   result = t.counter
 
-iterator pairs*[A](t: CountTableRef[A]): tuple[key: A, val: int] =
+iterator pairs*[A](t: CountTableRef[A]): (A, int) =
   ## iterates over any (key, value) pair in the table `t`.
   for h in 0..high(t.data):
     if t.data[h].val != 0: yield (t.data[h].key, t.data[h].val)
 
-iterator mpairs*[A](t: CountTableRef[A]): tuple[key: A, val: var int] =
+iterator mpairs*[A](t: CountTableRef[A]): (A, var int) =
   ## iterates over any (key, value) pair in the table `t`. The values can
   ## be modified.
   for h in 0..high(t.data):
@@ -826,28 +952,28 @@ proc newCountTable*[A](initialSize=64): CountTableRef[A] =
   ##
   ## `initialSize` needs to be a power of two. If you need to accept runtime
   ## values for this you could use the ``nextPowerOfTwo`` proc from the
-  ## `math <math.html>`_ module.
+  ## `math <math.html>`_ module or the ``rightSize`` method in this module.
   new(result)
   result[] = initCountTable[A](initialSize)
 
 proc newCountTable*[A](keys: openArray[A]): CountTableRef[A] =
   ## creates a new count table with every key in `keys` having a count of 1.
-  result = newCountTable[A](nextPowerOfTwo(keys.len+10))
+  result = newCountTable[A](rightSize(keys.len))
   for key in items(keys): result[key] = 1
 
 proc `$`*[A](t: CountTableRef[A]): string =
   ## The `$` operator for count tables.
   dollarImpl()
 
-proc inc*[A](t: CountTableRef[A], key: A, val = 1) = 
+proc inc*[A](t: CountTableRef[A], key: A, val = 1) =
   ## increments `t[key]` by `val`.
   t[].inc(key, val)
 
-proc smallest*[A](t: CountTableRef[A]): tuple[key: A, val: int] =
+proc smallest*[A](t: CountTableRef[A]): (A, int) =
   ## returns the largest (key,val)-pair. Efficiency: O(n)
   t[].smallest
 
-proc largest*[A](t: CountTableRef[A]): tuple[key: A, val: int] =
+proc largest*[A](t: CountTableRef[A]): (A, int) =
   ## returns the (key,val)-pair with the largest `val`. Efficiency: O(n)
   t[].largest
 
@@ -858,6 +984,22 @@ proc sort*[A](t: CountTableRef[A]) =
   ## `t` in the sorted order.
   t[].sort
 
+proc merge*[A](s: var CountTable[A], t: CountTable[A]) =
+  ## merges the second table into the first one
+  for key, value in t:
+    s.inc(key, value)
+
+proc merge*[A](s, t: CountTable[A]): CountTable[A] =
+  ## merges the two tables into a new one
+  result = initCountTable[A](nextPowerOfTwo(max(s.len, t.len)))
+  for table in @[s, t]:
+    for key, value in table:
+      result.inc(key, value)
+
+proc merge*[A](s, t: CountTableRef[A]) =
+  ## merges the second table into the first one
+  s[].merge(t[])
+
 when isMainModule:
   type
     Person = object
@@ -886,3 +1028,48 @@ when isMainModule:
   s2[p2] = 45_000
   s3[p1] = 30_000
   s3[p2] = 45_000
+
+  var
+    t1 = initCountTable[string]()
+    t2 = initCountTable[string]()
+  t1.inc("foo")
+  t1.inc("bar", 2)
+  t1.inc("baz", 3)
+  t2.inc("foo", 4)
+  t2.inc("bar")
+  t2.inc("baz", 11)
+  merge(t1, t2)
+  assert(t1["foo"] == 5)
+  assert(t1["bar"] == 3)
+  assert(t1["baz"] == 14)
+
+  let
+    t1r = newCountTable[string]()
+    t2r = newCountTable[string]()
+  t1r.inc("foo")
+  t1r.inc("bar", 2)
+  t1r.inc("baz", 3)
+  t2r.inc("foo", 4)
+  t2r.inc("bar")
+  t2r.inc("baz", 11)
+  merge(t1r, t2r)
+  assert(t1r["foo"] == 5)
+  assert(t1r["bar"] == 3)
+  assert(t1r["baz"] == 14)
+
+  var
+    t1l = initCountTable[string]()
+    t2l = initCountTable[string]()
+  t1l.inc("foo")
+  t1l.inc("bar", 2)
+  t1l.inc("baz", 3)
+  t2l.inc("foo", 4)
+  t2l.inc("bar")
+  t2l.inc("baz", 11)
+  let
+    t1merging = t1l
+    t2merging = t2l
+  let merged = merge(t1merging, t2merging)
+  assert(merged["foo"] == 5)
+  assert(merged["bar"] == 3)
+  assert(merged["baz"] == 14)
diff --git a/lib/pure/colors.nim b/lib/pure/colors.nim
index 7942255cb..f24cc0072 100644
--- a/lib/pure/colors.nim
+++ b/lib/pure/colors.nim
@@ -46,7 +46,7 @@ proc `+`*(a, b: Color): Color =
   colorOp(satPlus)
   
 proc `-`*(a, b: Color): Color =
-  ## substracts two colors: This uses saturated artithmetic, so that each color
+  ## subtracts two colors: This uses saturated artithmetic, so that each color
   ## component cannot overflow (255 is used as a maximum).
   colorOp(satMinus)
   
@@ -392,7 +392,7 @@ proc parseColor*(name: string): Color =
     result = Color(parseHexInt(name))
   else:
     var idx = binaryStrSearch(colorNames, name)
-    if idx < 0: raise newException(ValueError, "unkown color: " & name)
+    if idx < 0: raise newException(ValueError, "unknown color: " & name)
     result = colorNames[idx][1]
 
 proc isColor*(name: string): bool =
diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim
index 0c5704f69..8577bf7a1 100644
--- a/lib/pure/complex.nim
+++ b/lib/pure/complex.nim
@@ -27,6 +27,11 @@ type
 
 {.deprecated: [TComplex: Complex].}
 
+proc toComplex*(x: SomeInteger): Complex =
+  ## Convert some integer ``x`` to a complex number.
+  result.re = x
+  result.im = 0
+
 proc `==` *(x, y: Complex): bool =
   ## Compare two complex numbers `x` and `y` for equality.
   result = x.re == y.re and x.im == y.im
@@ -171,6 +176,12 @@ proc abs*(z: Complex): float =
     result = y * sqrt(1.0 + temp * temp)
 
 
+proc conjugate*(z: Complex): Complex =
+  ## Conjugate of complex number `z`.
+  result.re = z.re
+  result.im = -z.im
+
+
 proc sqrt*(z: Complex): Complex =
   ## Square root for a complex number `z`.
   var x, y, w, r: float
@@ -263,27 +274,101 @@ proc tan*(z: Complex): Complex =
   ## Returns the tangent of `z`.
   result = sin(z)/cos(z)
 
+proc arctan*(z: Complex): Complex =
+  ## Returns the inverse tangent of `z`.
+  var i: Complex = (0.0,1.0)
+  result = 0.5*i*(ln(1-i*z)-ln(1+i*z))
+
 proc cot*(z: Complex): Complex =
   ## Returns the cotangent of `z`.
   result = cos(z)/sin(z)
 
+proc arccot*(z: Complex): Complex =
+  ## Returns the inverse cotangent of `z`.
+  var i: Complex = (0.0,1.0)
+  result = 0.5*i*(ln(1-i/z)-ln(1+i/z))
+
 proc sec*(z: Complex): Complex =
   ## Returns the secant of `z`.
   result = 1.0/cos(z)
 
+proc arcsec*(z: Complex): Complex =
+  ## Returns the inverse secant of `z`.
+  var i: Complex = (0.0,1.0)
+  result = -i*ln(i*sqrt(1-1/(z*z))+1/z)
+
 proc csc*(z: Complex): Complex =
   ## Returns the cosecant of `z`.
   result = 1.0/sin(z)
 
+proc arccsc*(z: Complex): Complex =
+  ## Returns the inverse cosecant of `z`.
+  var i: Complex = (0.0,1.0)
+  result = -i*ln(sqrt(1-1/(z*z))+i/z)
+
 
 proc sinh*(z: Complex): Complex =
   ## Returns the hyperbolic sine of `z`.
   result = 0.5*(exp(z)-exp(-z))
 
+proc arcsinh*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic sine of `z`.
+  result = ln(z+sqrt(z*z+1))
+
 proc cosh*(z: Complex): Complex =
   ## Returns the hyperbolic cosine of `z`.
   result = 0.5*(exp(z)+exp(-z))
 
+proc arccosh*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic cosine of `z`.
+  result = ln(z+sqrt(z*z-1))
+
+proc tanh*(z: Complex): Complex =
+  ## Returns the hyperbolic tangent of `z`.
+  result = sinh(z)/cosh(z)
+
+proc arctanh*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic tangent of `z`.
+  result = 0.5*(ln((1+z)/(1-z)))
+
+proc sech*(z: Complex): Complex =
+  ## Returns the hyperbolic secant of `z`.
+  result = 2/(exp(z)+exp(-z))
+
+proc arcsech*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic secant of `z`.
+  result = ln(1/z+sqrt(1/z+1)*sqrt(1/z-1))
+
+proc csch*(z: Complex): Complex =
+  ## Returns the hyperbolic cosecant of `z`.
+  result = 2/(exp(z)-exp(-z))
+
+proc arccsch*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic cosecant of `z`.
+  result = ln(1/z+sqrt(1/(z*z)+1))
+
+proc coth*(z: Complex): Complex =
+  ## Returns the hyperbolic cotangent of `z`.
+  result = cosh(z)/sinh(z)
+
+proc arccoth*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic cotangent of `z`.
+  result = 0.5*(ln(1+1/z)-ln(1-1/z))
+
+proc phase*(z: Complex): float =
+  ## Returns the phase of `z`.
+  arctan2(z.im, z.re)
+
+proc polar*(z: Complex): tuple[r, phi: float] =
+  ## Returns `z` in polar coordinates.
+  result.r = abs(z)
+  result.phi = phase(z)
+
+proc rect*(r: float, phi: float): Complex =
+  ## Returns the complex number with polar coordinates `r` and `phi`.
+  result.re = r * cos(phi)
+  result.im = r * sin(phi)
+
 
 proc `$`*(z: Complex): string =
   ## Returns `z`'s string representation as ``"(re, im)"``.
@@ -303,41 +388,56 @@ when isMainModule:
   var tt = (10.0, 20.0)
   var ipi = (0.0, -PI)
  
-  assert( a         == a )
-  assert( (a-a)     == z )
-  assert( (a+b)     == z )
-  assert( (a/b)     == m1 )
-  assert( (1.0/a)   == (0.2, -0.4) )
-  assert( (a*b)     == (3.0, -4.0) )
-  assert( 10.0*a    == tt )
-  assert( a*10.0    == tt )
-  assert( tt/10.0   == a )
+  assert( a == a )
+  assert( (a-a) == z )
+  assert( (a+b) == z )
+  assert( (a/b) == m1 )
+  assert( (1.0/a) == (0.2, -0.4) )
+  assert( (a*b) == (3.0, -4.0) )
+  assert( 10.0*a == tt )
+  assert( a*10.0 == tt )
+  assert( tt/10.0 == a )
   assert( oo+(-1.0) == i )
   assert( (-1.0)+oo == i )
-  assert( abs(oo)   == sqrt(2.0) )
-  assert( sqrt(m1)  == i )
-  assert( exp(ipi)  =~ m1 )
+  assert( abs(oo) == sqrt(2.0) )
+  assert( conjugate(a) == (1.0, -2.0) )
+  assert( sqrt(m1) == i )
+  assert( exp(ipi) =~ m1 )
  
-  assert( pow(a,b)   =~ (-3.72999124927876, -1.68815826725068) )
-  assert( pow(z,a)   =~ (0.0, 0.0) )
-  assert( pow(z,z)   =~ (1.0, 0.0) )
+  assert( pow(a,b) =~ (-3.72999124927876, -1.68815826725068) )
+  assert( pow(z,a) =~ (0.0, 0.0) )
+  assert( pow(z,z) =~ (1.0, 0.0) )
   assert( pow(a,one) =~ a )
-  assert( pow(a,m1)  =~ (0.2, -0.4) )
+  assert( pow(a,m1) =~ (0.2, -0.4) )
 
-  assert( ln(a)    =~ (0.804718956217050, 1.107148717794090) )
+  assert( ln(a) =~ (0.804718956217050, 1.107148717794090) )
   assert( log10(a) =~ (0.349485002168009, 0.480828578784234) )
-  assert( log2(a)  =~ (1.16096404744368, 1.59727796468811) )
-
-  assert( sin(a)    =~ (3.16577851321617, 1.95960104142161) )
-  assert( cos(a)    =~ (2.03272300701967, -3.05189779915180) )
-  assert( tan(a)    =~ (0.0338128260798967, 1.0147936161466335) )
-  assert( cot(a)    =~ 1.0/tan(a) )
-  assert( sec(a)    =~ 1.0/cos(a) )
-  assert( csc(a)    =~ 1.0/sin(a) )
+  assert( log2(a) =~ (1.16096404744368, 1.59727796468811) )
+
+  assert( sin(a) =~ (3.16577851321617, 1.95960104142161) )
+  assert( cos(a) =~ (2.03272300701967, -3.05189779915180) )
+  assert( tan(a) =~ (0.0338128260798967, 1.0147936161466335) )
+  assert( cot(a) =~ 1.0/tan(a) )
+  assert( sec(a) =~ 1.0/cos(a) )
+  assert( csc(a) =~ 1.0/sin(a) )
   assert( arcsin(a) =~ (0.427078586392476, 1.528570919480998) )
   assert( arccos(a) =~ (1.14371774040242, -1.52857091948100) )
+  assert( arctan(a) =~ (1.338972522294494, 0.402359478108525) )
 
-  assert( cosh(a) =~ (-0.642148124715520, 1.068607421382778) ) 
+  assert( cosh(a) =~ (-0.642148124715520, 1.068607421382778) )
   assert( sinh(a) =~ (-0.489056259041294, 1.403119250622040) )
-
-
+  assert( tanh(a) =~ (1.1667362572409199,-0.243458201185725) )
+  assert( sech(a) =~ 1/cosh(a) )
+  assert( csch(a) =~ 1/sinh(a) )
+  assert( coth(a) =~ 1/tanh(a) )
+  assert( arccosh(a) =~ (1.528570919480998, 1.14371774040242) )
+  assert( arcsinh(a) =~ (1.469351744368185, 1.06344002357775) )
+  assert( arctanh(a) =~ (0.173286795139986, 1.17809724509617) )
+  assert( arcsech(a) =~ arccosh(1/a) )
+  assert( arccsch(a) =~ arcsinh(1/a) )
+  assert( arccoth(a) =~ arctanh(1/a) )
+
+  assert( phase(a) == 1.1071487177940904 )
+  var t = polar(a)
+  assert( rect(t.r, t.phi) =~ a )
+  assert( rect(1.0, 2.0) =~ (-0.4161468365471424, 0.9092974268256817) )
diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim
index ac5fa5dd9..6f2bc4491 100644
--- a/lib/pure/concurrency/cpuinfo.nim
+++ b/lib/pure/concurrency/cpuinfo.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/pure/concurrency/cpuload.nim b/lib/pure/concurrency/cpuload.nim
index 88fb4a064..7ce5e01b7 100644
--- a/lib/pure/concurrency/cpuload.nim
+++ b/lib/pure/concurrency/cpuload.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -78,7 +78,7 @@ proc advice*(s: var ThreadPoolState): ThreadPoolAdvice =
     result = doNothing
   inc s.calls
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   proc busyLoop() =
     while true:
       discard random(80)
diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim
index 0bd97043a..9f1e53fb8 100644
--- a/lib/pure/concurrency/threadpool.nim
+++ b/lib/pure/concurrency/threadpool.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -204,7 +204,7 @@ proc nimFlowVarSignal(fv: FlowVarBase) {.compilerProc.} =
     inc fv.ai.cv.counter
     release(fv.ai.cv.L)
     signal(fv.ai.cv.c)
-  if fv.usesSemaphore: 
+  if fv.usesSemaphore:
     signal(fv.cv)
 
 proc awaitAndThen*[T](fv: FlowVar[T]; action: proc (x: T) {.closure.}) =
diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim
index 6247efed2..9983c4a04 100644
--- a/lib/pure/cookies.nim
+++ b/lib/pure/cookies.nim
@@ -56,6 +56,12 @@ proc setCookie*(key, value: string, expires: TimeInfo,
 when isMainModule:
   var tim = Time(int(getTime()) + 76 * (60 * 60 * 24))
 
-  echo(setCookie("test", "value", tim.getGMTime()))
+  let cookie = setCookie("test", "value", tim.getGMTime())
+  when not defined(testing):
+    echo cookie
+  let start = "Set-Cookie: test=value; Expires="
+  assert cookie[0..start.high] == start
   
-  echo parseCookies("uid=1; kp=2")
+  let table = parseCookies("uid=1; kp=2")
+  assert table["uid"] == "1"
+  assert table["kp"] == "2"
diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim
index 958a4133b..2a6134615 100644
--- a/lib/pure/encodings.nim
+++ b/lib/pure/encodings.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -301,7 +301,7 @@ proc getCurrentEncoding*(): string =
   
 proc open*(destEncoding = "UTF-8", srcEncoding = "CP1252"): EncodingConverter =
   ## opens a converter that can convert from `srcEncoding` to `destEncoding`.
-  ## Raises `EIO` if it cannot fullfill the request.
+  ## Raises `EIO` if it cannot fulfill the request.
   when not defined(windows):
     result = iconvOpen(destEncoding, srcEncoding)
     if result == nil:
@@ -451,7 +451,7 @@ proc convert*(s: string, destEncoding = "UTF-8",
   finally:
     close(c)
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   let
     orig = "öäüß"
     cp1252 = convert(orig, "CP1252", "UTF-8")
diff --git a/lib/pure/events.nim b/lib/pure/events.nim
index 77faa6a66..44e9ed286 100644
--- a/lib/pure/events.nim
+++ b/lib/pure/events.nim
@@ -9,7 +9,7 @@
 
 ## :Author: Alex Mitchell
 ##
-## This module implements an event system that is not dependant on external
+## This module implements an event system that is not dependent on external
 ## graphical toolkits. It was originally called ``NimEE`` because 
 ## it was inspired by Python's PyEE module. There are two ways you can use
 ## events: one is a python-inspired way; the other is more of a C-style way.
diff --git a/lib/pure/fenv.nim b/lib/pure/fenv.nim
index 415ef455e..f8f115ecc 100644
--- a/lib/pure/fenv.nim
+++ b/lib/pure/fenv.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -101,3 +101,81 @@ proc feupdateenv*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
   ## Save current exceptions in temporary storage, install environment
   ## represented by object pointed to by `envp` and raise exceptions
   ## according to saved exceptions.
+
+var FP_RADIX_INTERNAL {. importc: "FLT_RADIX" header: "<float.h>" .} : int
+
+template fpRadix* : int = FP_RADIX_INTERNAL
+  ## The (integer) value of the radix used to represent any floating
+  ## point type on the architecture used to build the program.
+
+var FLT_MANT_DIG {. importc: "FLT_MANT_DIG" header: "<float.h>" .} : int
+var FLT_DIG {. importc: "FLT_DIG" header: "<float.h>" .} : int
+var FLT_MIN_EXP {. importc: "FLT_MIN_EXP" header: "<float.h>" .} : int
+var FLT_MAX_EXP {. importc: "FLT_MAX_EXP" header: "<float.h>" .} : int
+var FLT_MIN_10_EXP {. importc: "FLT_MIN_10_EXP" header: "<float.h>" .} : int
+var FLT_MAX_10_EXP {. importc: "FLT_MAX_10_EXP" header: "<float.h>" .} : int
+var FLT_MIN {. importc: "FLT_MIN" header: "<float.h>" .} : cfloat
+var FLT_MAX {. importc: "FLT_MAX" header: "<float.h>" .} : cfloat
+var FLT_EPSILON {. importc: "FLT_EPSILON" header: "<float.h>" .} : cfloat
+
+var DBL_MANT_DIG {. importc: "DBL_MANT_DIG" header: "<float.h>" .} : int
+var DBL_DIG {. importc: "DBL_DIG" header: "<float.h>" .} : int
+var DBL_MIN_EXP {. importc: "DBL_MIN_EXP" header: "<float.h>" .} : int
+var DBL_MAX_EXP {. importc: "DBL_MAX_EXP" header: "<float.h>" .} : int
+var DBL_MIN_10_EXP {. importc: "DBL_MIN_10_EXP" header: "<float.h>" .} : int
+var DBL_MAX_10_EXP {. importc: "DBL_MAX_10_EXP" header: "<float.h>" .} : int
+var DBL_MIN {. importc: "DBL_MIN" header: "<float.h>" .} : cdouble
+var DBL_MAX {. importc: "DBL_MAX" header: "<float.h>" .} : cdouble
+var DBL_EPSILON {. importc: "DBL_EPSILON" header: "<float.h>" .} : cdouble
+
+template mantissaDigits*(T : typedesc[float32]) : int = FLT_MANT_DIG
+  ## Number of digits (in base ``floatingPointRadix``) in the mantissa
+  ## of 32-bit floating-point numbers.
+template digits*(T : typedesc[float32]) : int = FLT_DIG
+  ## Number of decimal digits that can be represented in a
+  ## 32-bit floating-point type without losing precision.
+template minExponent*(T : typedesc[float32]) : int = FLT_MIN_EXP
+  ## Minimum (negative) exponent for 32-bit floating-point numbers.
+template maxExponent*(T : typedesc[float32]) : int = FLT_MAX_EXP
+  ## Maximum (positive) exponent for 32-bit floating-point numbers.
+template min10Exponent*(T : typedesc[float32]) : int = FLT_MIN_10_EXP
+  ## Minimum (negative) exponent in base 10 for 32-bit floating-point
+  ## numbers.
+template max10Exponent*(T : typedesc[float32]) : int = FLT_MAX_10_EXP
+  ## Maximum (positive) exponent in base 10 for 32-bit floating-point
+  ## numbers.
+template minimumPositiveValue*(T : typedesc[float32]) : float32 = FLT_MIN
+  ## The smallest positive (nonzero) number that can be represented in a
+  ## 32-bit floating-point type.
+template maximumPositiveValue*(T : typedesc[float32]) : float32 = FLT_MAX
+  ## The largest positive number that can be represented in a 32-bit
+  ## floating-point type.
+template epsilon*(T : typedesc[float32]): float32 = FLT_EPSILON
+  ## The difference between 1.0 and the smallest number greater than
+  ## 1.0 that can be represented in a 32-bit floating-point type.
+
+template mantissaDigits*(T : typedesc[float64]) : int = DBL_MANT_DIG
+  ## Number of digits (in base ``floatingPointRadix``) in the mantissa
+  ## of 64-bit floating-point numbers.
+template digits*(T : typedesc[float64]) : int = DBL_DIG
+  ## Number of decimal digits that can be represented in a
+  ## 64-bit floating-point type without losing precision.
+template minExponent*(T : typedesc[float64]) : int = DBL_MIN_EXP
+  ## Minimum (negative) exponent for 64-bit floating-point numbers.
+template maxExponent*(T : typedesc[float64]) : int = DBL_MAX_EXP
+  ## Maximum (positive) exponent for 64-bit floating-point numbers.
+template min10Exponent*(T : typedesc[float64]) : int = DBL_MIN_10_EXP
+  ## Minimum (negative) exponent in base 10 for 64-bit floating-point
+  ## numbers.
+template max10Exponent*(T : typedesc[float64]) : int = DBL_MAX_10_EXP
+  ## Maximum (positive) exponent in base 10 for 64-bit floating-point
+  ## numbers.
+template minimumPositiveValue*(T : typedesc[float64]) : float64 = DBL_MIN
+  ## The smallest positive (nonzero) number that can be represented in a
+  ## 64-bit floating-point type.
+template maximumPositiveValue*(T : typedesc[float64]) : float64 = DBL_MAX
+  ## The largest positive number that can be represented in a 64-bit
+  ## floating-point type.
+template epsilon*(T : typedesc[float64]): float64 = DBL_EPSILON
+  ## The difference between 1.0 and the smallest number greater than
+  ## 1.0 that can be represented in a 64-bit floating-point type.
diff --git a/lib/pure/fsmonitor.nim b/lib/pure/fsmonitor.nim
index bf4aef61c..83779eb9c 100644
--- a/lib/pure/fsmonitor.nim
+++ b/lib/pure/fsmonitor.nim
@@ -29,7 +29,7 @@ type
   FSMonitorObj = object of RootObj
     fd: cint
     handleEvent: proc (m: FSMonitor, ev: MonitorEvent) {.closure.}
-    targets: TTable[cint, string]
+    targets: Table[cint, string]
   
   MonitorEventType* = enum ## Monitor event type
     MonitorAccess,       ## File was accessed.
@@ -64,7 +64,7 @@ type
 const
   MaxEvents = 100
 
-proc newMonitor*(): PFSMonitor =
+proc newMonitor*(): FSMonitor =
   ## Creates a new file system monitor.
   new(result)
   result.targets = initTable[cint, string]()
@@ -72,7 +72,7 @@ proc newMonitor*(): PFSMonitor =
   if result.fd < 0:
     raiseOSError(osLastError())
 
-proc add*(monitor: PFSMonitor, target: string,
+proc add*(monitor: FSMonitor, target: string,
                filters = {MonitorAll}): cint {.discardable.} =
   ## Adds ``target`` which may be a directory or a file to the list of
   ## watched paths of ``monitor``.
@@ -99,14 +99,14 @@ proc add*(monitor: PFSMonitor, target: string,
     raiseOSError(osLastError())
   monitor.targets.add(result, target)
 
-proc del*(monitor: PFSMonitor, wd: cint) =
+proc del*(monitor: FSMonitor, wd: cint) =
   ## Removes watched directory or file as specified by ``wd`` from ``monitor``.
   ##
   ## If ``wd`` is not a part of ``monitor`` an EOS error is raised.
   if inotifyRmWatch(monitor.fd, wd) < 0:
     raiseOSError(osLastError())
 
-proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] =
+proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] =
   result = @[]
   let size = (sizeof(TINotifyEvent)+2000)*MaxEvents
   var buffer = newString(size)
@@ -118,7 +118,7 @@ proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] =
   var i = 0
   while i < le:
     var event = cast[ptr TINotifyEvent](addr(buffer[i]))
-    var mev: TMonitorEvent
+    var mev: MonitorEvent
     mev.wd = event.wd
     if event.len.int != 0:
       let cstr = event.name.addr.cstring
@@ -137,7 +137,7 @@ proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] =
       # Find the MovedFrom event.
       mev.oldPath = movedFrom[event.cookie.cint].old
       mev.newPath = "" # Set later
-      # Delete it from the TTable
+      # Delete it from the Table
       movedFrom.del(event.cookie.cint)
     elif (event.mask.int and IN_ACCESS) != 0: mev.kind = MonitorAccess
     elif (event.mask.int and IN_ATTRIB) != 0: mev.kind = MonitorAttrib
@@ -164,26 +164,26 @@ proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] =
   # If movedFrom events have not been matched with a moveTo. File has
   # been moved to an unwatched location, emit a MonitorDelete.
   for cookie, t in pairs(movedFrom):
-    var mev: TMonitorEvent
+    var mev: MonitorEvent
     mev.kind = MonitorDelete
     mev.wd = t.wd
     mev.name = t.old
     result.add(mev)
 
-proc FSMonitorRead(h: PObject) =
-  var events = PFSMonitor(h).getEvent(PFSMonitor(h).fd)
-  #var newEv: TMonitorEvent
+proc FSMonitorRead(h: RootRef) =
+  var events = FSMonitor(h).getEvent(FSMonitor(h).fd)
+  #var newEv: MonitorEvent
   for ev in events:
-    var target = PFSMonitor(h).targets[ev.wd]
+    var target = FSMonitor(h).targets[ev.wd]
     var newEv = ev
     if newEv.kind == MonitorMoved:
       newEv.oldPath = target / newEv.oldPath
       newEv.newPath = target / newEv.name
     else:
       newEv.fullName = target / newEv.name
-    PFSMonitor(h).handleEvent(PFSMonitor(h), newEv)
+    FSMonitor(h).handleEvent(FSMonitor(h), newEv)
 
-proc toDelegate(m: PFSMonitor): PDelegate =
+proc toDelegate(m: FSMonitor): Delegate =
   result = newDelegate()
   result.deleVal = m
   result.fd = (type(result.fd))(m.fd)
@@ -191,20 +191,20 @@ proc toDelegate(m: PFSMonitor): PDelegate =
   result.handleRead = FSMonitorRead
   result.open = true
 
-proc register*(d: PDispatcher, monitor: PFSMonitor,
-               handleEvent: proc (m: PFSMonitor, ev: TMonitorEvent) {.closure.}) =
+proc register*(d: Dispatcher, monitor: FSMonitor,
+               handleEvent: proc (m: FSMonitor, ev: MonitorEvent) {.closure.}) =
   ## Registers ``monitor`` with dispatcher ``d``.
   monitor.handleEvent = handleEvent
   var deleg = toDelegate(monitor)
   d.register(deleg)
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   proc main =
     var disp = newDispatcher()
     var monitor = newMonitor()
     echo monitor.add("/home/dom/inotifytests/")
     disp.register(monitor,
-      proc (m: PFSMonitor, ev: TMonitorEvent) =
+      proc (m: FSMonitor, ev: MonitorEvent) =
         echo("Got event: ", ev.kind)
         if ev.kind == MonitorMoved:
           echo("From ", ev.oldPath, " to ", ev.newPath)
diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim
index 975eae7e2..dd141eb01 100644
--- a/lib/pure/ftpclient.nim
+++ b/lib/pure/ftpclient.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
@@ -15,8 +15,8 @@ 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>`_. 
-## 
+## by `RFC 959 <http://tools.ietf.org/html/rfc959>`_.
+##
 ## This module provides both a synchronous and asynchronous implementation.
 ## The asynchronous implementation requires you to use the ``asyncFTPClient``
 ## function. You are then required to register the ``AsyncFTPClient`` with a
@@ -27,7 +27,7 @@ from asyncdispatch import PFuture
 ## file transfers, calls to functions which use the command socket will block.
 ##
 ## Here is some example usage of this module:
-## 
+##
 ## .. code-block:: Nim
 ##    var ftp = ftpClient("example.org", user = "user", pass = "pass")
 ##    ftp.connect()
@@ -51,7 +51,7 @@ type
       port*: rawsockets.Port
     else:
       port*: Port
-    
+
     jobInProgress*: bool
     job*: FTPJob[SockType]
 
@@ -91,7 +91,7 @@ type
     of EvLines:
       lines*: string ## Lines that have been transferred.
     of EvRetr, EvStore: ## Retr/Store operation finished.
-      nil 
+      nil
     of EvTransferProgress:
       bytesTotal*: BiggestInt     ## Bytes total.
       bytesFinished*: BiggestInt  ## Bytes transferred.
@@ -107,7 +107,7 @@ type
   EInvalidReply: ReplyError, EFTP: FTPError
 ].}
 
-proc ftpClient*(address: string, port = TPort(21),
+proc ftpClient*(address: string, port = Port(21),
                 user, pass = ""): FtpClient =
   ## Create a ``FtpClient`` object.
   new(result)
@@ -120,10 +120,10 @@ proc ftpClient*(address: string, port = TPort(21),
   result.csock = socket()
   if result.csock == invalidSocket: raiseOSError(osLastError())
 
-template blockingOperation(sock: TSocket, body: stmt) {.immediate.} =
+template blockingOperation(sock: Socket, body: stmt) {.immediate.} =
   body
 
-template blockingOperation(sock: asyncio.PAsyncSocket, body: stmt) {.immediate.} =
+template blockingOperation(sock: asyncio.AsyncSocket, body: stmt) {.immediate.} =
   sock.setBlocking(true)
   body
   sock.setBlocking(false)
@@ -145,14 +145,14 @@ proc send*[T](ftp: FtpBase[T], m: string): TaintedString =
 
 proc assertReply(received: TaintedString, expected: string) =
   if not received.string.startsWith(expected):
-    raise newException(EInvalidReply,
+    raise newException(ReplyError,
                        "Expected reply '$1' got: $2" % [
                        expected, received.string])
 
 proc assertReply(received: TaintedString, expected: varargs[string]) =
   for i in items(expected):
     if received.string.startsWith(i): return
-  raise newException(EInvalidReply,
+  raise newException(ReplyError,
                      "Expected reply '$1' got: $2" %
                      [expected.join("' or '"), received.string])
 
@@ -161,7 +161,7 @@ proc createJob[T](ftp: FtpBase[T],
                           nimcall,gcsafe.},
                cmd: FTPJobType) =
   if ftp.jobInProgress:
-    raise newException(EFTP, "Unable to do two jobs at once.")
+    raise newException(FTPError, "Unable to do two jobs at once.")
   ftp.jobInProgress = true
   new(ftp.job)
   ftp.job.prc = prc
@@ -182,11 +182,11 @@ proc deleteJob[T](ftp: FtpBase[T]) =
     ftp.job.file.close()
   ftp.dsock.close()
 
-proc handleTask(s: PAsyncSocket, ftp: PAsyncFTPClient) =
+proc handleTask(s: AsyncSocket, ftp: AsyncFTPClient) =
   if ftp.jobInProgress:
     if ftp.job.typ in {JRetr, JStore}:
       if epochTime() - ftp.job.lastProgressReport >= 1.0:
-        var r: TFTPEvent
+        var r: FTPEvent
         ftp.job.lastProgressReport = epochTime()
         r.typ = EvTransferProgress
         r.bytesTotal = ftp.job.total
@@ -195,57 +195,57 @@ proc handleTask(s: PAsyncSocket, ftp: PAsyncFTPClient) =
         r.filename = ftp.job.filename
         r.currentJob = ftp.job.typ
         ftp.job.oneSecond = 0
-        ftp.handleEvent(PAsyncFTPClient(ftp), r)
+        ftp.handleEvent(ftp, r)
 
-proc handleWrite(s: PAsyncSocket, ftp: PAsyncFTPClient) =
+proc handleWrite(s: AsyncSocket, ftp: AsyncFTPClient) =
   if ftp.jobInProgress:
     if ftp.job.typ == JStore:
       assert (not ftp.job.prc(ftp, true))
 
-proc handleConnect(s: PAsyncSocket, ftp: PAsyncFTPClient) =
+proc handleConnect(s: AsyncSocket, ftp: AsyncFTPClient) =
   ftp.dsockConnected = true
   assert(ftp.jobInProgress)
   if ftp.job.typ == JStore:
-    s.setHandleWrite(proc (s: PAsyncSocket) = handleWrite(s, ftp))
+    s.setHandleWrite(proc (s: AsyncSocket) = handleWrite(s, ftp))
   else:
     s.delHandleWrite()
 
-proc handleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
+proc handleRead(s: AsyncSocket, ftp: AsyncFTPClient) =
   assert ftp.jobInProgress
   assert ftp.job.typ != JStore
-  # This can never return true, because it shouldn't check for code 
+  # This can never return true, because it shouldn't check for code
   # 226 from csock.
   assert(not ftp.job.prc(ftp, true))
 
 proc pasv[T](ftp: FtpBase[T]) =
   ## Negotiate a data connection.
-  when T is TSocket:
+  when T is Socket:
     ftp.dsock = socket()
     if ftp.dsock == invalidSocket: raiseOSError(osLastError())
-  elif T is PAsyncSocket:
+  elif T is AsyncSocket:
     ftp.dsock = asyncSocket()
     ftp.dsock.handleRead =
-      proc (s: PAsyncSocket) =
+      proc (s: AsyncSocket) =
         handleRead(s, ftp)
     ftp.dsock.handleConnect =
-      proc (s: PAsyncSocket) =
+      proc (s: AsyncSocket) =
         handleConnect(s, ftp)
     ftp.dsock.handleTask =
-      proc (s: PAsyncSocket) =
+      proc (s: AsyncSocket) =
         handleTask(s, ftp)
     ftp.disp.register(ftp.dsock)
   else:
     {.fatal: "Incorrect socket instantiation".}
-  
+
   var pasvMsg = 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 ip = nums[0.. ^3]
+  var port = nums[^2.. ^1]
   var properPort = port[0].parseInt()*256+port[1].parseInt()
-  ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
-  when T is PAsyncSocket:
+  ftp.dsock.connect(ip.join("."), Port(properPort.toU16))
+  when T is AsyncSocket:
     ftp.dsockConnected = false
   else:
     ftp.dsockConnected = true
@@ -255,10 +255,10 @@ proc normalizePathSep(path: string): string =
 
 proc connect*[T](ftp: FtpBase[T]) =
   ## Connect to the FTP server specified by ``ftp``.
-  when T is PAsyncSocket:
+  when T is AsyncSocket:
     blockingOperation(ftp.csock):
       ftp.csock.connect(ftp.address, ftp.port)
-  elif T is TSocket:
+  elif T is Socket:
     ftp.csock.connect(ftp.address, ftp.port)
   else:
     {.fatal: "Incorrect socket instantiation".}
@@ -292,13 +292,13 @@ proc getLines[T](ftp: FtpBase[T], async: bool = false): bool =
   ## It doesn't if `async` is true, because it doesn't check for 226 then.
   if ftp.dsockConnected:
     var r = TaintedString""
-    when T is PAsyncSocket:
+    when T is AsyncSocket:
       if ftp.asyncDSock.readLine(r):
         if r.string == "":
           ftp.dsockConnected = false
         else:
           ftp.job.lines.add(r.string & "\n")
-    elif T is TSocket:
+    elif T is Socket:
       assert(not async)
       ftp.dsock.readLine(r)
       if r.string == "":
@@ -307,9 +307,9 @@ proc getLines[T](ftp: FtpBase[T], async: bool = false): bool =
         ftp.job.lines.add(r.string & "\n")
     else:
       {.fatal: "Incorrect socket instantiation".}
-  
+
   if not async:
-    var readSocks: seq[TSocket] = @[ftp.csock]
+    var readSocks: seq[Socket] = @[ftp.csock]
     # This is only needed here. Asyncio gets this socket...
     blockingOperation(ftp.csock):
       if readSocks.select(1) != 0 and ftp.csock in readSocks:
@@ -372,7 +372,7 @@ proc createDir*[T](ftp: FtpBase[T], dir: string, recursive: bool = false) =
     assertReply reply, "257"
 
 proc chmod*[T](ftp: FtpBase[T], path: string,
-            permissions: set[TFilePermission]) =
+            permissions: set[FilePermission]) =
   ## Changes permission of ``path`` to ``permissions``.
   var userOctal = 0
   var groupOctal = 0
@@ -396,7 +396,7 @@ proc chmod*[T](ftp: FtpBase[T], path: string,
 proc list*[T](ftp: FtpBase[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 
+  ## immediately and it will be your job to call asyncio's
   ## ``poll`` to progress this operation.
   ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
@@ -417,7 +417,7 @@ proc retrText*[T](ftp: FtpBase[T], file: string, async = false): string =
   ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
   assertReply ftp.send("RETR " & file.normalizePathSep), ["125", "150"]
-  
+
   if not async:
     while not ftp.job.prc(ftp, false): discard
     result = ftp.job.lines
@@ -431,12 +431,12 @@ proc getFile[T](ftp: FtpBase[T], async = false): bool =
     var bytesRead = 0
     var returned = false
     if async:
-      when T is TSocket:
-        raise newException(EFTP, "FTPClient must be async.")
+      when T is Socket:
+        raise newException(FTPError, "FTPClient must be async.")
       else:
         bytesRead = ftp.dsock.recvAsync(r, BufferSize)
         returned = bytesRead != -1
-    else: 
+    else:
       bytesRead = ftp.dsock.recv(r, BufferSize)
       returned = true
     let r2 = r.string
@@ -447,9 +447,9 @@ proc getFile[T](ftp: FtpBase[T], async = false): bool =
     elif returned and r2 == "":
       ftp.dsockConnected = false
 
-  when T is TSocket:
+  when T is Socket:
     if not async:
-      var readSocks: seq[TSocket] = @[ftp.csock]
+      var readSocks: seq[Socket] = @[ftp.csock]
       blockingOperation(ftp.csock):
         if readSocks.select(1) != 0 and ftp.csock in readSocks:
           assertReply ftp.expectReply(), "226"
@@ -458,7 +458,7 @@ proc getFile[T](ftp: FtpBase[T], async = false): bool =
 proc retrFile*[T](ftp: FtpBase[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 
+  ## 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[T], JRetr)
@@ -467,11 +467,11 @@ proc retrFile*[T](ftp: FtpBase[T], file, dest: string, async = false) =
   var reply = ftp.send("RETR " & file.normalizePathSep)
   assertReply reply, ["125", "150"]
   if {'(', ')'} notin reply.string:
-    raise newException(EInvalidReply, "Reply has no file size.")
+    raise newException(ReplyError, "Reply has no file size.")
   var fileSize: BiggestInt
   if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0:
-    raise newException(EInvalidReply, "Reply has no file size.")
-    
+    raise newException(ReplyError, "Reply has no file size.")
+
   ftp.job.total = fileSize
   ftp.job.lastProgressReport = epochTime()
   ftp.job.filename = file.normalizePathSep
@@ -488,7 +488,7 @@ proc doUpload[T](ftp: FtpBase[T], async = false): bool =
       if bytesSent == ftp.job.toStore.len:
         ftp.job.toStore = ""
       elif bytesSent != ftp.job.toStore.len and bytesSent != 0:
-        ftp.job.toStore = ftp.job.toStore[bytesSent .. -1]
+        ftp.job.toStore = ftp.job.toStore[bytesSent .. ^1]
       ftp.job.progress.inc(bytesSent)
       ftp.job.oneSecond.inc(bytesSent)
     else:
@@ -499,12 +499,12 @@ proc doUpload[T](ftp: FtpBase[T], async = false): bool =
         # File finished uploading.
         ftp.dsock.close()
         ftp.dsockConnected = false
-  
+
         if not async:
           assertReply ftp.expectReply(), "226"
           return true
         return false
-    
+
       if not async:
         ftp.dsock.send(s)
       else:
@@ -512,9 +512,9 @@ proc doUpload[T](ftp: FtpBase[T], async = false): bool =
         if bytesSent == 0:
           ftp.job.toStore.add(s)
         elif bytesSent != s.len:
-          ftp.job.toStore.add(s[bytesSent .. -1])
+          ftp.job.toStore.add(s[bytesSent .. ^1])
         len = bytesSent
-      
+
       ftp.job.progress.inc(len)
       ftp.job.oneSecond.inc(len)
 
@@ -522,8 +522,8 @@ proc store*[T](ftp: FtpBase[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 
+  ## 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[T], JStore)
   ftp.job.file = open(file)
@@ -531,7 +531,7 @@ proc store*[T](ftp: FtpBase[T], file, dest: string, async = false) =
   ftp.job.lastProgressReport = epochTime()
   ftp.job.filename = file
   ftp.pasv()
-  
+
   assertReply ftp.send("STOR " & dest.normalizePathSep), ["125", "150"]
 
   if not async:
@@ -545,10 +545,10 @@ proc close*[T](ftp: FtpBase[T]) =
   ftp.csock.close()
   ftp.dsock.close()
 
-proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
+proc csockHandleRead(s: AsyncSocket, ftp: AsyncFTPClient) =
   if ftp.jobInProgress:
     assertReply ftp.expectReply(), "226" # Make sure the transfer completed.
-    var r: TFTPEvent
+    var r: FTPEvent
     case ftp.job.typ
     of JRetrText:
       r.typ = EvLines
@@ -557,21 +557,21 @@ proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
       r.typ = EvRetr
       r.filename = ftp.job.filename
       if ftp.job.progress != ftp.job.total:
-        raise newException(EFTP, "Didn't download full file.")
+        raise newException(FTPError, "Didn't download full file.")
     of JStore:
       r.typ = EvStore
       r.filename = ftp.job.filename
       if ftp.job.progress != ftp.job.total:
-        raise newException(EFTP, "Didn't upload full file.")
+        raise newException(FTPError, "Didn't upload full file.")
     ftp.deleteJob()
-    
+
     ftp.handleEvent(ftp, r)
 
-proc asyncFTPClient*(address: string, port = TPort(21),
+proc asyncFTPClient*(address: string, port = Port(21),
                      user, pass = "",
-    handleEvent: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure,gcsafe.} = 
-      (proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = discard)): PAsyncFTPClient =
-  ## Create a ``PAsyncFTPClient`` object.
+    handleEvent: proc (ftp: AsyncFTPClient, ev: FTPEvent) {.closure,gcsafe.} =
+      (proc (ftp: AsyncFTPClient, ev: FTPEvent) = discard)): AsyncFTPClient =
+  ## Create a ``AsyncFTPClient`` object.
   ##
   ## Use this if you want to use asyncio's dispatcher.
   var dres: AsyncFtpClient
@@ -588,12 +588,12 @@ proc asyncFTPClient*(address: string, port = TPort(21),
       csockHandleRead(s, dres)
   result = dres
 
-proc register*(d: PDispatcher, ftp: PAsyncFTPClient): PDelegate {.discardable.} =
+proc register*(d: Dispatcher, ftp: AsyncFTPClient): Delegate {.discardable.} =
   ## Registers ``ftp`` with dispatcher ``d``.
   ftp.disp = d
   return ftp.disp.register(ftp.csock)
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   proc main =
     var d = newDispatcher()
     let hev =
@@ -617,7 +617,7 @@ when isMainModule:
           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()
@@ -629,7 +629,7 @@ when isMainModule:
       if not d.poll(): break
   main()
 
-when isMainModule and false:
+when not defined(testing) and isMainModule:
   var ftp = ftpClient("example.com", user = "foo", pass = "bar")
   ftp.connect()
   echo ftp.pwd()
diff --git a/lib/pure/future.nim b/lib/pure/future.nim
index a0c1b5c2d..661afd7b3 100644
--- a/lib/pure/future.nim
+++ b/lib/pure/future.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -12,7 +12,7 @@
 
 import macros
 
-proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} =
+proc createProcType(p, b: NimNode): NimNode {.compileTime.} =
   #echo treeRepr(p)
   #echo treeRepr(b)
   result = newNimNode(nnkProcTy)
@@ -44,7 +44,7 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} =
     formalParams.add identDefs
   else:
     error("Incorrect type list in proc type declaration.")
-  
+
   result.add formalParams
   result.add newEmptyNode()
   #echo(treeRepr(result))
@@ -59,10 +59,10 @@ macro `=>`*(p, b: expr): expr {.immediate.} =
   ##     f(2, 2)
   ##
   ##   passTwoAndTwo((x, y) => x + y) # 4
-  
+
   #echo treeRepr(p)
   #echo(treeRepr(b))
-  var params: seq[PNimrodNode] = @[newIdentNode("auto")]
+  var params: seq[NimNode] = @[newIdentNode("auto")]
 
   case p.kind
   of nnkPar:
@@ -118,7 +118,7 @@ macro `->`*(p, b: expr): expr {.immediate.} =
   ##
   ##   proc pass2(f: (float, float) -> float): float =
   ##     f(2, 2)
-  ##   
+  ##
   ##   # is the same as:
   ##
   ##   proc pass2(f: proc (x, y: float): float): float =
@@ -155,7 +155,6 @@ macro `[]`*(lc: ListComprehension, comp, typ: expr): expr =
 
   for i in countdown(comp[2].len-1, 0):
     let x = comp[2][i]
-    expectKind(x, nnkInfix)
     expectMinLen(x, 1)
     if x[0].kind == nnkIdent and $x[0].ident == "<-":
       expectLen(x, 3)
diff --git a/lib/pure/gentabs.nim b/lib/pure/gentabs.nim
index a6128efc9..84d0a44de 100644
--- a/lib/pure/gentabs.nim
+++ b/lib/pure/gentabs.nim
@@ -9,7 +9,7 @@
 
 ## The ``gentabs`` module implements an efficient hash table that is a
 ## key-value mapping. The keys are required to be strings, but the values
-## may be any Nim or user defined type. This module supports matching 
+## may be any Nim or user defined type. This module supports matching
 ## of keys in case-sensitive, case-insensitive and style-insensitive modes.
 
 {.deprecated.}
@@ -22,7 +22,7 @@ type
     modeCaseSensitive,     ## case sensitive matching of keys
     modeCaseInsensitive,   ## case insensitive matching of keys
     modeStyleInsensitive   ## style sensitive matching of keys
-    
+
   TGenKeyValuePair[T] = tuple[key: string, val: T]
   TGenKeyValuePairSeq[T] = seq[TGenKeyValuePair[T]]
   TGenTable*[T] = object of RootObj
@@ -83,7 +83,7 @@ proc rawGet[T](tbl: PGenTable[T], key: string): int =
     h = nextTry(h, high(tbl.data))
   result = - 1
 
-proc rawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T], 
+proc rawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T],
                   key: string, val: T) =
   var h: THash
   h = myhash(tbl, key) and high(data)
@@ -96,7 +96,7 @@ proc enlarge[T](tbl: PGenTable[T]) =
   var n: TGenKeyValuePairSeq[T]
   newSeq(n, len(tbl.data) * growthFactor)
   for i in countup(0, high(tbl.data)):
-    if not isNil(tbl.data[i].key): 
+    if not isNil(tbl.data[i].key):
       rawInsert[T](tbl, n, tbl.data[i].key, tbl.data[i].val)
   swap(tbl.data, n)
 
@@ -141,20 +141,20 @@ when isMainModule:
   assert(not x.hasKey("NOPE"))    # ...but key "NOPE" is not in the table.
   for k,v in pairs(x):            # make sure the 'pairs' iterator works
     assert(x[k]==v)
-  
+
   #
   # Verify a table of user-defined types
   #
   type
     TMyType = tuple[first, second: string] # a pair of strings
-  
+
   var y = newGenTable[TMyType](modeCaseInsensitive) # hash table where each
                                                     # value is TMyType tuple
-  
+
   #var junk: TMyType = ("OK", "Here")
-  
+
   #echo junk.first, " ", junk.second
-  
+
   y["Hello"] = ("Hello", "World")
   y["Goodbye"] = ("Goodbye", "Everyone")
   #y["Hello"] = TMyType( ("Hello", "World") )
@@ -163,31 +163,44 @@ when isMainModule:
   assert( not isNil(y["Hello"].first) )
   assert( y["Hello"].first == "Hello" )
   assert( y["Hello"].second == "World" )
-    
+
   #
   # Verify table of tables
   #
-  var z: PGenTable[ PGenTable[int] ] # hash table where each value is 
+  var z: PGenTable[ PGenTable[int] ] # hash table where each value is
                                      # a hash table of ints
-  
+
   z = newGenTable[PGenTable[int]](modeCaseInsensitive)
   z["first"] = newGenTable[int](modeCaseInsensitive)
   z["first"]["one"] = 1
   z["first"]["two"] = 2
   z["first"]["three"] = 3
-  
+
   z["second"] = newGenTable[int](modeCaseInsensitive)
   z["second"]["red"] = 10
   z["second"]["blue"] = 20
-  
+
   assert(len(z) == 2)               # length of outer table
   assert(len(z["first"]) == 3)      # length of "first" table
   assert(len(z["second"]) == 2)     # length of "second" table
   assert( z["first"]["one"] == 1)   # retrieve from first inner table
   assert( z["second"]["red"] == 10) # retrieve from second inner table
-  
-  for k,v in pairs(z):
-    echo( "$# ($#) ->" % [k,$len(v)] )
-    #for k2,v2 in pairs(v):
-    #  echo( "   $# <-> $#" % [k2,$v2] )
-  echo()
+
+  when false:
+    # disabled: depends on hash order:
+    var output = ""
+    for k, v in pairs(z):
+      output.add( "$# ($#) ->\L" % [k,$len(v)] )
+      for k2,v2 in pairs(v):
+        output.add( "  $# <-> $#\L" % [k2,$v2] )
+
+    let expected = unindent """
+      first (3) ->
+        two <-> 2
+        three <-> 3
+        one <-> 1
+      second (2) ->
+        red <-> 10
+        blue <-> 20
+    """
+    assert output == expected
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index 30daaf2dc..a16342d44 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -33,8 +33,8 @@
 ##  proc hash(x: Something): THash =
 ##    ## Computes a THash from `x`.
 ##    var h: THash = 0
-##    h = h &! hash(x.foo)
-##    h = h &! hash(x.bar)
+##    h = h !& hash(x.foo)
+##    h = h !& hash(x.bar)
 ##    result = !$h
 
 import 
diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim
index 4852ed50d..e6c15371e 100644
--- a/lib/pure/htmlgen.nim
+++ b/lib/pure/htmlgen.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -12,7 +12,7 @@
 ## as ``from htmlgen import nil`` and then fully qualify the macros.
 ##
 ##
-## This module implements a simple `XML`:idx: and `HTML`:idx: code 
+## This module implements a simple `XML`:idx: and `HTML`:idx: code
 ## generator. Each commonly used HTML tag has a corresponding macro
 ## that generates a string with its HTML representation.
 ##
@@ -21,9 +21,9 @@
 ## .. code-block:: Nim
 ##   var nim = "Nim"
 ##   echo h1(a(href="http://nim-lang.org", nim))
-##  
+##
 ## Writes the string::
-##   
+##
 ##   <h1><a href="http://nim-lang.org">Nim</a></h1>
 ##
 
@@ -36,16 +36,16 @@ const
     "onmouseover onmousemove onmouseout onkeypress onkeydown onkeyup "
   commonAttr* = coreAttr & eventAttr
 
-proc getIdent(e: PNimrodNode): string {.compileTime.} = 
+proc getIdent(e: NimNode): string {.compileTime.} =
   case e.kind
   of nnkIdent: result = normalize($e.ident)
-  of nnkAccQuoted: 
+  of nnkAccQuoted:
     result = getIdent(e[0])
     for i in 1 .. e.len-1:
       result.add getIdent(e[i])
   else: error("cannot extract identifier from node: " & toStrLit(e).strVal)
 
-proc delete[T](s: var seq[T], attr: T): bool = 
+proc delete[T](s: var seq[T], attr: T): bool =
   var idx = find(s, attr)
   if idx >= 0:
     var L = s.len
@@ -53,10 +53,10 @@ proc delete[T](s: var seq[T], attr: T): bool =
     setLen(s, L-1)
     result = true
 
-proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "",
-    isLeaf = false): PNimrodNode {.compileTime.} =
+proc xmlCheckedTag*(e: NimNode, tag: string, optAttr = "", reqAttr = "",
+    isLeaf = false): NimNode {.compileTime.} =
   ## use this procedure to define a new XML tag
-  
+
   # copy the attributes; when iterating over them these lists
   # will be modified, so that each attribute is only given one value
   var req = split(reqAttr)
@@ -66,7 +66,7 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "",
   result.add(newStrLitNode(tag))
   # first pass over attributes:
   for i in 1..e.len-1:
-    if e[i].kind == nnkExprEqExpr: 
+    if e[i].kind == nnkExprEqExpr:
       var name = getIdent(e[i][0])
       if delete(req, name) or delete(opt, name):
         result.add(newStrLitNode(" "))
@@ -81,7 +81,7 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "",
     error(req[0] & " attribute for '" & tag & "' element expected")
   if isLeaf:
     for i in 1..e.len-1:
-      if e[i].kind != nnkExprEqExpr: 
+      if e[i].kind != nnkExprEqExpr:
         error("element " & tag & " cannot be nested")
     result.add(newStrLitNode(" />"))
   else:
@@ -95,395 +95,396 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "",
   result = nestList(!"&", result)
 
 
-macro a*(e: expr): expr {.immediate.} = 
+macro a*(e: expr): expr {.immediate.} =
   ## generates the HTML ``a`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "a", "href charset type hreflang rel rev " &
     "accesskey tabindex" & commonAttr)
 
-macro acronym*(e: expr): expr {.immediate.} = 
+macro acronym*(e: expr): expr {.immediate.} =
   ## generates the HTML ``acronym`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "acronym", commonAttr)
 
-macro address*(e: expr): expr {.immediate.} = 
+macro address*(e: expr): expr {.immediate.} =
   ## generates the HTML ``address`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "address", commonAttr)
 
-macro area*(e: expr): expr {.immediate.} = 
+macro area*(e: expr): expr {.immediate.} =
   ## generates the HTML ``area`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "area", "shape coords href nohref" &
     " accesskey tabindex" & commonAttr, "alt", true)
 
-macro b*(e: expr): expr {.immediate.} = 
+macro b*(e: expr): expr {.immediate.} =
   ## generates the HTML ``b`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "b", commonAttr)
 
-macro base*(e: expr): expr {.immediate.} = 
+macro base*(e: expr): expr {.immediate.} =
   ## generates the HTML ``base`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "base", "", "href", true)
 
-macro big*(e: expr): expr {.immediate.} = 
+macro big*(e: expr): expr {.immediate.} =
   ## generates the HTML ``big`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "big", commonAttr)
 
-macro blockquote*(e: expr): expr {.immediate.} = 
+macro blockquote*(e: expr): expr {.immediate.} =
   ## generates the HTML ``blockquote`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "blockquote", " cite" & commonAttr)
 
-macro body*(e: expr): expr {.immediate.} = 
+macro body*(e: expr): expr {.immediate.} =
   ## generates the HTML ``body`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "body", commonAttr)
 
-macro br*(e: expr): expr {.immediate.} = 
+macro br*(e: expr): expr {.immediate.} =
   ## generates the HTML ``br`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "br", "", "", true)
 
-macro button*(e: expr): expr {.immediate.} = 
+macro button*(e: expr): expr {.immediate.} =
   ## generates the HTML ``button`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "button", "accesskey tabindex " &
     "disabled name type value" & commonAttr)
 
-macro caption*(e: expr): expr {.immediate.} = 
+macro caption*(e: expr): expr {.immediate.} =
   ## generates the HTML ``caption`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "caption", commonAttr)
 
-macro cite*(e: expr): expr {.immediate.} = 
+macro cite*(e: expr): expr {.immediate.} =
   ## generates the HTML ``cite`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "cite", commonAttr)
 
-macro code*(e: expr): expr {.immediate.} = 
+macro code*(e: expr): expr {.immediate.} =
   ## generates the HTML ``code`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "code", commonAttr)
 
-macro col*(e: expr): expr {.immediate.} = 
+macro col*(e: expr): expr {.immediate.} =
   ## generates the HTML ``col`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "col", "span align valign" & commonAttr, "", true)
 
-macro colgroup*(e: expr): expr {.immediate.} = 
+macro colgroup*(e: expr): expr {.immediate.} =
   ## generates the HTML ``colgroup`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "colgroup", "span align valign" & commonAttr)
 
-macro dd*(e: expr): expr {.immediate.} = 
+macro dd*(e: expr): expr {.immediate.} =
   ## generates the HTML ``dd`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "dd", commonAttr)
 
-macro del*(e: expr): expr {.immediate.} = 
+macro del*(e: expr): expr {.immediate.} =
   ## generates the HTML ``del`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "del", "cite datetime" & commonAttr)
 
-macro dfn*(e: expr): expr {.immediate.} = 
+macro dfn*(e: expr): expr {.immediate.} =
   ## generates the HTML ``dfn`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "dfn", commonAttr)
 
-macro `div`*(e: expr): expr {.immediate.} = 
+macro `div`*(e: expr): expr {.immediate.} =
   ## generates the HTML ``div`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "div", commonAttr)
 
-macro dl*(e: expr): expr {.immediate.} = 
+macro dl*(e: expr): expr {.immediate.} =
   ## generates the HTML ``dl`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "dl", commonAttr)
 
-macro dt*(e: expr): expr {.immediate.} = 
+macro dt*(e: expr): expr {.immediate.} =
   ## generates the HTML ``dt`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "dt", commonAttr)
 
-macro em*(e: expr): expr {.immediate.} = 
+macro em*(e: expr): expr {.immediate.} =
   ## generates the HTML ``em`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "em", commonAttr)
 
-macro fieldset*(e: expr): expr {.immediate.} = 
+macro fieldset*(e: expr): expr {.immediate.} =
   ## generates the HTML ``fieldset`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "fieldset", commonAttr)
 
-macro form*(e: expr): expr {.immediate.} = 
+macro form*(e: expr): expr {.immediate.} =
   ## generates the HTML ``form`` element.
   let e = callsite()
-  result = xmlCheckedTag(e, "form", "method encype accept accept-charset" & 
+  result = xmlCheckedTag(e, "form", "method encype accept accept-charset" &
     commonAttr, "action")
 
-macro h1*(e: expr): expr {.immediate.} = 
+macro h1*(e: expr): expr {.immediate.} =
   ## generates the HTML ``h1`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "h1", commonAttr)
 
-macro h2*(e: expr): expr {.immediate.} = 
+macro h2*(e: expr): expr {.immediate.} =
   ## generates the HTML ``h2`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "h2", commonAttr)
 
-macro h3*(e: expr): expr {.immediate.} = 
+macro h3*(e: expr): expr {.immediate.} =
   ## generates the HTML ``h3`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "h3", commonAttr)
 
-macro h4*(e: expr): expr {.immediate.} = 
+macro h4*(e: expr): expr {.immediate.} =
   ## generates the HTML ``h4`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "h4", commonAttr)
 
-macro h5*(e: expr): expr {.immediate.} = 
+macro h5*(e: expr): expr {.immediate.} =
   ## generates the HTML ``h5`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "h5", commonAttr)
 
-macro h6*(e: expr): expr {.immediate.} = 
+macro h6*(e: expr): expr {.immediate.} =
   ## generates the HTML ``h6`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "h6", commonAttr)
 
-macro head*(e: expr): expr {.immediate.} = 
+macro head*(e: expr): expr {.immediate.} =
   ## generates the HTML ``head`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "head", "profile")
 
-macro html*(e: expr): expr {.immediate.} = 
+macro html*(e: expr): expr {.immediate.} =
   ## generates the HTML ``html`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "html", "xmlns", "")
 
-macro hr*(): expr {.immediate.} = 
+macro hr*(): expr {.immediate.} =
   ## generates the HTML ``hr`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "hr", commonAttr, "", true)
 
-macro i*(e: expr): expr {.immediate.} = 
+macro i*(e: expr): expr {.immediate.} =
   ## generates the HTML ``i`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "i", commonAttr)
 
-macro img*(e: expr): expr {.immediate.} = 
+macro img*(e: expr): expr {.immediate.} =
   ## generates the HTML ``img`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "img", "longdesc height width", "src alt", true)
 
-macro input*(e: expr): expr {.immediate.} = 
+macro input*(e: expr): expr {.immediate.} =
   ## generates the HTML ``input`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "input", "name type value checked maxlength src" &
     " alt accept disabled readonly accesskey tabindex" & commonAttr, "", true)
 
-macro ins*(e: expr): expr {.immediate.} = 
+macro ins*(e: expr): expr {.immediate.} =
   ## generates the HTML ``ins`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "ins", "cite datetime" & commonAttr)
 
-macro kbd*(e: expr): expr {.immediate.} = 
+macro kbd*(e: expr): expr {.immediate.} =
   ## generates the HTML ``kbd`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "kbd", commonAttr)
 
-macro label*(e: expr): expr {.immediate.} = 
+macro label*(e: expr): expr {.immediate.} =
   ## generates the HTML ``label`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "label", "for accesskey" & commonAttr)
 
-macro legend*(e: expr): expr {.immediate.} = 
+macro legend*(e: expr): expr {.immediate.} =
   ## generates the HTML ``legend`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "legend", "accesskey" & commonAttr)
 
-macro li*(e: expr): expr {.immediate.} = 
+macro li*(e: expr): expr {.immediate.} =
   ## generates the HTML ``li`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "li", commonAttr)
 
-macro link*(e: expr): expr {.immediate.} = 
+macro link*(e: expr): expr {.immediate.} =
   ## generates the HTML ``link`` element.
   let e = callsite()
-  result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" & 
+  result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" &
     commonAttr, "", true)
 
-macro map*(e: expr): expr {.immediate.} = 
+macro map*(e: expr): expr {.immediate.} =
   ## generates the HTML ``map`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "map", "class title" & eventAttr, "id", false)
 
-macro meta*(e: expr): expr {.immediate.} = 
+macro meta*(e: expr): expr {.immediate.} =
   ## generates the HTML ``meta`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "meta", "name http-equiv scheme", "content", true)
 
-macro noscript*(e: expr): expr {.immediate.} = 
+macro noscript*(e: expr): expr {.immediate.} =
   ## generates the HTML ``noscript`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "noscript", commonAttr)
 
-macro `object`*(e: expr): expr {.immediate.} = 
+macro `object`*(e: expr): expr {.immediate.} =
   ## generates the HTML ``object`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "object", "classid data codebase declare type " &
     "codetype archive standby width height name tabindex" & commonAttr)
 
-macro ol*(e: expr): expr {.immediate.} = 
+macro ol*(e: expr): expr {.immediate.} =
   ## generates the HTML ``ol`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "ol", commonAttr)
 
-macro optgroup*(e: expr): expr {.immediate.} = 
+macro optgroup*(e: expr): expr {.immediate.} =
   ## generates the HTML ``optgroup`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "optgroup", "disabled" & commonAttr, "label", false)
 
-macro option*(e: expr): expr {.immediate.} = 
+macro option*(e: expr): expr {.immediate.} =
   ## generates the HTML ``option`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "option", "selected value" & commonAttr)
 
-macro p*(e: expr): expr {.immediate.} = 
+macro p*(e: expr): expr {.immediate.} =
   ## generates the HTML ``p`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "p", commonAttr)
 
-macro param*(e: expr): expr {.immediate.} = 
+macro param*(e: expr): expr {.immediate.} =
   ## generates the HTML ``param`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "param", "value id type valuetype", "name", true)
 
-macro pre*(e: expr): expr {.immediate.} = 
+macro pre*(e: expr): expr {.immediate.} =
   ## generates the HTML ``pre`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "pre", commonAttr)
 
-macro q*(e: expr): expr {.immediate.} = 
+macro q*(e: expr): expr {.immediate.} =
   ## generates the HTML ``q`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "q", "cite" & commonAttr)
 
-macro samp*(e: expr): expr {.immediate.} = 
+macro samp*(e: expr): expr {.immediate.} =
   ## generates the HTML ``samp`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "samp", commonAttr)
 
-macro script*(e: expr): expr {.immediate.} = 
+macro script*(e: expr): expr {.immediate.} =
   ## generates the HTML ``script`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "script", "src charset defer", "type", false)
 
-macro select*(e: expr): expr {.immediate.} = 
+macro select*(e: expr): expr {.immediate.} =
   ## generates the HTML ``select`` element.
   let e = callsite()
-  result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" & 
+  result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" &
     commonAttr)
 
-macro small*(e: expr): expr {.immediate.} = 
+macro small*(e: expr): expr {.immediate.} =
   ## generates the HTML ``small`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "small", commonAttr)
 
-macro span*(e: expr): expr {.immediate.} = 
+macro span*(e: expr): expr {.immediate.} =
   ## generates the HTML ``span`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "span", commonAttr)
 
-macro strong*(e: expr): expr {.immediate.} = 
+macro strong*(e: expr): expr {.immediate.} =
   ## generates the HTML ``strong`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "strong", commonAttr)
 
-macro style*(e: expr): expr {.immediate.} = 
+macro style*(e: expr): expr {.immediate.} =
   ## generates the HTML ``style`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "style", "media title", "type")
 
-macro sub*(e: expr): expr {.immediate.} = 
+macro sub*(e: expr): expr {.immediate.} =
   ## generates the HTML ``sub`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "sub", commonAttr)
 
-macro sup*(e: expr): expr {.immediate.} = 
+macro sup*(e: expr): expr {.immediate.} =
   ## generates the HTML ``sup`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "sup", commonAttr)
 
-macro table*(e: expr): expr {.immediate.} = 
+macro table*(e: expr): expr {.immediate.} =
   ## generates the HTML ``table`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "table", "summary border cellpadding cellspacing" &
     " frame rules width" & commonAttr)
 
-macro tbody*(e: expr): expr {.immediate.} = 
+macro tbody*(e: expr): expr {.immediate.} =
   ## generates the HTML ``tbody`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "tbody", "align valign" & commonAttr)
 
-macro td*(e: expr): expr {.immediate.} = 
+macro td*(e: expr): expr {.immediate.} =
   ## generates the HTML ``td`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "td", "colspan rowspan abbr axis headers scope" &
     " align valign" & commonAttr)
 
-macro textarea*(e: expr): expr {.immediate.} = 
+macro textarea*(e: expr): expr {.immediate.} =
   ## generates the HTML ``textarea`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "textarea", " name disabled readonly accesskey" &
     " tabindex" & commonAttr, "rows cols", false)
 
-macro tfoot*(e: expr): expr {.immediate.} = 
+macro tfoot*(e: expr): expr {.immediate.} =
   ## generates the HTML ``tfoot`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "tfoot", "align valign" & commonAttr)
 
-macro th*(e: expr): expr {.immediate.} = 
+macro th*(e: expr): expr {.immediate.} =
   ## generates the HTML ``th`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "th", "colspan rowspan abbr axis headers scope" &
     " align valign" & commonAttr)
 
-macro thead*(e: expr): expr {.immediate.} = 
+macro thead*(e: expr): expr {.immediate.} =
   ## generates the HTML ``thead`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "thead", "align valign" & commonAttr)
 
-macro title*(e: expr): expr {.immediate.} = 
+macro title*(e: expr): expr {.immediate.} =
   ## generates the HTML ``title`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "title")
 
-macro tr*(e: expr): expr {.immediate.} = 
+macro tr*(e: expr): expr {.immediate.} =
   ## generates the HTML ``tr`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "tr", "align valign" & commonAttr)
 
-macro tt*(e: expr): expr {.immediate.} = 
+macro tt*(e: expr): expr {.immediate.} =
   ## generates the HTML ``tt`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "tt", commonAttr)
 
-macro ul*(e: expr): expr {.immediate.} = 
+macro ul*(e: expr): expr {.immediate.} =
   ## generates the HTML ``ul`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "ul", commonAttr)
 
-macro `var`*(e: expr): expr {.immediate.} = 
+macro `var`*(e: expr): expr {.immediate.} =
   ## generates the HTML ``var`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "var", commonAttr)
 
 when isMainModule:
-  var nim = "Nim"
-  echo h1(a(href="http://nim-lang.org", nim))
-  echo form(action="test", `accept-charset` = "Content-Type")
-
+  let nim = "Nim"
+  assert h1(a(href="http://nim-lang.org", nim)) ==
+    """<h1><a href="http://nim-lang.org">Nim</a></h1>"""
+  assert form(action="test", `accept-charset` = "Content-Type") ==
+    """<form action="test" accept-charset="Content-Type"></form>"""
diff --git a/lib/pure/htmlparser.nim b/lib/pure/htmlparser.nim
index e2cbb4949..9719181b8 100644
--- a/lib/pure/htmlparser.nim
+++ b/lib/pure/htmlparser.nim
@@ -552,7 +552,7 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode =
 proc parseHtml*(s: Stream, filename: string, 
                 errors: var seq[string]): XmlNode = 
   ## parses the XML from stream `s` and returns a ``PXmlNode``. Every
-  ## occured parsing error is added to the `errors` sequence.
+  ## occurred parsing error is added to the `errors` sequence.
   var x: XmlParser
   open(x, s, filename, {reportComments, reportWhitespace})
   next(x)
@@ -581,7 +581,7 @@ proc parseHtml*(s: Stream): XmlNode =
 
 proc loadHtml*(path: string, errors: var seq[string]): XmlNode = 
   ## Loads and parses HTML from file specified by ``path``, and returns 
-  ## a ``PXmlNode``.  Every occured parsing error is added to
+  ## a ``PXmlNode``.  Every occurred parsing error is added to
   ## the `errors` sequence.
   var s = newFileStream(path, fmRead)
   if s == nil: raise newException(IOError, "Unable to read file: " & path)
@@ -593,7 +593,7 @@ proc loadHtml*(path: string): XmlNode =
   var errors: seq[string] = @[]
   result = loadHtml(path, errors)
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   import os
 
   var errors: seq[string] = @[]  
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 3afb625ee..9c27ecdab 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -32,21 +32,12 @@
 ## the server.
 ##
 ## .. code-block:: Nim
-##   var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
-##   var body: string = "--xyz\c\L"
-##   # soap 1.2 output
-##   body.add("Content-Disposition: form-data; name=\"output\"\c\L")
-##   body.add("\c\Lsoap12\c\L")
+##   var data = newMultipartData()
+##   data["output"] = "soap12"
+##   data["uploaded_file"] = ("test.html", "text/html",
+##     "<html><head></head><body><p>test</p></body></html>")
 ##
-##   # html
-##   body.add("--xyz\c\L")
-##   body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
-##            " filename=\"test.html\"\c\L")
-##   body.add("Content-Type: text/html\c\L")
-##   body.add("\c\L<html><head></head><body><p>test</p></body></html>\c\L")
-##   body.add("--xyz--")
-##
-##   echo(postContent("http://validator.w3.org/check", headers, body))
+##   echo postContent("http://validator.w3.org/check", multipart=data)
 ##
 ## Asynchronous HTTP requests
 ## ==========================
@@ -88,7 +79,7 @@
 ## constructor should be used for this purpose. However,
 ## currently only basic authentication is supported.
 
-import net, strutils, uri, parseutils, strtabs, base64, os
+import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math
 import asyncnet, asyncdispatch
 import rawsockets
 
@@ -103,6 +94,10 @@ type
     url*: Uri
     auth*: string
 
+  MultipartEntries* = openarray[tuple[name, content: string]]
+  MultipartData* = ref object
+    content: seq[string]
+
   ProtocolError* = object of IOError   ## exception that is raised when server
                                        ## does not conform to the implemented
                                        ## protocol
@@ -232,7 +227,7 @@ proc parseResponse(s: Socket, getBody: bool, timeout: int): Response =
       inc(linei, le)
       # Status code
       linei.inc skipWhitespace(line, linei)
-      result.status = line[linei .. -1]
+      result.status = line[linei .. ^1]
       parsedStatus = true
     else:
       # Parse headers
@@ -243,7 +238,7 @@ proc parseResponse(s: Socket, getBody: bool, timeout: int): Response =
       if line[linei] != ':': httpError("invalid headers")
       inc(linei) # Skip :
 
-      result.headers[name] = line[linei.. -1].strip()
+      result.headers[name] = line[linei.. ^1].strip()
   if not fullyRead:
     httpError("Connection was closed before full request has been made")
   if getBody:
@@ -282,19 +277,126 @@ proc newProxy*(url: string, auth = ""): Proxy =
   ## Constructs a new ``TProxy`` object.
   result = Proxy(url: parseUri(url), auth: auth)
 
-proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
-              body = "",
-              sslContext: SSLContext = defaultSSLContext,
-              timeout = -1, userAgent = defUserAgent,
-              proxy: Proxy = nil): Response =
-  ## | Requests ``url`` with the specified ``httpMethod``.
-  ## | Extra headers can be specified and must be seperated by ``\c\L``
+proc newMultipartData*: MultipartData =
+  ## Constructs a new ``MultipartData`` object.
+  MultipartData(content: @[])
+
+proc add*(p: var MultipartData, name, content: string, filename: string = nil,
+          contentType: string = nil) =
+  ## Add a value to the multipart data. Raises a `ValueError` exception if
+  ## `name`, `filename` or `contentType` contain newline characters.
+
+  if {'\c','\L'} in name:
+    raise newException(ValueError, "name contains a newline character")
+  if filename != nil and {'\c','\L'} in filename:
+    raise newException(ValueError, "filename contains a newline character")
+  if contentType != nil and {'\c','\L'} in contentType:
+    raise newException(ValueError, "contentType contains a newline character")
+
+  var str = "Content-Disposition: form-data; name=\"" & name & "\""
+  if filename != nil:
+    str.add("; filename=\"" & filename & "\"")
+  str.add("\c\L")
+  if contentType != nil:
+    str.add("Content-Type: " & contentType & "\c\L")
+  str.add("\c\L" & content & "\c\L")
+
+  p.content.add(str)
+
+proc add*(p: var MultipartData, xs: MultipartEntries): MultipartData
+         {.discardable.} =
+  ## Add a list of multipart entries to the multipart data `p`. All values are
+  ## added without a filename and without a content type.
+  ##
+  ## .. code-block:: Nim
+  ##   data.add({"action": "login", "format": "json"})
+  for name, content in xs.items:
+    p.add(name, content)
+  result = p
+
+proc newMultipartData*(xs: MultipartEntries): MultipartData =
+  ## Create a new multipart data object and fill it with the entries `xs`
+  ## directly.
+  ##
+  ## .. code-block:: Nim
+  ##   var data = newMultipartData({"action": "login", "format": "json"})
+  result = MultipartData(content: @[])
+  result.add(xs)
+
+proc addFiles*(p: var MultipartData, xs: openarray[tuple[name, file: string]]):
+              MultipartData {.discardable.} =
+  ## Add files to a multipart data object. The file will be opened from your
+  ## disk, read and sent with the automatically determined MIME type. Raises an
+  ## `IOError` if the file cannot be opened or reading fails. To manually
+  ## specify file content, filename and MIME type, use `[]=` instead.
+  ##
+  ## .. code-block:: Nim
+  ##   data.addFiles({"uploaded_file": "public/test.html"})
+  var m = newMimetypes()
+  for name, file in xs.items:
+    var contentType: string
+    let (dir, fName, ext) = splitFile(file)
+    if ext.len > 0:
+      contentType = m.getMimetype(ext[1..ext.high], nil)
+    p.add(name, readFile(file), fName & ext, contentType)
+  result = p
+
+proc `[]=`*(p: var MultipartData, name, content: string) =
+  ## Add a multipart entry to the multipart data `p`. The value is added
+  ## without a filename and without a content type.
+  ##
+  ## .. code-block:: Nim
+  ##   data["username"] = "NimUser"
+  p.add(name, content)
+
+proc `[]=`*(p: var MultipartData, name: string,
+            file: tuple[name, contentType, content: string]) =
+  ## Add a file to the multipart data `p`, specifying filename, contentType and
+  ## content manually.
+  ##
+  ## .. code-block:: Nim
+  ##   data["uploaded_file"] = ("test.html", "text/html",
+  ##     "<html><head></head><body><p>test</p></body></html>")
+  p.add(name, file.content, file.name, file.contentType)
+
+proc format(p: MultipartData): tuple[header, body: string] =
+  if p == nil or p.content == nil or p.content.len == 0:
+    return ("", "")
+
+  # Create boundary that is not in the data to be formatted
+  var bound: string
+  while true:
+    bound = $random(int.high)
+    var found = false
+    for s in p.content:
+      if bound in s:
+        found = true
+    if not found:
+      break
+
+  result.header = "Content-Type: multipart/form-data; boundary=" & bound & "\c\L"
+  result.body = ""
+  for s in p.content:
+    result.body.add("--" & bound & "\c\L" & s)
+  result.body.add("--" & bound & "--\c\L")
+
+proc request*(url: string, httpMethod: string, extraHeaders = "",
+              body = "", sslContext = defaultSSLContext, timeout = -1,
+              userAgent = defUserAgent, proxy: Proxy = nil): Response =
+  ## | Requests ``url`` with the custom method string specified by the
+  ## | ``httpMethod`` parameter.
+  ## | Extra headers can be specified and must be separated by ``\c\L``
   ## | An optional timeout can be specified in miliseconds, if reading from the
   ## server takes longer than specified an ETimeout exception will be raised.
   var r = if proxy == nil: parseUri(url) else: proxy.url
-  var headers = substr($httpMethod, len("http"))
+  var headers = substr(httpMethod, len("http"))
+  # TODO: Use generateHeaders further down once it supports proxies.
   if proxy == nil:
-    headers.add(" /" & r.path & r.query)
+    headers.add ' '
+    if r.path[0] != '/': headers.add '/'
+    headers.add(r.path)
+    if r.query.len > 0:
+      headers.add("?" & r.query)
   else:
     headers.add(" " & url)
 
@@ -330,9 +432,19 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
   if body != "":
     s.send(body)
 
-  result = parseResponse(s, httpMethod != httpHEAD, timeout)
+  result = parseResponse(s, httpMethod != "httpHEAD", timeout)
   s.close()
 
+proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
+              body = "", sslContext = defaultSSLContext, timeout = -1,
+              userAgent = defUserAgent, proxy: Proxy = nil): Response =
+  ## | Requests ``url`` with the specified ``httpMethod``.
+  ## | Extra headers can be specified and must be separated by ``\c\L``
+  ## | An optional timeout can be specified in miliseconds, if reading from the
+  ## server takes longer than specified an ETimeout exception will be raised.
+  result = request(url, $httpMethod, extraHeaders, body, sslContext, timeout,
+                   userAgent, proxy)
+
 proc redirection(status: string): bool =
   const redirectionNRs = ["301", "302", "303", "307"]
   for i in items(redirectionNRs):
@@ -387,22 +499,37 @@ proc post*(url: string, extraHeaders = "", body = "",
            maxRedirects = 5,
            sslContext: SSLContext = defaultSSLContext,
            timeout = -1, userAgent = defUserAgent,
-           proxy: Proxy = nil): Response =
+           proxy: Proxy = nil,
+           multipart: MultipartData = nil): Response =
   ## | POSTs ``body`` to the ``url`` and returns a ``Response`` object.
   ## | This proc adds the necessary Content-Length header.
   ## | This proc also handles redirection.
   ## | Extra headers can be specified and must be separated by ``\c\L``.
   ## | An optional timeout can be specified in miliseconds, if reading from the
   ## server takes longer than specified an ETimeout exception will be raised.
-  var xh = extraHeaders & "Content-Length: " & $len(body) & "\c\L"
-  result = request(url, httpPOST, xh, body, sslContext, timeout, userAgent,
+  ## | The optional ``multipart`` parameter can be used to create
+  ## ``multipart/form-data`` POSTs comfortably.
+  let (mpHeaders, mpBody) = format(multipart)
+
+  template withNewLine(x): expr =
+    if x.len > 0 and not x.endsWith("\c\L"):
+      x & "\c\L"
+    else:
+      x
+
+  var xb = mpBody.withNewLine() & body
+
+  var xh = extraHeaders.withNewLine() & mpHeaders.withNewLine() &
+    withNewLine("Content-Length: " & $len(xb))
+
+  result = request(url, httpPOST, xh, xb, sslContext, timeout, userAgent,
                    proxy)
   var lastUrl = ""
   for i in 1..maxRedirects:
     if result.status.redirection():
       let redirectTo = getNewLocation(lastURL, result.headers)
       var meth = if result.status != "307": httpGet else: httpPost
-      result = request(redirectTo, meth, xh, body, sslContext, timeout,
+      result = request(redirectTo, meth, xh, xb, sslContext, timeout,
                        userAgent, proxy)
       lastUrl = redirectTo
 
@@ -410,14 +537,17 @@ proc postContent*(url: string, extraHeaders = "", body = "",
                   maxRedirects = 5,
                   sslContext: SSLContext = defaultSSLContext,
                   timeout = -1, userAgent = defUserAgent,
-                  proxy: Proxy = nil): string =
+                  proxy: Proxy = nil,
+                  multipart: MultipartData = nil): string =
   ## | POSTs ``body`` to ``url`` and returns the response's body as a string
   ## | Raises exceptions for the status codes ``4xx`` and ``5xx``
   ## | Extra headers can be specified and must be separated by ``\c\L``.
   ## | An optional timeout can be specified in miliseconds, if reading from the
   ## server takes longer than specified an ETimeout exception will be raised.
+  ## | The optional ``multipart`` parameter can be used to create
+  ## ``multipart/form-data`` POSTs comfortably.
   var r = post(url, extraHeaders, body, maxRedirects, sslContext, timeout,
-               userAgent, proxy)
+               userAgent, proxy, multipart)
   if r.status[0] in {'4','5'}:
     raise newException(HttpRequestError, r.status)
   else:
@@ -438,11 +568,16 @@ proc downloadFile*(url: string, outputFilename: string,
   else:
     fileError("Unable to open file")
 
-proc generateHeaders(r: Uri, httpMethod: HttpMethod,
+proc generateHeaders(r: Uri, httpMethod: string,
                      headers: StringTableRef): string =
-  result = substr($httpMethod, len("http"))
+  # TODO: Use this in the blocking HttpClient once it supports proxies.
+  result = substr(httpMethod, len("http"))
   # TODO: Proxies
-  result.add(" /" & r.path & r.query)
+  result.add ' '
+  if r.path[0] != '/': result.add '/'
+  result.add(r.path)
+  if r.query.len > 0:
+    result.add("?" & r.query)
   result.add(" HTTP/1.1\c\L")
 
   add(result, "Host: " & r.hostname & "\c\L")
@@ -590,7 +725,7 @@ proc parseResponse(client: AsyncHttpClient,
       inc(linei, le)
       # Status code
       linei.inc skipWhitespace(line, linei)
-      result.status = line[linei .. -1]
+      result.status = line[linei .. ^1]
       parsedStatus = true
     else:
       # Parse headers
@@ -601,7 +736,7 @@ proc parseResponse(client: AsyncHttpClient,
       if line[linei] != ':': httpError("invalid headers")
       inc(linei) # Skip :
 
-      result.headers[name] = line[linei.. -1].strip()
+      result.headers[name] = line[linei.. ^1].strip()
   if not fullyRead:
     httpError("Connection was closed before full request has been made")
   if getBody:
@@ -635,10 +770,10 @@ proc newConnection(client: AsyncHttpClient, url: Uri) {.async.} =
     client.currentURL = url
     client.connected = true
 
-proc request*(client: AsyncHttpClient, url: string, httpMethod = httpGET,
+proc request*(client: AsyncHttpClient, url: string, httpMethod: string,
               body = ""): Future[Response] {.async.} =
   ## Connects to the hostname specified by the URL and performs a request
-  ## using the method specified.
+  ## using the custom method string specified by ``httpMethod``.
   ##
   ## Connection will kept alive. Further requests on the same ``client`` to
   ## the same hostname will not require a new connection to be made. The
@@ -651,13 +786,25 @@ proc request*(client: AsyncHttpClient, url: string, httpMethod = httpGET,
   if not client.headers.hasKey("user-agent") and client.userAgent != "":
     client.headers["User-Agent"] = client.userAgent
 
-  var headers = generateHeaders(r, httpMethod, client.headers)
+  var headers = generateHeaders(r, $httpMethod, client.headers)
 
   await client.socket.send(headers)
   if body != "":
     await client.socket.send(body)
 
-  result = await parseResponse(client, httpMethod != httpHEAD)
+  result = await parseResponse(client, httpMethod != "httpHEAD")
+
+proc request*(client: AsyncHttpClient, url: string, httpMethod = httpGET,
+              body = ""): Future[Response] =
+  ## Connects to the hostname specified by the URL and performs a request
+  ## using the method specified.
+  ##
+  ## Connection will kept alive. Further requests on the same ``client`` to
+  ## the same hostname will not require a new connection to be made. The
+  ## connection can be closed by using the ``close`` procedure.
+  ##
+  ## The returned future will complete once the request is completed.
+  result = request(client, url, $httpMethod, body)
 
 proc get*(client: AsyncHttpClient, url: string): Future[Response] {.async.} =
   ## Connects to the hostname specified by the URL and performs a GET request.
@@ -672,7 +819,7 @@ proc get*(client: AsyncHttpClient, url: string): Future[Response] {.async.} =
       result = await client.request(redirectTo, httpGET)
       lastUrl = redirectTo
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   when true:
     # Async
     proc main() {.async.} =
@@ -706,18 +853,9 @@ when isMainModule:
     #var r = get("http://validator.w3.org/check?uri=http%3A%2F%2Fgoogle.com&
     #  charset=%28detect+automatically%29&doctype=Inline&group=0")
 
-    var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
-    var body: string = "--xyz\c\L"
-    # soap 1.2 output
-    body.add("Content-Disposition: form-data; name=\"output\"\c\L")
-    body.add("\c\Lsoap12\c\L")
-
-    # html
-    body.add("--xyz\c\L")
-    body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
-             " filename=\"test.html\"\c\L")
-    body.add("Content-Type: text/html\c\L")
-    body.add("\c\L<html><head></head><body><p>test</p></body></html>\c\L")
-    body.add("--xyz--")
-
-    echo(postContent("http://validator.w3.org/check", headers, body))
+    var data = newMultipartData()
+    data["output"] = "soap12"
+    data["uploaded_file"] = ("test.html", "text/html",
+      "<html><head></head><body><p>test</p></body></html>")
+
+    echo postContent("http://validator.w3.org/check", multipart=data)
diff --git a/lib/pure/httpserver.nim b/lib/pure/httpserver.nim
index 38a068ea1..dc76c9228 100644
--- a/lib/pure/httpserver.nim
+++ b/lib/pure/httpserver.nim
@@ -363,7 +363,7 @@ proc run*(handleRequest: proc (client: Socket,
           port = Port(80)) =
   ## encapsulates the server object and main loop
   var s: TServer
-  open(s, port)
+  open(s, port, reuseAddr = true)
   #echo("httpserver running on port ", s.port)
   while true:
     next(s)
@@ -514,7 +514,7 @@ proc close*(h: PAsyncHTTPServer) =
   ## Closes the ``PAsyncHTTPServer``.
   h.asyncSocket.close()
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   var counter = 0
 
   var s: TServer
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 385787d6c..5d824d6f8 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -1,15 +1,15 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf, Dominik Picheta
+#        (c) Copyright 2015 Andreas Rumpf, Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
 ## This module implements a simple high performance `JSON`:idx:
-## parser. JSON (JavaScript Object Notation) is a lightweight 
-## data-interchange format that is easy for humans to read and write 
+## parser. JSON (JavaScript Object Notation) is a lightweight
+## data-interchange format that is easy for humans to read and write
 ## (unlike XML). It is easy for machines to parse and generate.
 ## JSON is based on a subset of the JavaScript Programming Language,
 ## Standard ECMA-262 3rd Edition - December 1999.
@@ -30,13 +30,32 @@
 ##
 ##   1.3000000000000000e+00
 ##   true
+##
+## This module can also be used to comfortably create JSON using the `%*`
+## operator:
+##
+## .. code-block:: nim
+##
+##   var hisName = "John"
+##   let herAge = 31
+##   var j = %*
+##     [
+##       {
+##         "name": hisName,
+##         "age": 30
+##       },
+##       {
+##         "name": "Susan",
+##         "age": herAge
+##       }
+##     ]
+
+import
+  hashes, strutils, lexbase, streams, unicode, macros
 
-import 
-  hashes, strutils, lexbase, streams, unicode
-
-type 
+type
   JsonEventKind* = enum  ## enumeration of all events that may occur when parsing
-    jsonError,           ## an error ocurred during parsing
+    jsonError,           ## an error occurred during parsing
     jsonEof,             ## end of file reached
     jsonString,          ## a string literal
     jsonInt,             ## an integer literal
@@ -48,7 +67,7 @@ type
     jsonObjectEnd,       ## end of an object: the ``}`` token
     jsonArrayStart,      ## start of an array: the ``[`` token
     jsonArrayEnd         ## start of an array: the ``]`` token
-    
+
   TTokKind = enum        # must be synchronized with TJsonEventKind!
     tkError,
     tkEof,
@@ -64,7 +83,7 @@ type
     tkBracketRi,
     tkColon,
     tkComma
-    
+
   JsonError* = enum        ## enumeration that lists all errors that can occur
     errNone,               ## no error
     errInvalidToken,       ## invalid token
@@ -77,8 +96,8 @@ type
     errEOC_Expected,       ## ``*/`` expected
     errEofExpected,        ## EOF expected
     errExprExpected        ## expr expected
-    
-  ParserState = enum 
+
+  ParserState = enum
     stateEof, stateStart, stateObject, stateArray, stateExpectArrayComma,
     stateExpectObjectComma, stateExpectColon, stateExpectValue
 
@@ -92,7 +111,7 @@ type
 
 {.deprecated: [TJsonEventKind: JsonEventKind, TJsonError: JsonError,
   TJsonParser: JsonParser].}
- 
+
 const
   errorMessages: array [JsonError, string] = [
     "no error",
@@ -127,56 +146,56 @@ proc open*(my: var JsonParser, input: Stream, filename: string) =
   my.state = @[stateStart]
   my.kind = jsonError
   my.a = ""
-  
-proc close*(my: var JsonParser) {.inline.} = 
+
+proc close*(my: var JsonParser) {.inline.} =
   ## closes the parser `my` and its associated input stream.
   lexbase.close(my)
 
-proc str*(my: JsonParser): string {.inline.} = 
-  ## returns the character data for the events: ``jsonInt``, ``jsonFloat``, 
+proc str*(my: JsonParser): string {.inline.} =
+  ## returns the character data for the events: ``jsonInt``, ``jsonFloat``,
   ## ``jsonString``
   assert(my.kind in {jsonInt, jsonFloat, jsonString})
   return my.a
 
-proc getInt*(my: JsonParser): BiggestInt {.inline.} = 
+proc getInt*(my: JsonParser): BiggestInt {.inline.} =
   ## returns the number for the event: ``jsonInt``
   assert(my.kind == jsonInt)
   return parseBiggestInt(my.a)
 
-proc getFloat*(my: JsonParser): float {.inline.} = 
+proc getFloat*(my: JsonParser): float {.inline.} =
   ## returns the number for the event: ``jsonFloat``
   assert(my.kind == jsonFloat)
   return parseFloat(my.a)
 
-proc kind*(my: JsonParser): JsonEventKind {.inline.} = 
+proc kind*(my: JsonParser): JsonEventKind {.inline.} =
   ## returns the current event type for the JSON parser
   return my.kind
-  
-proc getColumn*(my: JsonParser): int {.inline.} = 
+
+proc getColumn*(my: JsonParser): int {.inline.} =
   ## get the current column the parser has arrived at.
   result = getColNumber(my, my.bufpos)
 
-proc getLine*(my: JsonParser): int {.inline.} = 
+proc getLine*(my: JsonParser): int {.inline.} =
   ## get the current line the parser has arrived at.
   result = my.lineNumber
 
-proc getFilename*(my: JsonParser): string {.inline.} = 
+proc getFilename*(my: JsonParser): string {.inline.} =
   ## get the filename of the file that the parser processes.
   result = my.filename
-  
-proc errorMsg*(my: JsonParser): string = 
+
+proc errorMsg*(my: JsonParser): string =
   ## returns a helpful error message for the event ``jsonError``
   assert(my.kind == jsonError)
   result = "$1($2, $3) Error: $4" % [
     my.filename, $getLine(my), $getColumn(my), errorMessages[my.err]]
 
-proc errorMsgExpected*(my: JsonParser, e: string): string = 
+proc errorMsgExpected*(my: JsonParser, e: string): string =
   ## returns an error message "`e` expected" in the same format as the
-  ## other error messages 
+  ## other error messages
   result = "$1($2, $3) Error: $4" % [
     my.filename, $getLine(my), $getColumn(my), e & " expected"]
 
-proc handleHexChar(c: char, x: var int): bool = 
+proc handleHexChar(c: char, x: var int): bool =
   result = true # Success
   case c
   of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
@@ -189,8 +208,8 @@ proc parseString(my: var JsonParser): TTokKind =
   var pos = my.bufpos + 1
   var buf = my.buf
   while true:
-    case buf[pos] 
-    of '\0': 
+    case buf[pos]
+    of '\0':
       my.err = errQuoteExpected
       result = tkError
       break
@@ -199,21 +218,21 @@ proc parseString(my: var JsonParser): TTokKind =
       break
     of '\\':
       case buf[pos+1]
-      of '\\', '"', '\'', '/': 
+      of '\\', '"', '\'', '/':
         add(my.a, buf[pos+1])
         inc(pos, 2)
       of 'b':
         add(my.a, '\b')
-        inc(pos, 2)      
+        inc(pos, 2)
       of 'f':
         add(my.a, '\f')
-        inc(pos, 2)      
+        inc(pos, 2)
       of 'n':
         add(my.a, '\L')
-        inc(pos, 2)      
+        inc(pos, 2)
       of 'r':
         add(my.a, '\C')
-        inc(pos, 2)    
+        inc(pos, 2)
       of 't':
         add(my.a, '\t')
         inc(pos, 2)
@@ -225,15 +244,15 @@ proc parseString(my: var JsonParser): TTokKind =
         if handleHexChar(buf[pos], r): inc(pos)
         if handleHexChar(buf[pos], r): inc(pos)
         add(my.a, toUTF8(Rune(r)))
-      else: 
+      else:
         # don't bother with the error
         add(my.a, buf[pos])
         inc(pos)
-    of '\c': 
+    of '\c':
       pos = lexbase.handleCR(my, pos)
       buf = my.buf
       add(my.a, '\c')
-    of '\L': 
+    of '\L':
       pos = lexbase.handleLF(my, pos)
       buf = my.buf
       add(my.a, '\L')
@@ -241,25 +260,25 @@ proc parseString(my: var JsonParser): TTokKind =
       add(my.a, buf[pos])
       inc(pos)
   my.bufpos = pos # store back
-  
-proc skip(my: var JsonParser) = 
+
+proc skip(my: var JsonParser) =
   var pos = my.bufpos
   var buf = my.buf
-  while true: 
+  while true:
     case buf[pos]
-    of '/': 
-      if buf[pos+1] == '/': 
+    of '/':
+      if buf[pos+1] == '/':
         # skip line comment:
         inc(pos, 2)
         while true:
-          case buf[pos] 
-          of '\0': 
+          case buf[pos]
+          of '\0':
             break
-          of '\c': 
+          of '\c':
             pos = lexbase.handleCR(my, pos)
             buf = my.buf
             break
-          of '\L': 
+          of '\L':
             pos = lexbase.handleLF(my, pos)
             buf = my.buf
             break
@@ -269,44 +288,44 @@ proc skip(my: var JsonParser) =
         # skip long comment:
         inc(pos, 2)
         while true:
-          case buf[pos] 
-          of '\0': 
+          case buf[pos]
+          of '\0':
             my.err = errEOC_Expected
             break
-          of '\c': 
+          of '\c':
             pos = lexbase.handleCR(my, pos)
             buf = my.buf
-          of '\L': 
+          of '\L':
             pos = lexbase.handleLF(my, pos)
             buf = my.buf
           of '*':
             inc(pos)
-            if buf[pos] == '/': 
+            if buf[pos] == '/':
               inc(pos)
               break
           else:
             inc(pos)
-      else: 
+      else:
         break
-    of ' ', '\t': 
+    of ' ', '\t':
       inc(pos)
-    of '\c':  
+    of '\c':
       pos = lexbase.handleCR(my, pos)
       buf = my.buf
-    of '\L': 
+    of '\L':
       pos = lexbase.handleLF(my, pos)
       buf = my.buf
     else:
       break
   my.bufpos = pos
 
-proc parseNumber(my: var JsonParser) = 
+proc parseNumber(my: var JsonParser) =
   var pos = my.bufpos
   var buf = my.buf
-  if buf[pos] == '-': 
+  if buf[pos] == '-':
     add(my.a, '-')
     inc(pos)
-  if buf[pos] == '.': 
+  if buf[pos] == '.':
     add(my.a, "0.")
     inc(pos)
   else:
@@ -331,7 +350,7 @@ proc parseNumber(my: var JsonParser) =
       inc(pos)
   my.bufpos = pos
 
-proc parseName(my: var JsonParser) = 
+proc parseName(my: var JsonParser) =
   var pos = my.bufpos
   var buf = my.buf
   if buf[pos] in IdentStartChars:
@@ -340,11 +359,11 @@ proc parseName(my: var JsonParser) =
       inc(pos)
   my.bufpos = pos
 
-proc getTok(my: var JsonParser): TTokKind = 
+proc getTok(my: var JsonParser): TTokKind =
   setLen(my.a, 0)
   skip(my) # skip whitespace, comments
   case my.buf[my.bufpos]
-  of '-', '.', '0'..'9': 
+  of '-', '.', '0'..'9':
     parseNumber(my)
     if {'.', 'e', 'E'} in my.a:
       result = tkFloat
@@ -374,17 +393,17 @@ proc getTok(my: var JsonParser): TTokKind =
     result = tkEof
   of 'a'..'z', 'A'..'Z', '_':
     parseName(my)
-    case my.a 
+    case my.a
     of "null": result = tkNull
     of "true": result = tkTrue
     of "false": result = tkFalse
     else: result = tkError
-  else: 
+  else:
     inc(my.bufpos)
     result = tkError
   my.tok = result
 
-proc next*(my: var JsonParser) = 
+proc next*(my: var JsonParser) =
   ## retrieves the first/next event. This controls the parser.
   var tk = getTok(my)
   var i = my.state.len-1
@@ -397,13 +416,13 @@ proc next*(my: var JsonParser) =
     else:
       my.kind = jsonError
       my.err = errEofExpected
-  of stateStart: 
-    # tokens allowed? 
+  of stateStart:
+    # tokens allowed?
     case tk
     of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull:
       my.state[i] = stateEof # expect EOF next!
       my.kind = JsonEventKind(ord(tk))
-    of tkBracketLe: 
+    of tkBracketLe:
       my.state.add(stateArray) # we expect any
       my.kind = jsonArrayStart
     of tkCurlyLe:
@@ -414,12 +433,12 @@ proc next*(my: var JsonParser) =
     else:
       my.kind = jsonError
       my.err = errEofExpected
-  of stateObject: 
+  of stateObject:
     case tk
     of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull:
       my.state.add(stateExpectColon)
       my.kind = JsonEventKind(ord(tk))
-    of tkBracketLe: 
+    of tkBracketLe:
       my.state.add(stateExpectColon)
       my.state.add(stateArray)
       my.kind = jsonArrayStart
@@ -438,7 +457,7 @@ proc next*(my: var JsonParser) =
     of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull:
       my.state.add(stateExpectArrayComma) # expect value next!
       my.kind = JsonEventKind(ord(tk))
-    of tkBracketLe: 
+    of tkBracketLe:
       my.state.add(stateExpectArrayComma)
       my.state.add(stateArray)
       my.kind = jsonArrayStart
@@ -453,8 +472,8 @@ proc next*(my: var JsonParser) =
       my.kind = jsonError
       my.err = errBracketRiExpected
   of stateExpectArrayComma:
-    case tk 
-    of tkComma: 
+    case tk
+    of tkComma:
       discard my.state.pop()
       next(my)
     of tkBracketRi:
@@ -465,8 +484,8 @@ proc next*(my: var JsonParser) =
       my.kind = jsonError
       my.err = errBracketRiExpected
   of stateExpectObjectComma:
-    case tk 
-    of tkComma: 
+    case tk
+    of tkComma:
       discard my.state.pop()
       next(my)
     of tkCurlyRi:
@@ -476,9 +495,9 @@ proc next*(my: var JsonParser) =
     else:
       my.kind = jsonError
       my.err = errCurlyRiExpected
-  of stateExpectColon: 
-    case tk 
-    of tkColon: 
+  of stateExpectColon:
+    case tk
+    of tkColon:
       my.state[i] = stateExpectValue
       next(my)
     else:
@@ -489,7 +508,7 @@ proc next*(my: var JsonParser) =
     of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull:
       my.state[i] = stateExpectObjectComma
       my.kind = JsonEventKind(ord(tk))
-    of tkBracketLe: 
+    of tkBracketLe:
       my.state[i] = stateExpectObjectComma
       my.state.add(stateArray)
       my.kind = jsonArrayStart
@@ -513,8 +532,8 @@ type
     JString,
     JObject,
     JArray
-    
-  JsonNode* = ref JsonNodeObj ## JSON node 
+
+  JsonNode* = ref JsonNodeObj ## JSON node
   JsonNodeObj* {.acyclic.} = object
     case kind*: JsonNodeKind
     of JString:
@@ -586,6 +605,49 @@ proc newJArray*(): JsonNode =
   result.kind = JArray
   result.elems = @[]
 
+proc getStr*(n: JsonNode, default: string = ""): string =
+  ## Retrieves the string value of a `JString JsonNode`.
+  ##
+  ## Returns ``default`` if ``n`` is not a ``JString``.
+  if n.kind != JString: return default
+  else: return n.str
+
+proc getNum*(n: JsonNode, default: BiggestInt = 0): BiggestInt =
+  ## Retrieves the int value of a `JInt JsonNode`.
+  ##
+  ## Returns ``default`` if ``n`` is not a ``JInt``.
+  if n.kind != JInt: return default
+  else: return n.num
+
+proc getFNum*(n: JsonNode, default: float = 0.0): float =
+  ## Retrieves the float value of a `JFloat JsonNode`.
+  ##
+  ## Returns ``default`` if ``n`` is not a ``JFloat``.
+  if n.kind != JFloat: return default
+  else: return n.fnum
+
+proc getBVal*(n: JsonNode, default: bool = false): bool =
+  ## Retrieves the bool value of a `JBool JsonNode`.
+  ##
+  ## Returns ``default`` if ``n`` is not a ``JBool``.
+  if n.kind != JBool: return default
+  else: return n.bval
+
+proc getFields*(n: JsonNode,
+    default: seq[tuple[key: string, val: JsonNode]] = @[]):
+        seq[tuple[key: string, val: JsonNode]] =
+  ## Retrieves the key, value pairs of a `JObject JsonNode`.
+  ##
+  ## Returns ``default`` if ``n`` is not a ``JObject``.
+  if n.kind != JObject: return default
+  else: return n.fields
+
+proc getElems*(n: JsonNode, default: seq[JsonNode] = @[]): seq[JsonNode] =
+  ## Retrieves the int value of a `JArray JsonNode`.
+  ##
+  ## Returns ``default`` if ``n`` is not a ``JArray``.
+  if n.kind != JArray: return default
+  else: return n.elems
 
 proc `%`*(s: string): JsonNode =
   ## Generic constructor for JSON data. Creates a new `JString JsonNode`.
@@ -625,12 +687,35 @@ proc `%`*(elements: openArray[JsonNode]): JsonNode =
   newSeq(result.elems, elements.len)
   for i, p in pairs(elements): result.elems[i] = p
 
+proc toJson(x: NimNode): NimNode {.compiletime.} =
+  case x.kind
+  of nnkBracket:
+    result = newNimNode(nnkBracket)
+    for i in 0 .. <x.len:
+      result.add(toJson(x[i]))
+
+  of nnkTableConstr:
+    result = newNimNode(nnkTableConstr)
+    for i in 0 .. <x.len:
+      assert x[i].kind == nnkExprColonExpr
+      result.add(newNimNode(nnkExprColonExpr).add(x[i][0]).add(toJson(x[i][1])))
+
+  else:
+    result = x
+
+  result = prefix(result, "%")
+
+macro `%*`*(x: expr): expr =
+  ## Convert an expression to a JsonNode directly, without having to specify
+  ## `%` for every element.
+  result = toJson(x)
+
 proc `==`* (a,b: JsonNode): bool =
   ## Check two nodes for equality
   if a.isNil:
     if b.isNil: return true
     return false
-  elif b.isNil or a.kind != b.kind: 
+  elif b.isNil or a.kind != b.kind:
     return false
   else:
     return case a.kind
@@ -667,7 +752,7 @@ proc hash* (n:JsonNode): THash =
   of JNull:
     result = hash(0)
 
-proc len*(n: JsonNode): int = 
+proc len*(n: JsonNode): int =
   ## If `n` is a `JArray`, it returns the number of elements.
   ## If `n` is a `JObject`, it returns the number of pairs.
   ## Else it returns 0.
@@ -685,7 +770,7 @@ proc `[]`*(node: JsonNode, name: string): JsonNode =
     if key == name:
       return item
   return nil
-  
+
 proc `[]`*(node: JsonNode, index: int): JsonNode =
   ## Gets the node at `index` in an Array. Result is undefined if `index`
   ## is out of bounds
@@ -702,12 +787,12 @@ proc hasKey*(node: JsonNode, key: string): bool =
 proc existsKey*(node: JsonNode, key: string): bool {.deprecated.} = node.hasKey(key)
   ## Deprecated for `hasKey`
 
-proc add*(father, child: JsonNode) = 
-  ## Adds `child` to a JArray node `father`. 
+proc add*(father, child: JsonNode) =
+  ## Adds `child` to a JArray node `father`.
   assert father.kind == JArray
   father.elems.add(child)
 
-proc add*(obj: JsonNode, key: string, val: JsonNode) = 
+proc add*(obj: JsonNode, key: string, val: JsonNode) =
   ## Adds ``(key, val)`` pair to the JObject node `obj`. For speed
   ## reasons no check for duplicate keys is performed!
   ## But ``[]=`` performs the check.
@@ -718,27 +803,30 @@ proc `[]=`*(obj: JsonNode, key: string, val: JsonNode) =
   ## Sets a field from a `JObject`. Performs a check for duplicate keys.
   assert(obj.kind == JObject)
   for i in 0..obj.fields.len-1:
-    if obj.fields[i].key == key: 
+    if obj.fields[i].key == key:
       obj.fields[i].val = val
       return
   obj.fields.add((key, val))
 
-proc `{}`*(node: JsonNode, key: string): JsonNode =
-  ## Transverses the node and gets the given value. If any of the
-  ## names does not exist, returns nil
+proc `{}`*(node: JsonNode, keys: varargs[string]): JsonNode =
+  ## Traverses the node and gets the given value. If any of the
+  ## keys do not exist, returns nil. Also returns nil if one of the
+  ## intermediate data structures is not an object
   result = node
-  if isNil(node): return nil
-  result = result[key]
-
-proc `{}=`*(node: JsonNode, names: varargs[string], value: JsonNode) =
-  ## Transverses the node and tries to set the value at the given location
-  ## to `value` If any of the names are missing, they are added
+  for key in keys:
+    if isNil(result) or result.kind!=JObject:
+      return nil    
+    result=result[key]
+
+proc `{}=`*(node: JsonNode, keys: varargs[string], value: JsonNode) =
+  ## Traverses the node and tries to set the value at the given location
+  ## to `value` If any of the keys are missing, they are added
   var node = node
-  for i in 0..(names.len-2):
-    if isNil(node[names[i]]):
-      node[names[i]] = newJObject()
-    node = node[names[i]]
-  node[names[names.len-1]] = value
+  for i in 0..(keys.len-2):
+    if isNil(node[keys[i]]):
+      node[keys[i]] = newJObject()
+    node = node[keys[i]]
+  node[keys[keys.len-1]] = value
 
 proc delete*(obj: JsonNode, key: string) =
   ## Deletes ``obj[key]`` preserving the order of the other (key, value)-pairs.
@@ -773,17 +861,17 @@ proc copy*(p: JsonNode): JsonNode =
 
 # ------------- pretty printing ----------------------------------------------
 
-proc indent(s: var string, i: int) = 
-  s.add(repeatChar(i))
+proc indent(s: var string, i: int) =
+  s.add(spaces(i))
 
 proc newIndent(curr, indent: int, ml: bool): int =
   if ml: return curr + indent
   else: return indent
 
-proc nl(s: var string, ml: bool) = 
+proc nl(s: var string, ml: bool) =
   if ml: s.add("\n")
 
-proc escapeJson*(s: string): string = 
+proc escapeJson*(s: string): string =
   ## Converts a string `s` to its JSON representation.
   result = newStringOfCap(s.len + s.len shr 3)
   result.add("\"")
@@ -800,13 +888,13 @@ proc escapeJson*(s: string): string =
       result.add(toHex(r, 4))
   result.add("\"")
 
-proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true, 
+proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
               lstArr = false, currIndent = 0) =
   case node.kind
   of JObject:
     if currIndent != 0 and not lstArr: result.nl(ml)
     result.indent(currIndent) # Indentation
-    if node.fields.len > 0:  
+    if node.fields.len > 0:
       result.add("{")
       result.nl(ml) # New line
       for i in 0..len(node.fields)-1:
@@ -814,17 +902,17 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
           result.add(", ")
           result.nl(ml) # New Line
         # Need to indent more than {
-        result.indent(newIndent(currIndent, indent, ml)) 
+        result.indent(newIndent(currIndent, indent, ml))
         result.add(escapeJson(node.fields[i].key))
         result.add(": ")
-        toPretty(result, node.fields[i].val, indent, ml, false, 
+        toPretty(result, node.fields[i].val, indent, ml, false,
                  newIndent(currIndent, indent, ml))
       result.nl(ml)
       result.indent(currIndent) # indent the same as {
       result.add("}")
     else:
       result.add("{}")
-  of JString: 
+  of JString:
     if lstArr: result.indent(currIndent)
     result.add(escapeJson(node.str))
   of JInt:
@@ -864,7 +952,7 @@ proc pretty*(node: JsonNode, indent = 2): string =
 proc `$`*(node: JsonNode): string =
   ## Converts `node` to its JSON Representation on one line.
   result = ""
-  toPretty(result, node, 1, false)
+  toPretty(result, node, 0, false)
 
 iterator items*(node: JsonNode): JsonNode =
   ## Iterator for the items of `node`. `node` has to be a JArray.
@@ -872,17 +960,31 @@ iterator items*(node: JsonNode): JsonNode =
   for i in items(node.elems):
     yield i
 
+iterator mitems*(node: var JsonNode): var JsonNode =
+  ## Iterator for the items of `node`. `node` has to be a JArray. Items can be
+  ## modified.
+  assert node.kind == JArray
+  for i in mitems(node.elems):
+    yield i
+
 iterator pairs*(node: JsonNode): tuple[key: string, val: JsonNode] =
   ## Iterator for the child elements of `node`. `node` has to be a JObject.
   assert node.kind == JObject
   for key, val in items(node.fields):
     yield (key, val)
 
-proc eat(p: var JsonParser, tok: TTokKind) = 
+iterator mpairs*(node: var JsonNode): var tuple[key: string, val: JsonNode] =
+  ## Iterator for the child elements of `node`. `node` has to be a JObject.
+  ## Items can be modified
+  assert node.kind == JObject
+  for keyVal in mitems(node.fields):
+    yield keyVal
+
+proc eat(p: var JsonParser, tok: TTokKind) =
   if p.tok == tok: discard getTok(p)
   else: raiseParseErr(p, tokToStr[tok])
 
-proc parseJson(p: var JsonParser): JsonNode = 
+proc parseJson(p: var JsonParser): JsonNode =
   ## Parses JSON from a JSON Parser `p`.
   case p.tok
   of tkString:
@@ -899,17 +1001,17 @@ proc parseJson(p: var JsonParser): JsonNode =
   of tkTrue:
     result = newJBool(true)
     discard getTok(p)
-  of tkFalse: 
+  of tkFalse:
     result = newJBool(false)
     discard getTok(p)
-  of tkNull: 
+  of tkNull:
     result = newJNull()
     discard getTok(p)
-  of tkCurlyLe: 
+  of tkCurlyLe:
     result = newJObject()
     discard getTok(p)
-    while p.tok != tkCurlyRi: 
-      if p.tok != tkString: 
+    while p.tok != tkCurlyRi:
+      if p.tok != tkString:
         raiseParseErr(p, "string literal as key expected")
       var key = p.a
       discard getTok(p)
@@ -922,7 +1024,7 @@ proc parseJson(p: var JsonParser): JsonNode =
   of tkBracketLe:
     result = newJArray()
     discard getTok(p)
-    while p.tok != tkBracketRi: 
+    while p.tok != tkBracketRi:
       result.add(parseJson(p))
       if p.tok != tkComma: break
       discard getTok(p)
@@ -1042,28 +1144,31 @@ when false:
     of jsonObjectEnd: echo("}")
     of jsonArrayStart: echo("[")
     of jsonArrayEnd: echo("]")
-    
+
   close(x)
 
-# { "json": 5 } 
+# { "json": 5 }
 # To get that we shall use, obj["json"]
 
 when isMainModule:
   #var node = parse("{ \"test\": null }")
   #echo(node.existsKey("test56"))
+  
   var parsed = parseFile("tests/testdata/jsontest.json")
   var parsed2 = parseFile("tests/testdata/jsontest2.json")
-  echo(parsed)
-  echo()
-  echo(pretty(parsed, 2))
-  echo()
-  echo(parsed["keyÄÖöoßß"])
-  echo()
-  echo(pretty(parsed2))
-  try:
-    echo(parsed["key2"][12123])
-    raise newException(ValueError, "That line was expected to fail")
-  except IndexError: echo()
+
+  when not defined(testing):
+    echo(parsed)
+    echo()
+    echo(pretty(parsed, 2))
+    echo()
+    echo(parsed["keyÄÖöoßß"])
+    echo()
+    echo(pretty(parsed2))
+    try:
+      echo(parsed["key2"][12123])
+      raise newException(ValueError, "That line was expected to fail")
+    except IndexError: echo()
 
   let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd" }"""
   # nil passthrough
@@ -1087,11 +1192,51 @@ when isMainModule:
   except:
     assert(false, "EInvalidIndex thrown for valid index")
 
-  discard """
-  while true:
-    var json = stdin.readLine()
-    var node = parse(json)
-    echo(node)
-    echo()
-    echo()
-  """
+  assert(testJson{"b"}.str=="asd", "Couldn't fetch a singly nested key with {}") 
+  assert(isNil(testJson{"nonexistent"}), "Non-existent keys should return nil") 
+  assert(parsed2{"repository", "description"}.str=="IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
+  assert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
+  assert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
+  assert(testJson{"a"}==parseJson"[1, 2, 3, 4]", "Didn't return a non-JObject when there was one to be found")
+  assert(isNil(parseJson("[1, 2, 3]"){"foo"}), "Indexing directly into a list should return nil")
+ 
+  # Generator:
+  var j = %* [{"name": "John", "age": 30}, {"name": "Susan", "age": 31}]
+  assert j == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}] 
+
+  var j2 = %*
+    [
+      {
+        "name": "John",
+        "age": 30
+      },
+      {
+        "name": "Susan",
+        "age": 31
+      }
+    ]
+  assert j2 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
+
+  var name = "John"
+  let herAge = 30
+  const hisAge = 31
+
+  var j3 = %*
+    [ { "name": "John"
+      , "age": herAge
+      }
+    , { "name": "Susan"
+      , "age": hisAge
+      }
+    ]
+  assert j3 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
+  
+  when not defined(testing):
+    discard """
+    while true:
+      var json = stdin.readLine()
+      var node = parse(json)
+      echo(node)
+      echo()
+      echo()
+    """
diff --git a/lib/pure/lexbase.nim b/lib/pure/lexbase.nim
index a3a3d7b5c..23a87d9f8 100644
--- a/lib/pure/lexbase.nim
+++ b/lib/pure/lexbase.nim
@@ -165,5 +165,5 @@ proc getCurrentLine(L: BaseLexer, marker: bool = true): string =
     inc(i)
   add(result, "\n")
   if marker:
-    add(result, repeatChar(getColNumber(L, L.bufpos)) & "^\n")
+    add(result, spaces(getColNumber(L, L.bufpos)) & "^\n")
 
diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim
index 9247f69c5..a2ea53472 100644
--- a/lib/pure/logging.nim
+++ b/lib/pure/logging.nim
@@ -1,16 +1,16 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf, Dominik Picheta
+#        (c) Copyright 2015 Andreas Rumpf, Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
 ## This module implements a simple logger. It has been designed to be as simple
-## as possible to avoid bloat, if this library does not fullfill your needs,
+## as possible to avoid bloat, if this library does not fulfill your needs,
 ## write your own.
-## 
+##
 ## Format strings support the following variables which must be prefixed with
 ## the dollar operator (``$``):
 ##
@@ -21,23 +21,26 @@
 ## $time         Current time
 ## $app          ``os.getAppFilename()``
 ## ============  =======================
-## 
+##
 ##
 ## The following example demonstrates logging to three different handlers
 ## simultaneously:
 ##
 ## .. code-block:: nim
-##     
+##
 ##    var L = newConsoleLogger()
 ##    var fL = newFileLogger("test.log", fmtStr = verboseFmtStr)
 ##    var rL = newRollingFileLogger("rolling.log", fmtStr = verboseFmtStr)
-##    handlers.add(L)
-##    handlers.add(fL)
-##    handlers.add(rL)
+##    addHandler(L)
+##    addHandler(fL)
+##    addHandler(rL)
 ##    info("920410:52 accepted")
 ##    warn("4 8 15 16 23 4-- Error")
 ##    error("922044:16 SYSTEM FAILURE")
 ##    fatal("SYSTEM FAILURE SYSTEM FAILURE")
+##
+## **Warning:** The global list of handlers is a thread var, this means that
+## the handlers must be re-added in each thread.
 
 import strutils, os, times
 
@@ -61,20 +64,20 @@ const
 
 type
   Logger* = ref object of RootObj ## abstract logger; the base type of all loggers
-    levelThreshold*: Level    ## only messages of level >= levelThreshold 
+    levelThreshold*: Level    ## only messages of level >= levelThreshold
                               ## should be processed
     fmtStr: string ## = defaultFmtStr by default, see substituteLog for $date etc.
-    
+
   ConsoleLogger* = ref object of Logger ## logger that writes the messages to the
                                         ## console
-  
+
   FileLogger* = ref object of Logger ## logger that writes the messages to a file
     f: File
-  
-  RollingFileLogger* = ref object of FileLogger ## logger that writes the 
+
+  RollingFileLogger* = ref object of FileLogger ## logger that writes the
                                                 ## messages to a file and
                                                 ## performs log rotation
-    maxLines: int # maximum number of lines    
+    maxLines: int # maximum number of lines
     curLine : int
     baseName: string # initial filename
     baseMode: FileMode # initial file mode
@@ -83,22 +86,22 @@ type
 {.deprecated: [TLevel: Level, PLogger: Logger, PConsoleLogger: ConsoleLogger,
     PFileLogger: FileLogger, PRollingFileLogger: RollingFileLogger].}
 
-proc substituteLog(frmt: string): string = 
+proc substituteLog(frmt: string): string =
   ## converts $date to the current date
   ## converts $time to the current time
   ## converts $app to getAppFilename()
-  ## converts 
+  ## converts
   result = newStringOfCap(frmt.len + 20)
   var i = 0
-  while i < frmt.len: 
-    if frmt[i] != '$': 
+  while i < frmt.len:
+    if frmt[i] != '$':
       result.add(frmt[i])
       inc(i)
     else:
       inc(i)
       var v = ""
       var app = getAppFilename()
-      while frmt[i] in IdentChars: 
+      while frmt[i] in IdentChars:
         v.add(toLower(frmt[i]))
         inc(i)
       case v
@@ -111,12 +114,12 @@ proc substituteLog(frmt: string): string =
 
 method log*(logger: Logger, level: Level,
             frmt: string, args: varargs[string, `$`]) {.
-            raises: [Exception], 
+            raises: [Exception],
             tags: [TimeEffect, WriteIOEffect, ReadIOEffect].} =
   ## Override this method in custom loggers. Default implementation does
   ## nothing.
   discard
-  
+
 method log*(logger: ConsoleLogger, level: Level,
             frmt: string, args: varargs[string, `$`]) =
   ## Logs to the console using ``logger`` only.
@@ -124,14 +127,14 @@ method log*(logger: ConsoleLogger, level: Level,
     writeln(stdout, LevelNames[level], " ", substituteLog(logger.fmtStr),
             frmt % args)
 
-method log*(logger: FileLogger, level: Level, 
+method log*(logger: FileLogger, level: Level,
             frmt: string, args: varargs[string, `$`]) =
   ## Logs to a file using ``logger`` only.
   if level >= logger.levelThreshold:
     writeln(logger.f, LevelNames[level], " ",
             substituteLog(logger.fmtStr), frmt % args)
 
-proc defaultFilename*(): string = 
+proc defaultFilename*(): string =
   ## Returns the default filename for a logger.
   var (path, name, ext) = splitFile(getAppFilename())
   result = changeFileExt(path / name, "log")
@@ -142,10 +145,10 @@ proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr): Console
   result.fmtStr = fmtStr
   result.levelThreshold = levelThreshold
 
-proc newFileLogger*(filename = defaultFilename(), 
+proc newFileLogger*(filename = defaultFilename(),
                     mode: FileMode = fmAppend,
                     levelThreshold = lvlAll,
-                    fmtStr = defaultFmtStr): FileLogger = 
+                    fmtStr = defaultFmtStr): FileLogger =
   ## Creates a new file logger. This logger logs to a file.
   new(result)
   result.levelThreshold = levelThreshold
@@ -167,14 +170,14 @@ proc countFiles(filename: string): int =
     if kind == pcFile:
       let llfn = name & ext & ExtSep
       if path.extractFilename.startsWith(llfn):
-        let numS = path.extractFilename[llfn.len .. -1]
+        let numS = path.extractFilename[llfn.len .. ^1]
         try:
           let num = parseInt(numS)
           if num > result:
             result = num
         except ValueError: discard
 
-proc newRollingFileLogger*(filename = defaultFilename(), 
+proc newRollingFileLogger*(filename = defaultFilename(),
                            mode: FileMode = fmReadWrite,
                            levelThreshold = lvlAll,
                            fmtStr = defaultFmtStr,
@@ -183,15 +186,15 @@ proc newRollingFileLogger*(filename = defaultFilename(),
   ## a new log file will be started and the old will be renamed.
   new(result)
   result.levelThreshold = levelThreshold
-  result.fmtStr = defaultFmtStr
+  result.fmtStr = fmtStr
   result.maxLines = maxLines
   result.f = open(filename, mode)
   result.curLine = 0
   result.baseName = filename
   result.baseMode = mode
-  
+
   result.logFiles = countFiles(filename)
-  
+
   if mode == fmAppend:
     # We need to get a line count because we will be appending to the file.
     result.curLine = countLogLines(result)
@@ -203,7 +206,7 @@ proc rotate(logger: RollingFileLogger) =
     moveFile(dir / (name & ext & srcSuff),
              dir / (name & ext & ExtSep & $(i+1)))
 
-method log*(logger: RollingFileLogger, level: Level, 
+method log*(logger: RollingFileLogger, level: Level,
             frmt: string, args: varargs[string, `$`]) =
   ## Logs to a file using rolling ``logger`` only.
   if level >= logger.levelThreshold:
@@ -213,18 +216,17 @@ method log*(logger: RollingFileLogger, level: Level,
       logger.logFiles.inc
       logger.curLine = 0
       logger.f = open(logger.baseName, logger.baseMode)
-    
-    writeln(logger.f, LevelNames[level], " ", frmt % args)
+
+    writeln(logger.f, LevelNames[level], " ",substituteLog(logger.fmtStr), frmt % args)
     logger.curLine.inc
 
 # --------
 
-var
-  level* = lvlAll  ## global log filter
-  handlers*: seq[Logger] = @[] ## handlers with their own log levels
+var level {.threadvar.}: Level   ## global log filter
+var handlers {.threadvar.}: seq[Logger] ## handlers with their own log levels
 
 proc logLoop(level: Level, frmt: string, args: varargs[string, `$`]) =
-  for logger in items(handlers): 
+  for logger in items(handlers):
     if level >= logger.levelThreshold:
       log(logger, level, frmt, args)
 
@@ -233,7 +235,7 @@ template log*(level: Level, frmt: string, args: varargs[string, `$`]) =
   bind logLoop
   bind `%`
   bind logging.level
-  
+
   if level >= logging.level:
     logLoop(level, frmt, args)
 
@@ -241,33 +243,49 @@ template debug*(frmt: string, args: varargs[string, `$`]) =
   ## Logs a debug message to all registered handlers.
   log(lvlDebug, frmt, args)
 
-template info*(frmt: string, args: varargs[string, `$`]) = 
+template info*(frmt: string, args: varargs[string, `$`]) =
   ## Logs an info message to all registered handlers.
   log(lvlInfo, frmt, args)
 
-template warn*(frmt: string, args: varargs[string, `$`]) = 
+template warn*(frmt: string, args: varargs[string, `$`]) =
   ## Logs a warning message to all registered handlers.
   log(lvlWarn, frmt, args)
 
-template error*(frmt: string, args: varargs[string, `$`]) = 
+template error*(frmt: string, args: varargs[string, `$`]) =
   ## Logs an error message to all registered handlers.
   log(lvlError, frmt, args)
-  
-template fatal*(frmt: string, args: varargs[string, `$`]) =  
+
+template fatal*(frmt: string, args: varargs[string, `$`]) =
   ## Logs a fatal error message to all registered handlers.
   log(lvlFatal, frmt, args)
 
+proc addHandler*(handler: Logger) =
+  ## Adds ``handler`` to the list of handlers.
+  if handlers.isNil: handlers = @[]
+  handlers.add(handler)
+
+proc getHandlers*(): seq[Logger] =
+  ## Returns a list of all the registered handlers.
+  return handlers
+
+proc setLogFilter*(lvl: Level) =
+  ## Sets the global log filter.
+  level = lvl
+
+proc getLogFilter*(): Level =
+  ## Gets the global log filter.
+  return level
 
 # --------------
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   var L = newConsoleLogger()
   var fL = newFileLogger("test.log", fmtStr = verboseFmtStr)
   var rL = newRollingFileLogger("rolling.log", fmtStr = verboseFmtStr)
-  handlers.add(L)
-  handlers.add(fL)
-  handlers.add(rL)
+  addHandler(L)
+  addHandler(fL)
+  addHandler(rL)
   for i in 0 .. 25:
     info("hello" & $i, [])
-  
+
 
diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim
index 02abda722..e0092f314 100644
--- a/lib/pure/marshal.nim
+++ b/lib/pure/marshal.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -15,8 +15,8 @@
 ## type than its compiletime type:
 ##
 ## .. code-block:: nim
-## 
-##   type 
+##
+##   type
 ##     TA = object
 ##     TB = object of TA
 ##       f: int
@@ -28,6 +28,8 @@
 ##   new(b)
 ##   a = b
 ##   echo($$a[]) # produces "{}", not "{f: 0}"
+##
+## **Note**: The ``to`` and ``$$`` operations are available at compile-time!
 
 import streams, typeinfo, json, intsets, tables
 
@@ -38,7 +40,12 @@ proc storeAny(s: Stream, a: TAny, stored: var IntSet) =
   case a.kind
   of akNone: assert false
   of akBool: s.write($getBool(a))
-  of akChar: s.write(escapeJson($getChar(a)))
+  of akChar:
+    let ch = getChar(a)
+    if ch < '\128':
+      s.write(escapeJson($ch))
+    else:
+      s.write($int(ch))
   of akArray, akSequence:
     if a.kind == akSequence and isNil(a): s.write("null")
     else:
@@ -92,7 +99,7 @@ proc storeAny(s: Stream, a: TAny, stored: var IntSet) =
 proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
   case a.kind
   of akNone: assert false
-  of akBool: 
+  of akBool:
     case p.kind
     of jsonFalse: setBiggestInt(a, 0)
     of jsonTrue: setBiggestInt(a, 1)
@@ -105,8 +112,12 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
         setBiggestInt(a, ord(x[0]))
         next(p)
         return
+    elif p.kind == jsonInt:
+      setBiggestInt(a, getInt(p))
+      next(p)
+      return
     raiseParseErr(p, "string of length 1 expected for a char")
-  of akEnum: 
+  of akEnum:
     if p.kind == jsonString:
       setBiggestInt(a, getEnumOrdinal(a, p.str))
       next(p)
@@ -122,7 +133,7 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
     if p.kind == jsonArrayEnd: next(p)
     else: raiseParseErr(p, "']' end of array expected")
   of akSequence:
-    case p.kind 
+    case p.kind
     of jsonNull:
       setPointer(a, nil)
       next(p)
@@ -143,7 +154,7 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
     if p.kind != jsonObjectStart: raiseParseErr(p, "'{' expected for an object")
     next(p)
     while p.kind != jsonObjectEnd and p.kind != jsonEof:
-      if p.kind != jsonString: 
+      if p.kind != jsonString:
         raiseParseErr(p, "string expected for a field name")
       var fieldName = p.str
       next(p)
@@ -160,7 +171,7 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
     if p.kind == jsonArrayEnd: next(p)
     else: raiseParseErr(p, "']' end of array expected")
   of akPtr, akRef:
-    case p.kind 
+    case p.kind
     of jsonNull:
       setPointer(a, nil)
       next(p)
@@ -170,7 +181,7 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
     of jsonArrayStart:
       next(p)
       if a.kind == akRef: invokeNew(a)
-      else: setPointer(a, alloc0(a.baseTypeSize))      
+      else: setPointer(a, alloc0(a.baseTypeSize))
       if p.kind == jsonInt:
         t[p.getInt] = getPointer(a)
         next(p)
@@ -179,8 +190,8 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
       if p.kind == jsonArrayEnd: next(p)
       else: raiseParseErr(p, "']' end of ref-address pair expected")
     else: raiseParseErr(p, "int for pointer type expected")
-  of akProc, akPointer, akCString: 
-    case p.kind 
+  of akProc, akPointer, akCString:
+    case p.kind
     of jsonNull:
       setPointer(a, nil)
       next(p)
@@ -189,7 +200,7 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
       next(p)
     else: raiseParseErr(p, "int for pointer type expected")
   of akString:
-    case p.kind 
+    case p.kind
     of jsonNull:
       setPointer(a, nil)
       next(p)
@@ -197,7 +208,7 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
       setString(a, p.str)
       next(p)
     else: raiseParseErr(p, "string expected")
-  of akInt..akInt64, akUInt..akUInt64: 
+  of akInt..akInt64, akUInt..akUInt64:
     if p.kind == jsonInt:
       setBiggestInt(a, getInt(p))
       next(p)
@@ -243,22 +254,22 @@ proc to*[T](data: string): T =
   ## reads data and transforms it to a ``T``.
   var tab = initTable[BiggestInt, pointer]()
   loadAny(newStringStream(data), toAny(result), tab)
-  
-when isMainModule:
+
+when not defined(testing) and isMainModule:
   template testit(x: expr) = echo($$to[type(x)]($$x))
 
   var x: array[0..4, array[0..4, string]] = [
-    ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"], 
-    ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"], 
+    ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
+    ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
     ["test", "1", "2", "3", "4"]]
   testit(x)
   var test2: tuple[name: string, s: uint] = ("tuple test", 56u)
   testit(test2)
-  
+
   type
     TE = enum
       blah, blah2
-  
+
     TestObj = object
       test, asd: int
       case test2: TE
@@ -266,7 +277,7 @@ when isMainModule:
         help: string
       else:
         nil
-        
+
     PNode = ref TNode
     TNode = object
       next, prev: PNode
@@ -294,7 +305,7 @@ when isMainModule:
   test4.a = "ref string test: A"
   test4.b = "ref string test: B"
   testit(test4)
-  
+
   var test5 = @[(0,1),(2,3),(4,5)]
   testit(test5)
 
@@ -305,7 +316,7 @@ when isMainModule:
   echo($$test7)
   testit(test7)
 
-  type 
+  type
     TA {.inheritable.} = object
     TB = object of TA
       f: int
diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim
index 46fc9985c..d55963c15 100644
--- a/lib/pure/matchers.nim
+++ b/lib/pure/matchers.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -42,7 +42,7 @@ proc validEmailAddress*(s: string): bool {.noSideEffect,
   case toLower(x)
   of "com", "org", "net", "gov", "mil", "biz", "info", "mobi", "name",
      "aero", "jobs", "museum": return true
-  return false
+  else: return false
 
 proc parseInt*(s: string, value: var int, validRange: Slice[int]) {.
   noSideEffect, rtl, extern: "nmatchParseInt".} =
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 987c35d1c..daa108460 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -93,9 +93,9 @@ proc nextPowerOfTwo*(x: int): int {.noSideEffect.} =
   result = x - 1 
   when defined(cpu64):
     result = result or (result shr 32)
-  when sizeof(int) > 16:
+  when sizeof(int) > 2:
     result = result or (result shr 16)
-  when sizeof(int) > 8:
+  when sizeof(int) > 1:
     result = result or (result shr 8)
   result = result or (result shr 4)
   result = result or (result shr 2)
@@ -129,29 +129,30 @@ proc variance*(x: openArray[float]): float {.noSideEffect.} =
     result = result + diff*diff
   result = result / toFloat(len(x))
 
-proc random*(max: int): int {.gcsafe.}
+proc random*(max: int): int {.benign.}
   ## returns a random number in the range 0..max-1. The sequence of
   ## random number is always the same, unless `randomize` is called
   ## which initializes the random number generator with a "random"
   ## number, i.e. a tickcount.
 
-proc random*(max: float): float {.gcsafe.}
+proc random*(max: float): float {.benign.}
   ## returns a random number in the range 0..<max. The sequence of
   ## random number is always the same, unless `randomize` is called
   ## which initializes the random number generator with a "random"
   ## number, i.e. a tickcount. This has a 16-bit resolution on windows
   ## and a 48-bit resolution on other platforms.
 
-proc randomize*() {.gcsafe.}
+proc randomize*() {.benign.}
   ## initializes the random number generator with a "random"
   ## number, i.e. a tickcount. Note: Does nothing for the JavaScript target,
   ## as JavaScript does not support this.
   
-proc randomize*(seed: int) {.gcsafe.}
+proc randomize*(seed: int) {.benign.}
   ## initializes the random number generator with a specific seed.
   ## Note: Does nothing for the JavaScript target,
   ## as JavaScript does not support this.
 
+{.push noSideEffect.}
 when not defined(JS):
   proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
     ## computes the square root of `x`.
@@ -273,6 +274,8 @@ else:
     var y = exp(2.0*x)
     return (y-1.0)/(y+1.0)
 
+{.pop.}
+
 proc `mod`*(x, y: float): float =
   result = if y == 0.0: x else: x - y * (x/y).floor
 
@@ -280,7 +283,7 @@ proc random*[T](x: Slice[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 =
+proc random*[T](a: openArray[T]): T =
   ## returns a random element from the openarray `a`.
   result = a[random(a.low..a.len)]
 
@@ -329,6 +332,31 @@ proc standardDeviation*(s: RunningStat): float =
 {.pop.}
 {.pop.}
 
+proc `^`*[T](x, y: T): T =
+  ## Computes ``x`` to the power ``y`. ``x`` must be non-negative, use
+  ## `pow <#pow,float,float>` for negative exponents.
+  assert y >= 0
+  var (x, y) = (x, y)
+  result = 1
+
+  while y != 0:
+    if (y and 1) != 0:
+      result *= x
+    y = y shr 1
+    x *= x
+
+proc gcd*[T](x, y: T): T =
+  ## Computes the greatest common divisor of ``x`` and ``y``.
+  var (x,y) = (x,y)
+  while y != 0:
+    x = x mod y
+    swap x, y
+  abs x
+
+proc lcm*[T](x, y: T): T =
+  ## Computes the least common multiple of ``x`` and ``y``.
+  x div gcd(x, y) * y
+
 when isMainModule and not defined(JS):
   proc gettime(dummy: ptr cint): cint {.importc: "time", header: "<time.h>".}
 
@@ -344,4 +372,10 @@ when isMainModule and not defined(JS):
   randomize(seed)
   for i in 0..SIZE-1:
     assert buf[i] == random(high(int)), "non deterministic random seeding"
-  echo "random values equal after reseeding"
+
+  when not defined(testing):
+    echo "random values equal after reseeding"
+
+  # Check for no side effect annotation
+  proc mySqrt(num: float): float {.noSideEffect.} =
+    return sqrt(num)
diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim
index 3b5453957..5ee301b15 100644
--- a/lib/pure/md5.nim
+++ b/lib/pure/md5.nim
@@ -9,18 +9,20 @@
 
 ## Module for computing MD5 checksums.
 
-type 
-  MD5State = array[0..3, int32]
-  MD5Block = array[0..15, int32]
-  MD5CBits = array[0..7, int8]
-  MD5Digest* = array[0..15, int8]
-  MD5Buffer = array[0..63, int8]
-  MD5Context* {.final.} = object 
+import unsigned
+
+type
+  MD5State = array[0..3, uint32]
+  MD5Block = array[0..15, uint32]
+  MD5CBits = array[0..7, uint8]
+  MD5Digest* = array[0..15, uint8]
+  MD5Buffer = array[0..63, uint8]
+  MD5Context* {.final.} = object
     state: MD5State
-    count: array[0..1, int32]
+    count: array[0..1, uint32]
     buffer: MD5Buffer
 
-const 
+const
   padding: cstring = "\x80\0\0\0" &
                      "\0\0\0\0\0\0\0\0" &
                      "\0\0\0\0\0\0\0\0" &
@@ -31,60 +33,60 @@ const
                      "\0\0\0\0\0\0\0\0" &
                      "\0\0\0\0"
 
-proc F(x, y, z: int32): int32 {.inline.} = 
+proc F(x, y, z: uint32): uint32 {.inline.} =
   result = (x and y) or ((not x) and z)
 
-proc G(x, y, z: int32): int32 {.inline.} = 
+proc G(x, y, z: uint32): uint32 {.inline.} =
   result = (x and z) or (y and (not z))
 
-proc H(x, y, z: int32): int32 {.inline.} = 
+proc H(x, y, z: uint32): uint32 {.inline.} =
   result = x xor y xor z
 
-proc I(x, y, z: int32): int32 {.inline.} = 
+proc I(x, y, z: uint32): uint32 {.inline.} =
   result = y xor (x or (not z))
 
-proc rot(x: var int32, n: int8) {.inline.} = 
-  x = toU32(x shl ze(n)) or (x shr toU32(32 -% ze(n)))
+proc rot(x: var uint32, n: uint8) {.inline.} =
+  x = (x shl n) or (x shr (32'u32 - n))
 
-proc FF(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
-  a = a +% F(b, c, d) +% x +% ac
+proc FF(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
+  a = a + F(b, c, d) + x + ac
   rot(a, s)
-  a = a +% b
+  a = a + b
 
-proc GG(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
-  a = a +% G(b, c, d) +% x +% ac
+proc GG(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
+  a = a + G(b, c, d) + x + ac
   rot(a, s)
-  a = a +% b
+  a = a + b
 
-proc HH(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
-  a = a +% H(b, c, d) +% x +% ac
+proc HH(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
+  a = a + H(b, c, d) + x + ac
   rot(a, s)
-  a = a +% b
+  a = a + b
 
-proc II(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
-  a = a +% I(b, c, d) +% x +% ac
+proc II(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
+  a = a + I(b, c, d) + x + ac
   rot(a, s)
-  a = a +% b
+  a = a + b
 
-proc encode(dest: var MD5Block, src: cstring) = 
+proc encode(dest: var MD5Block, src: cstring) =
   var j = 0
   for i in 0..high(dest):
-    dest[i] = toU32(ord(src[j]) or 
-                ord(src[j+1]) shl 8 or
-                ord(src[j+2]) shl 16 or
-                ord(src[j+3]) shl 24)
+    dest[i] = uint32(ord(src[j])) or
+              uint32(ord(src[j+1])) shl 8 or
+              uint32(ord(src[j+2])) shl 16 or
+              uint32(ord(src[j+3])) shl 24
     inc(j, 4)
 
-proc decode(dest: var openArray[int8], src: openArray[int32]) = 
+proc decode(dest: var openArray[uint8], src: openArray[uint32]) =
   var i = 0
   for j in 0..high(src):
-    dest[i] = toU8(src[j] and 0xff'i32)
-    dest[i+1] = toU8(src[j] shr 8'i32 and 0xff'i32)
-    dest[i+2] = toU8(src[j] shr 16'i32 and 0xff'i32)
-    dest[i+3] = toU8(src[j] shr 24'i32 and 0xff'i32)
+    dest[i] = src[j] and 0xff'u32
+    dest[i+1] = src[j] shr 8 and 0xff'u32
+    dest[i+2] = src[j] shr 16 and 0xff'u32
+    dest[i+3] = src[j] shr 24 and 0xff'u32
     inc(i, 4)
 
-proc transform(buffer: pointer, state: var MD5State) = 
+proc transform(buffer: pointer, state: var MD5State) =
   var
     myBlock: MD5Block
   encode(myBlock, cast[cstring](buffer))
@@ -92,111 +94,111 @@ proc transform(buffer: pointer, state: var MD5State) =
   var b = state[1]
   var c = state[2]
   var d = state[3]
-  FF(a, b, c, d, myBlock[0], 7'i8, 0xD76AA478'i32)
-  FF(d, a, b, c, myBlock[1], 12'i8, 0xE8C7B756'i32)
-  FF(c, d, a, b, myBlock[2], 17'i8, 0x242070DB'i32)
-  FF(b, c, d, a, myBlock[3], 22'i8, 0xC1BDCEEE'i32)
-  FF(a, b, c, d, myBlock[4], 7'i8, 0xF57C0FAF'i32)
-  FF(d, a, b, c, myBlock[5], 12'i8, 0x4787C62A'i32)
-  FF(c, d, a, b, myBlock[6], 17'i8, 0xA8304613'i32)
-  FF(b, c, d, a, myBlock[7], 22'i8, 0xFD469501'i32)
-  FF(a, b, c, d, myBlock[8], 7'i8, 0x698098D8'i32)
-  FF(d, a, b, c, myBlock[9], 12'i8, 0x8B44F7AF'i32)
-  FF(c, d, a, b, myBlock[10], 17'i8, 0xFFFF5BB1'i32)
-  FF(b, c, d, a, myBlock[11], 22'i8, 0x895CD7BE'i32)
-  FF(a, b, c, d, myBlock[12], 7'i8, 0x6B901122'i32)
-  FF(d, a, b, c, myBlock[13], 12'i8, 0xFD987193'i32)
-  FF(c, d, a, b, myBlock[14], 17'i8, 0xA679438E'i32)
-  FF(b, c, d, a, myBlock[15], 22'i8, 0x49B40821'i32)
-  GG(a, b, c, d, myBlock[1], 5'i8, 0xF61E2562'i32)
-  GG(d, a, b, c, myBlock[6], 9'i8, 0xC040B340'i32)
-  GG(c, d, a, b, myBlock[11], 14'i8, 0x265E5A51'i32)
-  GG(b, c, d, a, myBlock[0], 20'i8, 0xE9B6C7AA'i32)
-  GG(a, b, c, d, myBlock[5], 5'i8, 0xD62F105D'i32)
-  GG(d, a, b, c, myBlock[10], 9'i8, 0x02441453'i32)
-  GG(c, d, a, b, myBlock[15], 14'i8, 0xD8A1E681'i32)
-  GG(b, c, d, a, myBlock[4], 20'i8, 0xE7D3FBC8'i32)
-  GG(a, b, c, d, myBlock[9], 5'i8, 0x21E1CDE6'i32)
-  GG(d, a, b, c, myBlock[14], 9'i8, 0xC33707D6'i32)
-  GG(c, d, a, b, myBlock[3], 14'i8, 0xF4D50D87'i32)
-  GG(b, c, d, a, myBlock[8], 20'i8, 0x455A14ED'i32)
-  GG(a, b, c, d, myBlock[13], 5'i8, 0xA9E3E905'i32)
-  GG(d, a, b, c, myBlock[2], 9'i8, 0xFCEFA3F8'i32)
-  GG(c, d, a, b, myBlock[7], 14'i8, 0x676F02D9'i32)
-  GG(b, c, d, a, myBlock[12], 20'i8, 0x8D2A4C8A'i32)
-  HH(a, b, c, d, myBlock[5], 4'i8, 0xFFFA3942'i32)
-  HH(d, a, b, c, myBlock[8], 11'i8, 0x8771F681'i32)
-  HH(c, d, a, b, myBlock[11], 16'i8, 0x6D9D6122'i32)
-  HH(b, c, d, a, myBlock[14], 23'i8, 0xFDE5380C'i32)
-  HH(a, b, c, d, myBlock[1], 4'i8, 0xA4BEEA44'i32)
-  HH(d, a, b, c, myBlock[4], 11'i8, 0x4BDECFA9'i32)
-  HH(c, d, a, b, myBlock[7], 16'i8, 0xF6BB4B60'i32)
-  HH(b, c, d, a, myBlock[10], 23'i8, 0xBEBFBC70'i32)
-  HH(a, b, c, d, myBlock[13], 4'i8, 0x289B7EC6'i32)
-  HH(d, a, b, c, myBlock[0], 11'i8, 0xEAA127FA'i32)
-  HH(c, d, a, b, myBlock[3], 16'i8, 0xD4EF3085'i32)
-  HH(b, c, d, a, myBlock[6], 23'i8, 0x04881D05'i32)
-  HH(a, b, c, d, myBlock[9], 4'i8, 0xD9D4D039'i32)
-  HH(d, a, b, c, myBlock[12], 11'i8, 0xE6DB99E5'i32)
-  HH(c, d, a, b, myBlock[15], 16'i8, 0x1FA27CF8'i32)
-  HH(b, c, d, a, myBlock[2], 23'i8, 0xC4AC5665'i32)
-  II(a, b, c, d, myBlock[0], 6'i8, 0xF4292244'i32)
-  II(d, a, b, c, myBlock[7], 10'i8, 0x432AFF97'i32)
-  II(c, d, a, b, myBlock[14], 15'i8, 0xAB9423A7'i32)
-  II(b, c, d, a, myBlock[5], 21'i8, 0xFC93A039'i32)
-  II(a, b, c, d, myBlock[12], 6'i8, 0x655B59C3'i32)
-  II(d, a, b, c, myBlock[3], 10'i8, 0x8F0CCC92'i32)
-  II(c, d, a, b, myBlock[10], 15'i8, 0xFFEFF47D'i32)
-  II(b, c, d, a, myBlock[1], 21'i8, 0x85845DD1'i32)
-  II(a, b, c, d, myBlock[8], 6'i8, 0x6FA87E4F'i32)
-  II(d, a, b, c, myBlock[15], 10'i8, 0xFE2CE6E0'i32)
-  II(c, d, a, b, myBlock[6], 15'i8, 0xA3014314'i32)
-  II(b, c, d, a, myBlock[13], 21'i8, 0x4E0811A1'i32)
-  II(a, b, c, d, myBlock[4], 6'i8, 0xF7537E82'i32)
-  II(d, a, b, c, myBlock[11], 10'i8, 0xBD3AF235'i32)
-  II(c, d, a, b, myBlock[2], 15'i8, 0x2AD7D2BB'i32)
-  II(b, c, d, a, myBlock[9], 21'i8, 0xEB86D391'i32)
-  state[0] = state[0] +% a
-  state[1] = state[1] +% b
-  state[2] = state[2] +% c
-  state[3] = state[3] +% d
-  
-proc md5Init*(c: var MD5Context) = 
-  ## initializes a MD5Context  
-  c.state[0] = 0x67452301'i32
-  c.state[1] = 0xEFCDAB89'i32
-  c.state[2] = 0x98BADCFE'i32
-  c.state[3] = 0x10325476'i32
-  c.count[0] = 0'i32
-  c.count[1] = 0'i32
+  FF(a, b, c, d, myBlock[0], 7'u8, 0xD76AA478'u32)
+  FF(d, a, b, c, myBlock[1], 12'u8, 0xE8C7B756'u32)
+  FF(c, d, a, b, myBlock[2], 17'u8, 0x242070DB'u32)
+  FF(b, c, d, a, myBlock[3], 22'u8, 0xC1BDCEEE'u32)
+  FF(a, b, c, d, myBlock[4], 7'u8, 0xF57C0FAF'u32)
+  FF(d, a, b, c, myBlock[5], 12'u8, 0x4787C62A'u32)
+  FF(c, d, a, b, myBlock[6], 17'u8, 0xA8304613'u32)
+  FF(b, c, d, a, myBlock[7], 22'u8, 0xFD469501'u32)
+  FF(a, b, c, d, myBlock[8], 7'u8, 0x698098D8'u32)
+  FF(d, a, b, c, myBlock[9], 12'u8, 0x8B44F7AF'u32)
+  FF(c, d, a, b, myBlock[10], 17'u8, 0xFFFF5BB1'u32)
+  FF(b, c, d, a, myBlock[11], 22'u8, 0x895CD7BE'u32)
+  FF(a, b, c, d, myBlock[12], 7'u8, 0x6B901122'u32)
+  FF(d, a, b, c, myBlock[13], 12'u8, 0xFD987193'u32)
+  FF(c, d, a, b, myBlock[14], 17'u8, 0xA679438E'u32)
+  FF(b, c, d, a, myBlock[15], 22'u8, 0x49B40821'u32)
+  GG(a, b, c, d, myBlock[1], 5'u8, 0xF61E2562'u32)
+  GG(d, a, b, c, myBlock[6], 9'u8, 0xC040B340'u32)
+  GG(c, d, a, b, myBlock[11], 14'u8, 0x265E5A51'u32)
+  GG(b, c, d, a, myBlock[0], 20'u8, 0xE9B6C7AA'u32)
+  GG(a, b, c, d, myBlock[5], 5'u8, 0xD62F105D'u32)
+  GG(d, a, b, c, myBlock[10], 9'u8, 0x02441453'u32)
+  GG(c, d, a, b, myBlock[15], 14'u8, 0xD8A1E681'u32)
+  GG(b, c, d, a, myBlock[4], 20'u8, 0xE7D3FBC8'u32)
+  GG(a, b, c, d, myBlock[9], 5'u8, 0x21E1CDE6'u32)
+  GG(d, a, b, c, myBlock[14], 9'u8, 0xC33707D6'u32)
+  GG(c, d, a, b, myBlock[3], 14'u8, 0xF4D50D87'u32)
+  GG(b, c, d, a, myBlock[8], 20'u8, 0x455A14ED'u32)
+  GG(a, b, c, d, myBlock[13], 5'u8, 0xA9E3E905'u32)
+  GG(d, a, b, c, myBlock[2], 9'u8, 0xFCEFA3F8'u32)
+  GG(c, d, a, b, myBlock[7], 14'u8, 0x676F02D9'u32)
+  GG(b, c, d, a, myBlock[12], 20'u8, 0x8D2A4C8A'u32)
+  HH(a, b, c, d, myBlock[5], 4'u8, 0xFFFA3942'u32)
+  HH(d, a, b, c, myBlock[8], 11'u8, 0x8771F681'u32)
+  HH(c, d, a, b, myBlock[11], 16'u8, 0x6D9D6122'u32)
+  HH(b, c, d, a, myBlock[14], 23'u8, 0xFDE5380C'u32)
+  HH(a, b, c, d, myBlock[1], 4'u8, 0xA4BEEA44'u32)
+  HH(d, a, b, c, myBlock[4], 11'u8, 0x4BDECFA9'u32)
+  HH(c, d, a, b, myBlock[7], 16'u8, 0xF6BB4B60'u32)
+  HH(b, c, d, a, myBlock[10], 23'u8, 0xBEBFBC70'u32)
+  HH(a, b, c, d, myBlock[13], 4'u8, 0x289B7EC6'u32)
+  HH(d, a, b, c, myBlock[0], 11'u8, 0xEAA127FA'u32)
+  HH(c, d, a, b, myBlock[3], 16'u8, 0xD4EF3085'u32)
+  HH(b, c, d, a, myBlock[6], 23'u8, 0x04881D05'u32)
+  HH(a, b, c, d, myBlock[9], 4'u8, 0xD9D4D039'u32)
+  HH(d, a, b, c, myBlock[12], 11'u8, 0xE6DB99E5'u32)
+  HH(c, d, a, b, myBlock[15], 16'u8, 0x1FA27CF8'u32)
+  HH(b, c, d, a, myBlock[2], 23'u8, 0xC4AC5665'u32)
+  II(a, b, c, d, myBlock[0], 6'u8, 0xF4292244'u32)
+  II(d, a, b, c, myBlock[7], 10'u8, 0x432AFF97'u32)
+  II(c, d, a, b, myBlock[14], 15'u8, 0xAB9423A7'u32)
+  II(b, c, d, a, myBlock[5], 21'u8, 0xFC93A039'u32)
+  II(a, b, c, d, myBlock[12], 6'u8, 0x655B59C3'u32)
+  II(d, a, b, c, myBlock[3], 10'u8, 0x8F0CCC92'u32)
+  II(c, d, a, b, myBlock[10], 15'u8, 0xFFEFF47D'u32)
+  II(b, c, d, a, myBlock[1], 21'u8, 0x85845DD1'u32)
+  II(a, b, c, d, myBlock[8], 6'u8, 0x6FA87E4F'u32)
+  II(d, a, b, c, myBlock[15], 10'u8, 0xFE2CE6E0'u32)
+  II(c, d, a, b, myBlock[6], 15'u8, 0xA3014314'u32)
+  II(b, c, d, a, myBlock[13], 21'u8, 0x4E0811A1'u32)
+  II(a, b, c, d, myBlock[4], 6'u8, 0xF7537E82'u32)
+  II(d, a, b, c, myBlock[11], 10'u8, 0xBD3AF235'u32)
+  II(c, d, a, b, myBlock[2], 15'u8, 0x2AD7D2BB'u32)
+  II(b, c, d, a, myBlock[9], 21'u8, 0xEB86D391'u32)
+  state[0] = state[0] + a
+  state[1] = state[1] + b
+  state[2] = state[2] + c
+  state[3] = state[3] + d
+
+proc md5Init*(c: var MD5Context) =
+  ## initializes a MD5Context
+  c.state[0] = 0x67452301'u32
+  c.state[1] = 0xEFCDAB89'u32
+  c.state[2] = 0x98BADCFE'u32
+  c.state[3] = 0x10325476'u32
+  c.count[0] = 0'u32
+  c.count[1] = 0'u32
   zeroMem(addr(c.buffer), sizeof(MD5buffer))
 
-proc md5Update*(c: var MD5Context, input: cstring, len: int) = 
+proc md5Update*(c: var MD5Context, input: cstring, len: int) =
   ## updates the MD5Context with the `input` data of length `len`
   var input = input
-  var Index = (c.count[0] shr 3) and 0x3F
-  c.count[0] = c.count[0] +% toU32(len shl 3)
-  if c.count[0] < (len shl 3): c.count[1] = c.count[1] +% 1'i32
-  c.count[1] = c.count[1] +% toU32(len shr 29)
+  var Index = int((c.count[0] shr 3) and 0x3F)
+  c.count[0] = c.count[0] + (uint32(len) shl 3)
+  if c.count[0] < (uint32(len) shl 3): c.count[1] = c.count[1] + 1'u32
+  c.count[1] = c.count[1] + (uint32(len) shr 29)
   var PartLen = 64 - Index
-  if len >= PartLen: 
+  if len >= PartLen:
     copyMem(addr(c.buffer[Index]), input, PartLen)
     transform(addr(c.buffer), c.state)
     var i = PartLen
-    while i + 63 < len: 
+    while i + 63 < len:
       transform(addr(input[i]), c.state)
       inc(i, 64)
     copyMem(addr(c.buffer[0]), addr(input[i]), len-i)
   else:
     copyMem(addr(c.buffer[Index]), addr(input[0]), len)
 
-proc md5Final*(c: var MD5Context, digest: var MD5Digest) = 
+proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
   ## finishes the MD5Context and stores the result in `digest`
   var
     Bits: MD5CBits
     PadLen: int
   decode(Bits, c.count)
-  var Index = (c.count[0] shr 3) and 0x3F
+  var Index = int((c.count[0] shr 3) and 0x3F)
   if Index < 56: PadLen = 56 - Index
   else: PadLen = 120 - Index
   md5Update(c, padding, PadLen)
@@ -204,34 +206,34 @@ proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
   decode(digest, c.state)
   zeroMem(addr(c), sizeof(MD5Context))
 
-proc toMD5*(s: string): MD5Digest = 
+proc toMD5*(s: string): MD5Digest =
   ## computes the MD5Digest value for a string `s`
   var c: MD5Context
   md5Init(c)
   md5Update(c, cstring(s), len(s))
   md5Final(c, result)
-  
-proc `$`*(D: MD5Digest): string = 
+
+proc `$`*(d: MD5Digest): string =
   ## converts a MD5Digest value into its string representation
   const digits = "0123456789abcdef"
   result = ""
-  for i in 0..15: 
-    add(result, digits[(D[i] shr 4) and 0xF])
-    add(result, digits[D[i] and 0xF])
+  for i in 0..15:
+    add(result, digits[(d[i] shr 4) and 0xF])
+    add(result, digits[d[i] and 0xF])
 
-proc getMD5*(s: string): string =  
+proc getMD5*(s: string): string =
   ## computes an MD5 value of `s` and returns its string representation
-  var 
+  var
     c: MD5Context
     d: MD5Digest
   md5Init(c)
   md5Update(c, cstring(s), len(s))
   md5Final(c, d)
   result = $d
-  
-proc `==`*(D1, D2: MD5Digest): bool =  
+
+proc `==`*(D1, D2: MD5Digest): bool =
   ## checks if two MD5Digest values are identical
-  for i in 0..15: 
+  for i in 0..15:
     if D1[i] != D2[i]: return false
   return true
 
@@ -241,5 +243,3 @@ when isMainModule:
   assert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
     "7e716d0e702df0505fc72e2b89467910")
   assert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e")
-
-
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 24dbfb6d3..d49dfae9f 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Nim Contributors
+#        (c) Copyright 2015 Nim Contributors
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/pure/mersenne.nim b/lib/pure/mersenne.nim
index a6a781cb8..74112e304 100644
--- a/lib/pure/mersenne.nim
+++ b/lib/pure/mersenne.nim
@@ -32,7 +32,7 @@ proc getNum*(m: var MersenneTwister): int =
   return int(y)
 
 # Test
-when isMainModule:
+when not defined(testing) and isMainModule:
   var mt = newMersenneTwister(2525)
 
   for i in 0..99:
diff --git a/lib/pure/mimetypes.nim b/lib/pure/mimetypes.nim
index a52ba4ebe..642419e64 100644
--- a/lib/pure/mimetypes.nim
+++ b/lib/pure/mimetypes.nim
@@ -518,5 +518,5 @@ proc register*(mimedb: var MimeDB, ext: string, mimetype: string) =
 
 when isMainModule:
   var m = newMimetypes()
-  echo m.getMimetype("mp4")
-  echo m.getExt("text/html")
+  assert m.getMimetype("mp4") == "video/mp4"
+  assert m.getExt("text/html") == "html"
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index e6fe79740..ffbc6e320 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -60,7 +60,8 @@ type
         sslHasPeekChar: bool
         sslPeekChar: char
       of false: nil
-  
+    lastError: OSErrorCode ## stores the last error on this socket
+
   Socket* = ref SocketImpl
 
   SOBool* = enum ## Boolean socket options.
@@ -80,6 +81,23 @@ type
     TReadLineResult: ReadLineResult, TSOBool: SOBool, PSocket: Socket,
     TSocketImpl: SocketImpl].}
 
+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 isIpAddress*(address_str: string): bool {.tags: [].}
+proc parseIpAddress*(address_str: string): TIpAddress
+
 proc isDisconnectionError*(flags: set[SocketFlag],
     lastError: OSErrorCode): bool =
   ## Determines whether ``lastError`` is a disconnection error. Only does this
@@ -119,7 +137,7 @@ proc newSocket*(domain, typ, protocol: cint, buffered = true): Socket =
   result = newSocket(fd, buffered)
 
 proc newSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
-             protocol: Protocol = IPPROTO_TCP, buffered = true): Socket =
+                protocol: Protocol = IPPROTO_TCP, buffered = true): Socket =
   ## Creates a new socket.
   ##
   ## If an error occurs EOS will be raised.
@@ -231,6 +249,15 @@ when defined(ssl):
     if SSLSetFd(socket.sslHandle, socket.fd) != 1:
       raiseSSLError()
 
+proc getSocketError*(socket: Socket): OSErrorCode =
+  ## Checks ``osLastError`` for a valid error. If it has been reset it uses
+  ## the last error stored in the socket object.
+  result = osLastError()
+  if result == 0.OSErrorCode:
+    result = socket.lastError
+  if result == 0.OSErrorCode:
+    raise newException(OSError, "No valid socket error code available")
+
 proc socketError*(socket: Socket, err: int = -1, async = false,
                   lastError = (-1).OSErrorCode) =
   ## Raises an OSError based on the error code returned by ``SSLGetError``
@@ -258,7 +285,7 @@ proc socketError*(socket: Socket, err: int = -1, async = false,
         of SSL_ERROR_WANT_X509_LOOKUP:
           raiseSSLError("Function for x509 lookup has been called.")
         of SSL_ERROR_SYSCALL:
-          var errStr = "IO error has occured "
+          var errStr = "IO error has occurred "
           let sslErr = ErrPeekLastError()
           if sslErr == 0 and err == 0:
             errStr.add "because an EOF was observed that violates the protocol"
@@ -276,7 +303,7 @@ proc socketError*(socket: Socket, err: int = -1, async = false,
         else: raiseSSLError("Unknown Error")
   
   if err == -1 and not (when defined(ssl): socket.isSSL else: false):
-    let lastE = if lastError.int == -1: osLastError() else: lastError
+    var lastE = if lastError.int == -1: getSocketError(socket) else: lastError
     if async:
       when useWinVersion:
         if lastE.int32 == WSAEWOULDBLOCK:
@@ -294,7 +321,8 @@ proc listen*(socket: Socket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} =
   ## queue of pending connections.
   ##
   ## Raises an EOS error upon failure.
-  if listen(socket.fd, backlog) < 0'i32: raiseOSError(osLastError())
+  if rawsockets.listen(socket.fd, backlog) < 0'i32:
+    raiseOSError(osLastError())
 
 proc bindAddr*(socket: Socket, port = Port(0), address = "") {.
   tags: [ReadIOEffect].} =
@@ -321,7 +349,8 @@ proc bindAddr*(socket: Socket, port = Port(0), address = "") {.
     dealloc(aiList)
 
 proc acceptAddr*(server: Socket, client: var Socket, address: var string,
-                 flags = {SocketFlag.SafeDisconn}) {.tags: [ReadIOEffect].} =
+                 flags = {SocketFlag.SafeDisconn}) {.
+                 tags: [ReadIOEffect], gcsafe, locks: 0.} =
   ## 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.
@@ -442,6 +471,8 @@ proc close*(socket: Socket) =
         # shutdown i.e not wait for the peers "close notify" alert with a second
         # call to SSLShutdown
         let res = SSLShutdown(socket.sslHandle)
+        SSLFree(socket.sslHandle)
+        socket.sslHandle = nil
         if res == 0:
           discard
         elif res != 1:
@@ -497,6 +528,12 @@ proc connect*(socket: Socket, address: string, port = Port(0),
   
   when defined(ssl):
     if socket.isSSL:
+      # RFC3546 for SNI specifies that IP addresses are not allowed.
+      if not isIpAddress(address):
+        # Discard result in case OpenSSL version doesn't support SNI, or we're
+        # not using TLSv1+
+        discard SSL_set_tlsext_host_name(socket.sslHandle, address)
+
       let ret = SSLConnect(socket.sslHandle)
       socketError(socket, ret)
 
@@ -568,6 +605,10 @@ proc readIntoBuf(socket: Socket, flags: int32): int =
       result = recv(socket.fd, addr(socket.buffer), cint(socket.buffer.high), flags)
   else:
     result = recv(socket.fd, addr(socket.buffer), cint(socket.buffer.high), flags)
+  if result < 0:
+    # Save it in case it gets reset (the Nim codegen occassionally may call
+    # Win API functions which reset it).
+    socket.lastError = osLastError()
   if result <= 0:
     socket.bufLen = 0
     socket.currPos = 0
@@ -623,6 +664,9 @@ proc recv*(socket: Socket, data: pointer, size: int): int {.tags: [ReadIOEffect]
         result = recv(socket.fd, data, size.cint, 0'i32)
     else:
       result = recv(socket.fd, data, size.cint, 0'i32)
+    if result < 0:
+      # Save the error in case it gets reset.
+      socket.lastError = osLastError()
 
 proc waitFor(socket: Socket, waited: var float, timeout, size: int,
              funcName: string): int {.tags: [TimeEffect].} =
@@ -695,7 +739,7 @@ proc recv*(socket: Socket, data: var string, size: int, timeout = -1,
   result = recv(socket, cstring(data), size, timeout)
   if result < 0:
     data.setLen(0)
-    let lastError = osLastError()
+    let lastError = getSocketError(socket)
     if flags.isDisconnectionError(lastError): return
     socket.socketError(result, lastError = lastError)
   data.setLen(result)
@@ -743,7 +787,7 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
       line.add("\c\L")
 
   template raiseSockError(): stmt {.dirty, immediate.} =
-    let lastError = osLastError()
+    let lastError = getSocketError(socket)
     if flags.isDisconnectionError(lastError): setLen(line.string, 0); return
     socket.socketError(n, lastError = lastError)
 
@@ -886,7 +930,7 @@ proc connectAsync(socket: Socket, name: string, port = Port(0),
                   af: Domain = AF_INET) {.tags: [ReadIOEffect].} =
   ## A variant of ``connect`` for non-blocking sockets.
   ##
-  ## This procedure will immediatelly return, it will not block until a connection
+  ## This procedure will immediately return, it will not block until a connection
   ## is made. It is up to the caller to make sure the connection has been established
   ## by checking (using ``select``) whether the socket is writeable.
   ##
@@ -938,26 +982,16 @@ proc connect*(socket: Socket, address: string, port = Port(0), timeout: int,
         doAssert socket.handshake()
   socket.fd.setBlocking(true)
 
-proc isSsl*(socket: Socket): bool = return socket.isSSL
+proc isSsl*(socket: Socket): bool = 
   ## Determines whether ``socket`` is a SSL socket.
+  when defined(ssl):
+    result = socket.isSSL
+  else:
+    result = false
 
 proc getFd*(socket: Socket): SocketHandle = 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
@@ -1216,7 +1250,7 @@ proc parseIPv6Address(address_str: string): TIpAddress =
     raise newException(ValueError,
       "Invalid IP Address. The address consists of too many groups")
 
-proc parseIpAddress*(address_str: string): TIpAddress =
+proc parseIpAddress(address_str: string): TIpAddress =
   ## Parses an IP address
   ## Raises EInvalidValue on error
   if address_str == nil:
@@ -1225,3 +1259,13 @@ proc parseIpAddress*(address_str: string): TIpAddress =
     return parseIPv6Address(address_str)
   else:
     return parseIPv4Address(address_str)
+
+
+proc isIpAddress(address_str: string): bool =
+  ## Checks if a string is an IP address
+  ## Returns true if it is, false otherwise
+  try:
+    discard parseIpAddress(address_str)
+  except ValueError:
+    return false
+  return true
diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim
index 3598cdd3a..cce2a20ae 100644
--- a/lib/pure/nimprof.nim
+++ b/lib/pure/nimprof.nim
@@ -132,7 +132,7 @@ else:
   proc hook(st: TStackTrace) {.nimcall.} =
     if interval == 0:
       hookAux(st, 1)
-    elif getTicks() - t0 > interval:
+    elif int64(t0) == 0 or getTicks() - t0 > interval:
       hookAux(st, 1)
       t0 = getTicks()
 
diff --git a/lib/pure/nimprof.nimrod.cfg b/lib/pure/nimprof.nim.cfg
index 1589e7394..1589e7394 100644
--- a/lib/pure/nimprof.nimrod.cfg
+++ b/lib/pure/nimprof.nim.cfg
diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim
index 0dc8e3c15..ac90dd16b 100644
--- a/lib/pure/oids.nim
+++ b/lib/pure/oids.nim
@@ -88,6 +88,6 @@ proc generatedTime*(oid: Oid): Time =
   bigEndian32(addr(tmp), addr(dummy))
   result = Time(tmp)
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   let xo = genOid()
   echo xo.generatedTime
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index ad82dc682..f53abe81d 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -185,7 +185,7 @@ const
 proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
   ## Retrieves the operating system's error flag, ``errno``.
   ## On Windows ``GetLastError`` is checked before ``errno``.
-  ## Returns "" if no error occured.
+  ## Returns "" if no error occurred.
   ##
   ## **Deprecated since version 0.9.4**: use the other ``osErrorMsg`` proc.
 
@@ -599,7 +599,7 @@ proc splitPath*(path: string): tuple[head, tail: string] {.
 
 proc parentDirPos(path: string): int =
   var q = 1
-  if path[len(path)-1] in {DirSep, AltSep}: q = 2
+  if len(path) >= 1 and path[len(path)-1] in {DirSep, AltSep}: q = 2
   for i in countdown(len(path)-q, 0):
     if path[i] in {DirSep, AltSep}: return i
   result = -1
@@ -1010,8 +1010,16 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
 proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
   tags: [ReadIOEffect, WriteIOEffect].} =
   ## Moves a file from `source` to `dest`. If this fails, `OSError` is raised.
-  if c_rename(source, dest) != 0'i32:
-    raise newException(OSError, $strerror(errno))
+  when defined(Windows):
+    when useWinUnicode:
+      let s = newWideCString(source)
+      let d = newWideCString(dest)
+      if moveFileW(s, d, 0'i32) == 0'i32: raiseOSError(osLastError())
+    else:
+      if moveFileA(source, dest, 0'i32) == 0'i32: raiseOSError(osLastError())
+  else:
+    if c_rename(source, dest) != 0'i32:
+      raise newException(OSError, $strerror(errno))
 
 when not declared(ENOENT) and not defined(Windows):
   when NoFakeVars:
@@ -1074,8 +1082,12 @@ when defined(windows):
   # because we support Windows GUI applications, things get really
   # messy here...
   when useWinUnicode:
-    proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
-      importc: "wcschr", header: "<string.h>".}
+    when defined(cpp):
+      proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
+        importcpp: "(NI16*)wcschr((const wchar_t *)#, #)", header: "<string.h>".}
+    else:
+      proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
+        importc: "wcschr", header: "<string.h>".}
   else:
     proc strEnd(cstr: cstring, c = 0'i32): cstring {.
       importc: "strchr", header: "<string.h>".}
@@ -1087,7 +1099,7 @@ when defined(windows):
         var
           env = getEnvironmentStringsW()
           e = env
-        if e == nil: return # an error occured
+        if e == nil: return # an error occurred
         while true:
           var eend = strEnd(e)
           add(environment, $e)
@@ -1098,7 +1110,7 @@ when defined(windows):
         var
           env = getEnvironmentStringsA()
           e = env
-        if e == nil: return # an error occured
+        if e == nil: return # an error occurred
         while true:
           var eend = strEnd(e)
           add(environment, $e)
@@ -1109,8 +1121,8 @@ when defined(windows):
 
 else:
   const
-    useNSGetEnviron = defined(macosx) and
-      (defined(createNimRtl) or defined(useNimRtl))
+    useNSGetEnviron = defined(macosx)
+
   when useNSGetEnviron:
     # From the manual:
     # Shared libraries and bundles don't have direct access to environ,
@@ -1170,7 +1182,7 @@ proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
   ## If an error occurs, `EInvalidEnvVar` is raised.
 
   # Note: by storing the string in the environment sequence,
-  # we gurantee that we don't free the memory before the program
+  # we guarantee that we don't free the memory before the program
   # ends (this is needed for POSIX compliance). It is also needed so that
   # the process itself may access its modified environment variables!
   var indx = findEnvVar(key)
@@ -1287,8 +1299,16 @@ iterator walkDir*(dir: string): tuple[kind: PathComponent, path: string] {.
         if y != "." and y != "..":
           var s: TStat
           y = dir / y
-          if lstat(y, s) < 0'i32: break
           var k = pcFile
+
+          when defined(linux) or defined(macosx) or defined(bsd):
+            if x.d_type != DT_UNKNOWN:
+              if x.d_type == DT_DIR: k = pcDir
+              if x.d_type == DT_LNK: k = succ(k)
+              yield (k, y)
+              continue
+
+          if lstat(y, s) < 0'i32: break
           if S_ISDIR(s.st_mode): k = pcDir
           if S_ISLNK(s.st_mode): k = succ(k)
           yield (k, y)
@@ -1335,7 +1355,7 @@ proc rawRemoveDir(dir: string) =
     if rmdir(dir) != 0'i32 and errno != ENOENT: raiseOSError(osLastError())
 
 proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
-  WriteDirEffect, ReadDirEffect].} =
+  WriteDirEffect, ReadDirEffect], benign.} =
   ## Removes the directory `dir` including all subdirectories and files
   ## in `dir` (recursively).
   ##
@@ -1381,7 +1401,7 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect].} =
   rawCreateDir(dir)
 
 proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
-  tags: [WriteIOEffect, ReadIOEffect].} =
+  tags: [WriteIOEffect, ReadIOEffect], benign.} =
   ## Copies a directory from `source` to `dest`.
   ##
   ## If this fails, `OSError` is raised. On the Windows platform this proc will
@@ -1442,7 +1462,7 @@ proc createHardlink*(src, dest: string) =
 proc parseCmdLine*(c: string): seq[string] {.
   noSideEffect, rtl, extern: "nos$1".} =
   ## Splits a command line into several components;
-  ## This proc is only occassionally useful, better use the `parseopt` module.
+  ## This proc is only occasionally useful, better use the `parseopt` module.
   ##
   ## On Windows, it uses the following parsing rules
   ## (see http://msdn.microsoft.com/en-us/library/17w5ykft.aspx ):
@@ -1554,7 +1574,7 @@ proc copyFileWithPermissions*(source, dest: string,
 
 proc copyDirWithPermissions*(source, dest: string,
     ignorePermissionErrors = true) {.rtl, extern: "nos$1",
-    tags: [WriteIOEffect, ReadIOEffect].} =
+    tags: [WriteIOEffect, ReadIOEffect], benign.} =
   ## Copies a directory from `source` to `dest` preserving file permissions.
   ##
   ## If this fails, `OSError` is raised. This is a wrapper proc around `copyDir()
@@ -1843,16 +1863,21 @@ proc getFileSize*(file: string): BiggestInt {.rtl, extern: "nos$1",
       close(f)
     else: raiseOSError(osLastError())
 
+proc expandTilde*(path: string): string {.tags: [ReadEnvEffect].}
+
 proc findExe*(exe: string): string {.tags: [ReadDirEffect, ReadEnvEffect].} =
   ## Searches for `exe` in the current working directory and then
   ## in directories listed in the ``PATH`` environment variable.
   ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe`
-  ## is added an ``.exe`` file extension if it has no extension.
+  ## is added the `ExeExt <#ExeExt>`_ file extension if it has none.
   result = addFileExt(exe, os.ExeExt)
   if existsFile(result): return
   var path = string(os.getEnv("PATH"))
   for candidate in split(path, PathSep):
-    var x = candidate / result
+    when defined(windows):
+      var x = candidate / result
+    else:
+      var x = expandTilde(candidate) / result
     if existsFile(x): return x
   result = ""
 
@@ -1977,6 +2002,8 @@ proc getFileInfo*(handle: FileHandle): FileInfo =
     rawToFormalFileInfo(rawInfo, result)
 
 proc getFileInfo*(file: File): FileInfo =
+  if file.isNil:
+    raise newException(IOError, "File is nil")
   result = getFileInfo(file.getFileHandle())
 
 proc getFileInfo*(path: string, followSymlink = true): FileInfo =
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index bfdb0efed..dce0673ba 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -137,7 +137,7 @@ proc startProcess*(command: string,
   ## `env` is the environment that will be passed to the process.
   ## If ``env == nil`` the environment is inherited of
   ## the parent process. `options` are additional flags that may be passed
-  ## to `startProcess`. See the documentation of ``TProcessOption`` for the
+  ## to `startProcess`. See the documentation of ``ProcessOption`` for the
   ## meaning of these flags. You need to `close` the process when done.
   ##
   ## Note that you can't pass any `args` if you use the option
@@ -146,7 +146,7 @@ proc startProcess*(command: string,
   ## of `args` to `command` carefully escaping/quoting any special characters,
   ## since it will be passed *as is* to the system shell. Each system/shell may
   ## feature different escaping rules, so try to avoid this kind of shell
-  ## invokation if possible as it leads to non portable software.
+  ## invocation if possible as it leads to non portable software.
   ##
   ## Return value: The newly created process object. Nil is never returned,
   ## but ``EOS`` is raised in case of an error.
@@ -174,7 +174,7 @@ proc terminate*(p: Process) {.rtl, extern: "nosp$1", tags: [].}
 proc kill*(p: Process) {.rtl, extern: "nosp$1", tags: [].}
   ## Kill the process `p`. On Posix OSes the procedure sends ``SIGKILL`` to
   ## the process. On Windows ``kill()`` is simply an alias for ``terminate()``.
-  
+
 proc running*(p: Process): bool {.rtl, extern: "nosp$1", tags: [].}
   ## Returns true iff the process `p` is still running. Returns immediately.
 
@@ -260,7 +260,7 @@ proc execProcesses*(cmds: openArray[string],
     for i in 0..m-1:
       if beforeRunEvent != nil:
         beforeRunEvent(i)
-      q[i] = startCmd(cmds[i], options=options)
+      q[i] = startProcess(cmds[i], options=options + {poEvalCommand})
     when defined(noBusyWaiting):
       var r = 0
       for i in m..high(cmds):
@@ -275,7 +275,7 @@ proc execProcesses*(cmds: openArray[string],
         if q[r] != nil: close(q[r])
         if beforeRunEvent != nil:
           beforeRunEvent(i)
-        q[r] = startCmd(cmds[i], options=options)
+        q[r] = startProcess(cmds[i], options=options + {poEvalCommand})
         r = (r + 1) mod n
     else:
       var i = m
@@ -288,7 +288,7 @@ proc execProcesses*(cmds: openArray[string],
             if q[r] != nil: close(q[r])
             if beforeRunEvent != nil:
               beforeRunEvent(i)
-            q[r] = startCmd(cmds[i], options=options)
+            q[r] = startProcess(cmds[i], options=options + {poEvalCommand})
             inc(i)
             if i > high(cmds): break
     for j in 0..m-1:
@@ -298,7 +298,7 @@ proc execProcesses*(cmds: openArray[string],
     for i in 0..high(cmds):
       if beforeRunEvent != nil:
         beforeRunEvent(i)
-      var p = startCmd(cmds[i], options=options)
+      var p = startProcess(cmds[i], options=options + {poEvalCommand})
       result = max(waitForExit(p), result)
       close(p)
 
@@ -644,14 +644,14 @@ elif not defined(useNimRtl):
     var pid: TPid
 
     var sysArgs = allocCStringArray(sysArgsRaw)
-    finally: deallocCStringArray(sysArgs)
+    defer: deallocCStringArray(sysArgs)
 
     var sysEnv = if env == nil:
         envToCStringArray()
       else:
         envToCStringArray(env)
 
-    finally: deallocCStringArray(sysEnv)
+    defer: deallocCStringArray(sysEnv)
 
     var data: TStartProcessData
     data.sysCommand = sysCommand
@@ -666,7 +666,7 @@ elif not defined(useNimRtl):
     data.workingDir = workingDir
 
 
-    when declared(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:
@@ -748,7 +748,7 @@ elif not defined(useNimRtl):
     if pipe(data.pErrorPipe) != 0:
       raiseOSError(osLastError())
 
-    finally:
+    defer:
       discard close(data.pErrorPipe[readIdx])
 
     var pid: TPid
@@ -823,7 +823,7 @@ elif not defined(useNimRtl):
         discard execvp(data.sysCommand, data.sysArgs)
       else:
         when defined(uClibc):
-          # uClibc environment (OpenWrt included) doesn't have the full execvpe 
+          # uClibc environment (OpenWrt included) doesn't have the full execvpe
           discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
         else:
           discard execvpe(data.sysCommand, data.sysArgs, data.sysEnv)
@@ -848,7 +848,14 @@ elif not defined(useNimRtl):
     if kill(p.id, SIGCONT) != 0'i32: raiseOsError(osLastError())
 
   proc running(p: Process): bool =
-    var ret = waitpid(p.id, p.exitCode, WNOHANG)
+    var ret : int
+    when not defined(freebsd):
+      ret = waitpid(p.id, p.exitCode, WNOHANG)
+    else:
+      var status : cint = 1
+      ret = waitpid(p.id, status, WNOHANG)
+      if WIFEXITED(status):
+        p.exitCode = status
     if ret == 0: return true # Can't establish status. Assume running.
     result = ret == int(p.id)
 
@@ -857,9 +864,9 @@ elif not defined(useNimRtl):
       raiseOsError(osLastError())
 
   proc kill(p: Process) =
-    if kill(p.id, SIGKILL) != 0'i32: 
+    if kill(p.id, SIGKILL) != 0'i32:
       raiseOsError(osLastError())
-    
+
   proc waitForExit(p: Process, timeout: int = -1): int =
     #if waitPid(p.id, p.exitCode, 0) == int(p.id):
     # ``waitPid`` fails if the process is not running anymore. But then
@@ -876,7 +883,7 @@ elif not defined(useNimRtl):
     var ret = waitpid(p.id, p.exitCode, WNOHANG)
     var b = ret == int(p.id)
     if b: result = -1
-    if p.exitCode == -3: result = -1
+    if not WIFEXITED(p.exitCode): result = -1
     else: result = p.exitCode.int shr 8
 
   proc createStream(stream: var Stream, handle: var FileHandle,
@@ -900,7 +907,7 @@ elif not defined(useNimRtl):
       createStream(p.errStream, p.errHandle, fmRead)
     return p.errStream
 
-  proc csystem(cmd: cstring): cint {.nodecl, importc: "system", 
+  proc csystem(cmd: cstring): cint {.nodecl, importc: "system",
                                      header: "<stdlib.h>".}
 
   proc execCmd(command: string): int =
@@ -949,7 +956,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
                 exitCode: int] {.tags: [ExecIOEffect, ReadIOEffect], gcsafe.} =
   ## a convenience proc that runs the `command`, grabs all its output and
   ## exit code and returns both.
-  var p = startCmd(command, options)
+  var p = startProcess(command, options=options + {poEvalCommand})
   var outp = outputStream(p)
   result = (TaintedString"", -1)
   var line = newStringOfCap(120).TaintedString
diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim
index bb9d2aed2..bb64c8134 100644
--- a/lib/pure/parsecfg.nim
+++ b/lib/pure/parsecfg.nim
@@ -35,7 +35,7 @@ type
     cfgSectionStart,    ## a ``[section]`` has been parsed
     cfgKeyValuePair,    ## a ``key=value`` pair has been detected
     cfgOption,          ## a ``--key=value`` command line option
-    cfgError            ## an error ocurred during parsing
+    cfgError            ## an error occurred during parsing
     
   CfgEvent* = object of RootObj ## describes a parsing event
     case kind*: CfgEventKind    ## the kind of the event
diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim
index f4943ed89..117d75cfa 100644
--- a/lib/pure/parsecsv.nim
+++ b/lib/pure/parsecsv.nim
@@ -166,7 +166,7 @@ proc close*(my: var CsvParser) {.inline.} =
   ## closes the parser `my` and its associated input stream.
   lexbase.close(my)
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   import os
   var s = newFileStream(paramStr(1), fmRead)
   if s == nil: quit("cannot open the file" & paramStr(1))
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index 8af6920c1..4c92a7cdf 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -11,9 +11,12 @@
 ## It supports one convenience iterator over all command line options and some
 ## lower-level features.
 ##
-## **Deprecated since version 0.9.3:** Use the `parseopt2 <parseopt2.html>`_
-## module instead as this version has issues with spaces in arguments.
-{.deprecated.}
+## Supported syntax:
+##
+## 1. short options - ``-abcd``, where a, b, c, d are names
+## 2. long option - ``--foo:bar``, ``--foo=bar`` or ``--foo``
+## 3. argument - everything else
+
 {.push debugger: off.}
 
 include "system/inclrtl"
diff --git a/lib/pure/parseopt2.nim b/lib/pure/parseopt2.nim
index 5b1f50958..73b498fe0 100644
--- a/lib/pure/parseopt2.nim
+++ b/lib/pure/parseopt2.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -60,7 +60,7 @@ proc initOptParser*(cmdline: string): OptParser {.rtl, deprecated.} =
   ## Initalizes option parses with cmdline. Splits cmdline in on spaces
   ## and calls initOptParser(openarray[string])
   ## Do not use.
-  if cmdline == "": # backward compatibilty
+  if cmdline == "": # backward compatibility
     return initOptParser(seq[string](nil))
   else:
     return initOptParser(cmdline.split)
diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim
index bb4ede779..91917b1c5 100644
--- a/lib/pure/parsesql.nim
+++ b/lib/pure/parsesql.nim
@@ -1330,7 +1330,7 @@ proc renderSQL*(n: SqlNode): string =
   result = ""
   ra(n, result, 0)
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   echo(renderSQL(parseSQL(newStringStream("""
       CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic');
       CREATE TABLE holidays (
diff --git a/lib/pure/parseurl.nim b/lib/pure/parseurl.nim
index f27cd8c12..56bf10768 100644
--- a/lib/pure/parseurl.nim
+++ b/lib/pure/parseurl.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index 1efb141fc..c07b713de 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -181,7 +181,7 @@ proc parseWhile*(s: string, token: var string, validChars: set[char],
   token = substr(s, start, i-1)
 
 proc captureBetween*(s: string, first: char, second = '\0', start = 0): string =
-  ## Finds the first occurence of ``first``, then returns everything from there
+  ## Finds the first occurrence of ``first``, then returns everything from there
   ## up to ``second``(if ``second`` is '\0', then ``first`` is used).
   var i = skipUntil(s, first, start)+1+start
   result = ""
@@ -228,7 +228,7 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
   if (sizeof(int) <= 4) and
       ((res < low(int)) or (res > high(int))):
     raise newException(OverflowError, "overflow")
-  else:
+  elif result != 0:
     number = int(res)
 
 proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
@@ -240,11 +240,12 @@ proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
 proc parseFloat*(s: string, number: var float, start = 0): int {.
   rtl, extern: "npuParseFloat", noSideEffect.} =
   ## parses a float starting at `start` and stores the value into `number`.
-  ## Result is the number of processed chars or 0 if there occured a parsing
+  ## Result is the number of processed chars or 0 if there occurred a parsing
   ## error.
   var bf: BiggestFloat
   result = parseBiggestFloat(s, bf, start)
-  number = bf
+  if result != 0:
+    number = bf
   
 type
   InterpolatedKind* = enum   ## describes for `interpolatedFragments`
@@ -294,7 +295,7 @@ iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind,
             dec nesting
           of '\0':
             raise newException(ValueError, 
-              "Expected closing '}': " & s[i..s.len])
+              "Expected closing '}': " & substr(s, i, s.high))
           else: discard
           inc j
         inc i, 2 # skip ${
@@ -310,7 +311,7 @@ iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind,
         kind = ikDollar
       else:
         raise newException(ValueError, 
-          "Unable to parse a varible name at " & s[i..s.len])
+          "Unable to parse a varible name at " & substr(s, i, s.high))
     else:
       while j < s.len and s[j] != '$': inc j
       kind = ikStr
@@ -322,8 +323,12 @@ iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind,
     i = j
 
 when isMainModule:
-  for k, v in interpolatedFragments("$test{}  $this is ${an{  example}}  "):
-    echo "(", k, ", \"", v, "\")"
+  import sequtils
+  let input = "$test{}  $this is ${an{  example}}  "
+  let expected = @[(ikVar, "test"), (ikStr, "{}  "), (ikVar, "this"),
+                   (ikStr, " is "), (ikExpr, "an{  example}"), (ikStr, "  ")]
+  assert toSeq(interpolatedFragments(input)) == expected
+
   var value = 0
   discard parseHex("0x38", value)
   assert value == 56
diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim
index 39dead3c0..eb792f086 100644
--- a/lib/pure/parsexml.nim
+++ b/lib/pure/parsexml.nim
@@ -57,7 +57,7 @@ import
 
 type 
   XmlEventKind* = enum ## enumation of all events that may occur when parsing
-    xmlError,           ## an error ocurred during parsing
+    xmlError,           ## an error occurred during parsing
     xmlEof,             ## end of file reached
     xmlCharData,        ## character data
     xmlWhitespace,      ## whitespace has been parsed
@@ -128,6 +128,7 @@ proc open*(my: var XmlParser, input: Stream, filename: string,
   my.kind = xmlError
   my.a = ""
   my.b = ""
+  my.c = nil
   my.options = options
   
 proc close*(my: var XmlParser) {.inline.} = 
@@ -138,43 +139,43 @@ proc kind*(my: XmlParser): XmlEventKind {.inline.} =
   ## returns the current event type for the XML parser
   return my.kind
 
-proc charData*(my: XmlParser): string {.inline.} = 
+template charData*(my: XmlParser): string =
   ## returns the character data for the events: ``xmlCharData``, 
   ## ``xmlWhitespace``, ``xmlComment``, ``xmlCData``, ``xmlSpecial``
   assert(my.kind in {xmlCharData, xmlWhitespace, xmlComment, xmlCData, 
                      xmlSpecial})
-  return my.a
+  my.a
 
-proc elementName*(my: XmlParser): string {.inline.} = 
+template elementName*(my: XmlParser): string =
   ## returns the element name for the events: ``xmlElementStart``, 
   ## ``xmlElementEnd``, ``xmlElementOpen``
   assert(my.kind in {xmlElementStart, xmlElementEnd, xmlElementOpen})
-  return my.a
+  my.a
 
-proc entityName*(my: XmlParser): string {.inline.} = 
+template entityName*(my: XmlParser): string =
   ## returns the entity name for the event: ``xmlEntity``
   assert(my.kind == xmlEntity)
-  return my.a
+  my.a
   
-proc attrKey*(my: XmlParser): string {.inline.} = 
+template attrKey*(my: XmlParser): string =
   ## returns the attribute key for the event ``xmlAttribute``
   assert(my.kind == xmlAttribute)
-  return my.a
+  my.a
   
-proc attrValue*(my: XmlParser): string {.inline.} = 
+template attrValue*(my: XmlParser): string =
   ## returns the attribute value for the event ``xmlAttribute``
   assert(my.kind == xmlAttribute)
-  return my.b
+  my.b
 
-proc piName*(my: XmlParser): string {.inline.} = 
+template piName*(my: XmlParser): string =
   ## returns the processing instruction name for the event ``xmlPI``
   assert(my.kind == xmlPI)
-  return my.a
+  my.a
 
-proc piRest*(my: XmlParser): string {.inline.} = 
+template piRest*(my: XmlParser): string =
   ## returns the rest of the processing instruction for the event ``xmlPI``
   assert(my.kind == xmlPI)
-  return my.b
+  my.b
 
 proc rawData*(my: XmlParser): string {.inline.} =
   ## returns the underlying 'data' string by reference.
@@ -621,13 +622,13 @@ proc next*(my: var XmlParser) =
   of stateEmptyElementTag:
     my.state = stateNormal
     my.kind = xmlElementEnd
-    if not isNil(my.c):
+    if not my.c.isNil:
       my.a = my.c
   of stateError: 
     my.kind = xmlError
     my.state = stateNormal
   
-when isMainModule:
+when not defined(testing) and isMainModule:
   import os
   var s = newFileStream(paramStr(1), fmRead)
   if s == nil: quit("cannot open the file" & paramStr(1))
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 7cef0a00d..39f0bfa95 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -29,7 +29,7 @@ when useUnicode:
 const
   InlineThreshold = 5  ## number of leaves; -1 to disable inlining
   MaxSubpatterns* = 20 ## defines the maximum number of subpatterns that
-                       ## can be captured. More subpatterns cannot be captured! 
+                       ## can be captured. More subpatterns cannot be captured!
 
 type
   PegKind = enum
@@ -85,14 +85,14 @@ type
     of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns]
     else: sons: seq[TNode]
   NonTerminal* = ref NonTerminalObj
-  
+
   Peg* = TNode ## type that represents a PEG
 
 {.deprecated: [TPeg: Peg].}
 
 proc term*(t: string): Peg {.nosideEffect, rtl, extern: "npegs$1Str".} =
   ## constructs a PEG from a terminal string
-  if t.len != 1:  
+  if t.len != 1:
     result.kind = pkTerminal
     result.term = t
   else:
@@ -116,7 +116,7 @@ proc term*(t: char): Peg {.nosideEffect, rtl, extern: "npegs$1Char".} =
   assert t != '\0'
   result.kind = pkChar
   result.ch = t
-  
+
 proc charSet*(s: set[char]): Peg {.nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a PEG from a character set `s`
   assert '\0' notin s
@@ -129,12 +129,12 @@ proc add(d: var Peg, s: Peg) {.inline.} = add(d.sons, s)
 
 proc addChoice(dest: var Peg, elem: Peg) =
   var L = dest.len-1
-  if L >= 0 and dest.sons[L].kind == pkCharChoice: 
+  if L >= 0 and dest.sons[L].kind == pkCharChoice:
     # caution! Do not introduce false aliasing here!
     case elem.kind
     of pkCharChoice:
       dest.sons[L] = charSet(dest.sons[L].charChoice[] + elem.charChoice[])
-    of pkChar: 
+    of pkChar:
       dest.sons[L] = charSet(dest.sons[L].charChoice[] + {elem.ch})
     else: add(dest, elem)
   else: add(dest, elem)
@@ -158,12 +158,12 @@ proc `/`*(a: varargs[Peg]): Peg {.
 
 proc addSequence(dest: var Peg, elem: Peg) =
   var L = dest.len-1
-  if L >= 0 and dest.sons[L].kind == pkTerminal: 
+  if L >= 0 and dest.sons[L].kind == pkTerminal:
     # caution! Do not introduce false aliasing here!
     case elem.kind
-    of pkTerminal: 
+    of pkTerminal:
       dest.sons[L] = term(dest.sons[L].term & elem.term)
-    of pkChar: 
+    of pkChar:
       dest.sons[L] = term(dest.sons[L].term & elem.ch)
     else: add(dest, elem)
   else: add(dest, elem)
@@ -172,7 +172,7 @@ proc sequence*(a: varargs[Peg]): Peg {.
   nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a sequence with all the PEGs from `a`
   multipleOp(pkSequence, addSequence)
- 
+
 proc `?`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsOptional".} =
   ## constructs an optional for the PEG `a`
   if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar,
@@ -207,7 +207,7 @@ proc `!*`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsSearch".} =
   result.kind = pkSearch
   result.sons = @[a]
 
-proc `!*\`*(a: Peg): Peg {.noSideEffect, rtl, 
+proc `!*\`*(a: Peg): Peg {.noSideEffect, rtl,
                              extern: "npgegsCapturedSearch".} =
   ## constructs a "captured search" for the PEG `a`
   result.kind = pkCapturedSearch
@@ -216,7 +216,7 @@ proc `!*\`*(a: Peg): Peg {.noSideEffect, rtl,
 proc `+`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsGreedyPosRep".} =
   ## constructs a "greedy positive repetition" with the PEG `a`
   return sequence(a, *a)
-  
+
 proc `&`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsAndPredicate".} =
   ## constructs an "and predicate" with the PEG `a`
   result.kind = pkAndPredicate
@@ -239,33 +239,33 @@ proc newLine*: Peg {.inline.} =
   ## constructs the PEG `newline`:idx: (``\n``)
   result.kind = pkNewLine
 
-proc unicodeLetter*: Peg {.inline.} = 
+proc unicodeLetter*: Peg {.inline.} =
   ## constructs the PEG ``\letter`` which matches any Unicode letter.
   result.kind = pkLetter
-  
-proc unicodeLower*: Peg {.inline.} = 
+
+proc unicodeLower*: Peg {.inline.} =
   ## constructs the PEG ``\lower`` which matches any Unicode lowercase letter.
-  result.kind = pkLower 
+  result.kind = pkLower
 
-proc unicodeUpper*: Peg {.inline.} = 
+proc unicodeUpper*: Peg {.inline.} =
   ## constructs the PEG ``\upper`` which matches any Unicode uppercase letter.
   result.kind = pkUpper
-  
-proc unicodeTitle*: Peg {.inline.} = 
+
+proc unicodeTitle*: Peg {.inline.} =
   ## constructs the PEG ``\title`` which matches any Unicode title letter.
   result.kind = pkTitle
 
-proc unicodeWhitespace*: Peg {.inline.} = 
-  ## constructs the PEG ``\white`` which matches any Unicode 
+proc unicodeWhitespace*: Peg {.inline.} =
+  ## constructs the PEG ``\white`` which matches any Unicode
   ## whitespace character.
   result.kind = pkWhitespace
 
-proc startAnchor*: Peg {.inline.} = 
-  ## constructs the PEG ``^`` which matches the start of the input.  
+proc startAnchor*: Peg {.inline.} =
+  ## constructs the PEG ``^`` which matches the start of the input.
   result.kind = pkStartAnchor
 
-proc endAnchor*: Peg {.inline.} = 
-  ## constructs the PEG ``$`` which matches the end of the input.  
+proc endAnchor*: Peg {.inline.} =
+  ## constructs the PEG ``$`` which matches the end of the input.
   result = !any()
 
 proc capture*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsCapture".} =
@@ -274,21 +274,21 @@ proc capture*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsCapture".} =
   result.sons = @[a]
 
 proc backref*(index: range[1..MaxSubpatterns]): Peg {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
+  nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a back reference of the given `index`. `index` starts counting
   ## from 1.
   result.kind = pkBackRef
   result.index = index-1
 
 proc backrefIgnoreCase*(index: range[1..MaxSubpatterns]): Peg {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
+  nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a back reference of the given `index`. `index` starts counting
   ## from 1. Ignores case for matching.
   result.kind = pkBackRefIgnoreCase
   result.index = index-1
 
 proc backrefIgnoreStyle*(index: range[1..MaxSubpatterns]): Peg {.
-  nosideEffect, rtl, extern: "npegs$1".}= 
+  nosideEffect, rtl, extern: "npegs$1".}=
   ## constructs a back reference of the given `index`. `index` starts counting
   ## from 1. Ignores style for matching.
   result.kind = pkBackRefIgnoreStyle
@@ -298,7 +298,7 @@ proc spaceCost(n: Peg): int =
   case n.kind
   of pkEmpty: discard
   of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar,
-     pkGreedyRepChar, pkCharChoice, pkGreedyRepSet, 
+     pkGreedyRepChar, pkCharChoice, pkGreedyRepSet,
      pkAny..pkWhitespace, pkGreedyAny:
     result = 1
   of pkNonTerminal:
@@ -310,7 +310,7 @@ proc spaceCost(n: Peg): int =
       if result >= InlineThreshold: break
 
 proc nonterminal*(n: NonTerminal): Peg {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
+  nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a PEG that consists of the nonterminal symbol
   assert n != nil
   if ntDeclared in n.flags and spaceCost(n.rule) < InlineThreshold:
@@ -331,7 +331,7 @@ proc newNonTerminal*(name: string, line, column: int): NonTerminal {.
 template letters*: expr =
   ## expands to ``charset({'A'..'Z', 'a'..'z'})``
   charSet({'A'..'Z', 'a'..'z'})
-  
+
 template digits*: expr =
   ## expands to ``charset({'0'..'9'})``
   charSet({'0'..'9'})
@@ -339,11 +339,11 @@ template digits*: expr =
 template whitespace*: expr =
   ## expands to ``charset({' ', '\9'..'\13'})``
   charSet({' ', '\9'..'\13'})
-  
+
 template identChars*: expr =
   ## expands to ``charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})``
   charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'})
-  
+
 template identStartChars*: expr =
   ## expands to ``charset({'A'..'Z', 'a'..'z', '_'})``
   charSet({'a'..'z', 'A'..'Z', '_'})
@@ -352,14 +352,14 @@ template ident*: expr =
   ## same as ``[a-zA-Z_][a-zA-z_0-9]*``; standard identifier
   sequence(charSet({'a'..'z', 'A'..'Z', '_'}),
            *charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'}))
-  
+
 template natural*: expr =
   ## same as ``\d+``
   +digits
 
 # ------------------------- debugging -----------------------------------------
 
-proc esc(c: char, reserved = {'\0'..'\255'}): string = 
+proc esc(c: char, reserved = {'\0'..'\255'}): string =
   case c
   of '\b': result = "\\b"
   of '\t': result = "\\t"
@@ -374,38 +374,38 @@ proc esc(c: char, reserved = {'\0'..'\255'}): string =
   elif c < ' ' or c >= '\128': result = '\\' & $ord(c)
   elif c in reserved: result = '\\' & c
   else: result = $c
-  
+
 proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'"
 
-proc singleQuoteEsc(str: string): string = 
+proc singleQuoteEsc(str: string): string =
   result = "'"
   for c in items(str): add result, esc(c, {'\''})
   add result, '\''
-  
-proc charSetEscAux(cc: set[char]): string = 
+
+proc charSetEscAux(cc: set[char]): string =
   const reserved = {'^', '-', ']'}
   result = ""
   var c1 = 0
-  while c1 <= 0xff: 
-    if chr(c1) in cc: 
+  while c1 <= 0xff:
+    if chr(c1) in cc:
       var c2 = c1
       while c2 < 0xff and chr(succ(c2)) in cc: inc(c2)
-      if c1 == c2: 
+      if c1 == c2:
         add result, esc(chr(c1), reserved)
-      elif c2 == succ(c1): 
+      elif c2 == succ(c1):
         add result, esc(chr(c1), reserved) & esc(chr(c2), reserved)
-      else: 
+      else:
         add result, esc(chr(c1), reserved) & '-' & esc(chr(c2), reserved)
       c1 = c2
     inc(c1)
-  
+
 proc charSetEsc(cc: set[char]): string =
-  if card(cc) >= 128+64: 
+  if card(cc) >= 128+64:
     result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']'
-  else: 
+  else:
     result = '[' & charSetEscAux(cc) & ']'
-  
-proc toStrAux(r: Peg, res: var string) = 
+
+proc toStrAux(r: Peg, res: var string) =
   case r.kind
   of pkEmpty: add(res, "()")
   of pkAny: add(res, '.')
@@ -469,25 +469,25 @@ proc toStrAux(r: Peg, res: var string) =
     toStrAux(r.sons[0], res)
   of pkCapture:
     add(res, '{')
-    toStrAux(r.sons[0], res)    
+    toStrAux(r.sons[0], res)
     add(res, '}')
-  of pkBackRef: 
+  of pkBackRef:
     add(res, '$')
     add(res, $r.index)
-  of pkBackRefIgnoreCase: 
+  of pkBackRefIgnoreCase:
     add(res, "i$")
     add(res, $r.index)
-  of pkBackRefIgnoreStyle: 
+  of pkBackRefIgnoreStyle:
     add(res, "y$")
     add(res, $r.index)
   of pkRule:
-    toStrAux(r.sons[0], res)    
+    toStrAux(r.sons[0], res)
     add(res, " <- ")
     toStrAux(r.sons[1], res)
   of pkList:
     for i in 0 .. high(r.sons):
       toStrAux(r.sons[i], res)
-      add(res, "\n")  
+      add(res, "\n")
   of pkStartAnchor:
     add(res, '^')
 
@@ -506,14 +506,14 @@ type
 
 {.deprecated: [TCaptures: Captures].}
 
-proc bounds*(c: Captures, 
-             i: range[0..MaxSubpatterns-1]): tuple[first, last: int] = 
+proc bounds*(c: Captures,
+             i: range[0..MaxSubpatterns-1]): tuple[first, last: int] =
   ## returns the bounds ``[first..last]`` of the `i`'th capture.
   result = c.matches[i]
 
 when not useUnicode:
   type
-    TRune = char
+    Rune = char
   template fastRuneAt(s, i, ch: expr) =
     ch = s[i]
     inc(i)
@@ -527,7 +527,7 @@ when not useUnicode:
 
 proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
                nosideEffect, rtl, extern: "npegs$1".} =
-  ## low-level matching proc that implements the PEG interpreter. Use this 
+  ## low-level matching proc that implements the PEG interpreter. Use this
   ## for maximum efficiency (every other PEG operation ends up calling this
   ## proc).
   ## Returns -1 if it does not match, else the length of the match
@@ -541,7 +541,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       result = runeLenAt(s, start)
     else:
       result = -1
-  of pkLetter: 
+  of pkLetter:
     if s[start] != '\0':
       var a: Rune
       result = start
@@ -550,7 +550,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       else: result = -1
     else:
       result = -1
-  of pkLower: 
+  of pkLower:
     if s[start] != '\0':
       var a: Rune
       result = start
@@ -559,7 +559,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       else: result = -1
     else:
       result = -1
-  of pkUpper: 
+  of pkUpper:
     if s[start] != '\0':
       var a: Rune
       result = start
@@ -568,16 +568,16 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       else: result = -1
     else:
       result = -1
-  of pkTitle: 
+  of pkTitle:
     if s[start] != '\0':
       var a: Rune
       result = start
       fastRuneAt(s, result, a)
-      if isTitle(a): dec(result, start) 
+      if isTitle(a): dec(result, start)
       else: result = -1
     else:
       result = -1
-  of pkWhitespace: 
+  of pkWhitespace:
     if s[start] != '\0':
       var a: Rune
       result = start
@@ -641,7 +641,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
     when false: echo "leave: ", p.nt.name
     if result < 0: c.ml = oldMl
   of pkSequence:
-    var oldMl = c.ml  
+    var oldMl = c.ml
     result = 0
     for i in 0..high(p.sons):
       var x = rawMatch(s, p.sons[i], start+result, c)
@@ -723,11 +723,11 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       #else: silently ignore the capture
     else:
       c.ml = idx
-  of pkBackRef..pkBackRefIgnoreStyle: 
+  of pkBackRef..pkBackRefIgnoreStyle:
     if p.index >= c.ml: return -1
     var (a, b) = c.matches[p.index]
     var n: Peg
-    n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef)) 
+    n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef))
     n.term = s.substr(a, b)
     result = rawMatch(s, n, start, c)
   of pkStartAnchor:
@@ -744,24 +744,6 @@ template fillMatches(s, caps, c: expr) =
     else:
       caps[k] = nil
 
-proc match*(s: string, pattern: Peg, matches: var openArray[string],
-            start = 0): bool {.nosideEffect, rtl, extern: "npegs$1Capture".} =
-  ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and
-  ## the captured substrings in the array ``matches``. If it does not
-  ## match, nothing is written into ``matches`` and ``false`` is
-  ## returned.
-  var c: Captures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c) == len(s) - start
-  if result: fillMatches(s, matches, c)
-
-proc match*(s: string, pattern: Peg, 
-            start = 0): bool {.nosideEffect, rtl, extern: "npegs$1".} =
-  ## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``.
-  var c: Captures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c) == len(s)-start
-
 proc matchLen*(s: string, pattern: Peg, matches: var openArray[string],
                start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} =
   ## the same as ``match``, but it returns the length of the match,
@@ -773,7 +755,7 @@ proc matchLen*(s: string, pattern: Peg, matches: var openArray[string],
   result = rawMatch(s, pattern, start, c)
   if result >= 0: fillMatches(s, matches, c)
 
-proc matchLen*(s: string, pattern: Peg, 
+proc matchLen*(s: string, pattern: Peg,
                start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} =
   ## the same as ``match``, but it returns the length of the match,
   ## if there is no match, -1 is returned. Note that a match length
@@ -783,6 +765,20 @@ proc matchLen*(s: string, pattern: Peg,
   c.origStart = start
   result = rawMatch(s, pattern, start, c)
 
+proc match*(s: string, pattern: Peg, matches: var openArray[string],
+            start = 0): bool {.nosideEffect, rtl, extern: "npegs$1Capture".} =
+  ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and
+  ## the captured substrings in the array ``matches``. If it does not
+  ## match, nothing is written into ``matches`` and ``false`` is
+  ## returned.
+  result = matchLen(s, pattern, matches, start) != -1
+
+proc match*(s: string, pattern: Peg,
+            start = 0): bool {.nosideEffect, rtl, extern: "npegs$1".} =
+  ## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``.
+  result = matchLen(s, pattern, start) != -1
+
+
 proc find*(s: string, pattern: Peg, matches: var openArray[string],
            start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} =
   ## returns the starting position of ``pattern`` in ``s`` and the captured
@@ -797,11 +793,11 @@ proc find*(s: string, pattern: Peg, matches: var openArray[string],
       return i
   return -1
   # could also use the pattern here: (!P .)* P
-  
+
 proc findBounds*(s: string, pattern: Peg, matches: var openArray[string],
                  start = 0): tuple[first, last: int] {.
                  nosideEffect, rtl, extern: "npegs$1Capture".} =
-  ## returns the starting position and end position of ``pattern`` in ``s`` 
+  ## returns the starting position and end position of ``pattern`` in ``s``
   ## and the captured
   ## substrings in the array ``matches``. If it does not match, nothing
   ## is written into ``matches`` and (-1,0) is returned.
@@ -814,8 +810,8 @@ proc findBounds*(s: string, pattern: Peg, matches: var openArray[string],
       fillMatches(s, matches, c)
       return (i, i+L-1)
   return (-1, 0)
-  
-proc find*(s: string, pattern: Peg, 
+
+proc find*(s: string, pattern: Peg,
            start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} =
   ## returns the starting position of ``pattern`` in ``s``. If it does not
   ## match, -1 is returned.
@@ -824,8 +820,8 @@ proc find*(s: string, pattern: Peg,
   for i in start .. s.len-1:
     if rawMatch(s, pattern, i, c) >= 0: return i
   return -1
-  
-iterator findAll*(s: string, pattern: Peg, start = 0): string = 
+
+iterator findAll*(s: string, pattern: Peg, start = 0): string =
   ## yields all matching *substrings* of `s` that match `pattern`.
   var c: Captures
   c.origStart = start
@@ -838,23 +834,23 @@ iterator findAll*(s: string, pattern: Peg, start = 0): string =
     else:
       yield substr(s, i, i+L-1)
       inc(i, L)
-    
+
 proc findAll*(s: string, pattern: Peg, start = 0): seq[string] {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
+  nosideEffect, rtl, extern: "npegs$1".} =
   ## returns all matching *substrings* of `s` that match `pattern`.
   ## If it does not match, @[] is returned.
   accumulateResult(findAll(s, pattern, start))
 
 when not defined(nimhygiene):
   {.pragma: inject.}
-  
+
 template `=~`*(s: string, pattern: Peg): bool =
-  ## This calls ``match`` with an implicit declared ``matches`` array that 
-  ## can be used in the scope of the ``=~`` call: 
-  ## 
+  ## This calls ``match`` with an implicit declared ``matches`` array that
+  ## can be used in the scope of the ``=~`` call:
+  ##
   ## .. code-block:: nim
   ##
-  ##   if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}": 
+  ##   if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}":
   ##     # matches a key=value pair:
   ##     echo("Key: ", matches[0])
   ##     echo("Value: ", matches[1])
@@ -865,7 +861,7 @@ template `=~`*(s: string, pattern: Peg): bool =
   ##     echo("comment: ", matches[0])
   ##   else:
   ##     echo("syntax error")
-  ##  
+  ##
   bind MaxSubpatterns
   when not declaredInScope(matches):
     var matches {.inject.}: array[0..MaxSubpatterns-1, string]
@@ -902,7 +898,7 @@ proc replacef*(s: string, sub: Peg, by: string): string {.
   ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
   ##
   ## .. code-block:: nim
-  ##   "var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2")
+  ##   "var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2")
   ##
   ## Results in:
   ##
@@ -941,10 +937,10 @@ proc replace*(s: string, sub: Peg, by = ""): string {.
       add(result, by)
       inc(i, x)
   add(result, substr(s, i))
-  
+
 proc parallelReplace*(s: string, subs: varargs[
                       tuple[pattern: Peg, repl: string]]): string {.
-                      nosideEffect, rtl, extern: "npegs$1".} = 
+                      nosideEffect, rtl, extern: "npegs$1".} =
   ## Returns a modified copy of `s` with the substitutions in `subs`
   ## applied in parallel.
   result = ""
@@ -964,8 +960,8 @@ proc parallelReplace*(s: string, subs: varargs[
       add(result, s[i])
       inc(i)
   # copy the rest:
-  add(result, substr(s, i))  
-  
+  add(result, substr(s, i))
+
 proc transformFile*(infile, outfile: string,
                     subs: varargs[tuple[pattern: Peg, repl: string]]) {.
                     rtl, extern: "npegs$1".} =
@@ -974,7 +970,7 @@ proc transformFile*(infile, outfile: string,
   ## error occurs. This is supposed to be used for quick scripting.
   var x = readFile(infile).string
   writeFile(outfile, x.parallelReplace(subs))
-  
+
 iterator split*(s: string, sep: Peg): string =
   ## Splits the string `s` into substrings.
   ##
@@ -1049,14 +1045,14 @@ type
     tkBackref,          ## '$'
     tkDollar,           ## '$'
     tkHat               ## '^'
-  
+
   TToken {.final.} = object  ## a token
     kind: TTokKind           ## the type of the token
     modifier: TModifier
     literal: string          ## the parsed (string) literal
     charset: set[char]       ## if kind == tkCharSet
     index: int               ## if kind == tkBackref
-  
+
   PegLexer {.inheritable.} = object          ## the lexer object.
     bufpos: int               ## the current position within the buffer
     buf: cstring              ## the buffer itself
@@ -1086,7 +1082,7 @@ proc handleLF(L: var PegLexer, pos: int): int =
   result = pos+1
   L.lineStart = result
 
-proc init(L: var PegLexer, input, filename: string, line = 1, col = 0) = 
+proc init(L: var PegLexer, input, filename: string, line = 1, col = 0) =
   L.buf = input
   L.bufpos = 0
   L.lineNumber = line
@@ -1094,69 +1090,69 @@ proc init(L: var PegLexer, input, filename: string, line = 1, col = 0) =
   L.lineStart = 0
   L.filename = filename
 
-proc getColumn(L: PegLexer): int {.inline.} = 
+proc getColumn(L: PegLexer): int {.inline.} =
   result = abs(L.bufpos - L.lineStart) + L.colOffset
 
-proc getLine(L: PegLexer): int {.inline.} = 
+proc getLine(L: PegLexer): int {.inline.} =
   result = L.lineNumber
-  
+
 proc errorStr(L: PegLexer, msg: string, line = -1, col = -1): string =
   var line = if line < 0: getLine(L) else: line
   var col = if col < 0: getColumn(L) else: col
   result = "$1($2, $3) Error: $4" % [L.filename, $line, $col, msg]
 
-proc handleHexChar(c: var PegLexer, xi: var int) = 
+proc handleHexChar(c: var PegLexer, xi: var int) =
   case c.buf[c.bufpos]
-  of '0'..'9': 
+  of '0'..'9':
     xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0'))
     inc(c.bufpos)
-  of 'a'..'f': 
+  of 'a'..'f':
     xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10)
     inc(c.bufpos)
-  of 'A'..'F': 
+  of 'A'..'F':
     xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
     inc(c.bufpos)
   else: discard
 
-proc getEscapedChar(c: var PegLexer, tok: var TToken) = 
+proc getEscapedChar(c: var PegLexer, tok: var TToken) =
   inc(c.bufpos)
   case c.buf[c.bufpos]
-  of 'r', 'R', 'c', 'C': 
+  of 'r', 'R', 'c', 'C':
     add(tok.literal, '\c')
     inc(c.bufpos)
-  of 'l', 'L': 
+  of 'l', 'L':
     add(tok.literal, '\L')
     inc(c.bufpos)
-  of 'f', 'F': 
+  of 'f', 'F':
     add(tok.literal, '\f')
     inc(c.bufpos)
-  of 'e', 'E': 
+  of 'e', 'E':
     add(tok.literal, '\e')
     inc(c.bufpos)
-  of 'a', 'A': 
+  of 'a', 'A':
     add(tok.literal, '\a')
     inc(c.bufpos)
-  of 'b', 'B': 
+  of 'b', 'B':
     add(tok.literal, '\b')
     inc(c.bufpos)
-  of 'v', 'V': 
+  of 'v', 'V':
     add(tok.literal, '\v')
     inc(c.bufpos)
-  of 't', 'T': 
+  of 't', 'T':
     add(tok.literal, '\t')
     inc(c.bufpos)
-  of 'x', 'X': 
+  of 'x', 'X':
     inc(c.bufpos)
     var xi = 0
     handleHexChar(c, xi)
     handleHexChar(c, xi)
     if xi == 0: tok.kind = tkInvalid
     else: add(tok.literal, chr(xi))
-  of '0'..'9': 
+  of '0'..'9':
     var val = ord(c.buf[c.bufpos]) - ord('0')
     inc(c.bufpos)
     var i = 1
-    while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}): 
+    while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}):
       val = val * 10 + ord(c.buf[c.bufpos]) - ord('0')
       inc(c.bufpos)
       inc(i)
@@ -1169,32 +1165,32 @@ proc getEscapedChar(c: var PegLexer, tok: var TToken) =
   else:
     add(tok.literal, c.buf[c.bufpos])
     inc(c.bufpos)
-  
-proc skip(c: var PegLexer) = 
+
+proc skip(c: var PegLexer) =
   var pos = c.bufpos
   var buf = c.buf
-  while true: 
+  while true:
     case buf[pos]
-    of ' ', '\t': 
+    of ' ', '\t':
       inc(pos)
     of '#':
       while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
     of '\c':
       pos = handleCR(c, pos)
       buf = c.buf
-    of '\L': 
+    of '\L':
       pos = handleLF(c, pos)
       buf = c.buf
-    else: 
+    else:
       break                   # EndOfFile also leaves the loop
   c.bufpos = pos
-  
-proc getString(c: var PegLexer, tok: var TToken) = 
+
+proc getString(c: var PegLexer, tok: var TToken) =
   tok.kind = tkStringLit
   var pos = c.bufpos + 1
   var buf = c.buf
   var quote = buf[pos-1]
-  while true: 
+  while true:
     case buf[pos]
     of '\\':
       c.bufpos = pos
@@ -1205,13 +1201,13 @@ proc getString(c: var PegLexer, tok: var TToken) =
       break
     elif buf[pos] == quote:
       inc(pos)
-      break      
+      break
     else:
       add(tok.literal, buf[pos])
       inc(pos)
   c.bufpos = pos
-  
-proc getDollar(c: var PegLexer, tok: var TToken) = 
+
+proc getDollar(c: var PegLexer, tok: var TToken) =
   var pos = c.bufpos + 1
   var buf = c.buf
   if buf[pos] in {'0'..'9'}:
@@ -1223,8 +1219,8 @@ proc getDollar(c: var PegLexer, tok: var TToken) =
   else:
     tok.kind = tkDollar
   c.bufpos = pos
-  
-proc getCharSet(c: var PegLexer, tok: var TToken) = 
+
+proc getCharSet(c: var PegLexer, tok: var TToken) =
   tok.kind = tkCharSet
   tok.charset = {}
   var pos = c.bufpos + 1
@@ -1247,7 +1243,7 @@ proc getCharSet(c: var PegLexer, tok: var TToken) =
     of '\C', '\L', '\0':
       tok.kind = tkInvalid
       break
-    else: 
+    else:
       ch = buf[pos]
       inc(pos)
     incl(tok.charset, ch)
@@ -1267,18 +1263,18 @@ proc getCharSet(c: var PegLexer, tok: var TToken) =
         of '\C', '\L', '\0':
           tok.kind = tkInvalid
           break
-        else: 
+        else:
           ch2 = buf[pos]
           inc(pos)
         for i in ord(ch)+1 .. ord(ch2):
           incl(tok.charset, chr(i))
   c.bufpos = pos
   if caret: tok.charset = {'\1'..'\xFF'} - tok.charset
-  
-proc getSymbol(c: var PegLexer, tok: var TToken) = 
+
+proc getSymbol(c: var PegLexer, tok: var TToken) =
   var pos = c.bufpos
   var buf = c.buf
-  while true: 
+  while true:
     add(tok.literal, buf[pos])
     inc(pos)
     if buf[pos] notin strutils.IdentChars: break
@@ -1294,7 +1290,7 @@ proc getBuiltin(c: var PegLexer, tok: var TToken) =
     tok.kind = tkEscaped
     getEscapedChar(c, tok) # may set tok.kind to tkInvalid
 
-proc getTok(c: var PegLexer, tok: var TToken) = 
+proc getTok(c: var PegLexer, tok: var TToken) =
   tok.kind = tkInvalid
   tok.modifier = modNone
   setLen(tok.literal, 0)
@@ -1309,11 +1305,11 @@ proc getTok(c: var PegLexer, tok: var TToken) =
     else:
       tok.kind = tkCurlyLe
       add(tok.literal, '{')
-  of '}': 
+  of '}':
     tok.kind = tkCurlyRi
     inc(c.bufpos)
     add(tok.literal, '}')
-  of '[': 
+  of '[':
     getCharSet(c, tok)
   of '(':
     tok.kind = tkParLe
@@ -1323,7 +1319,7 @@ proc getTok(c: var PegLexer, tok: var TToken) =
     tok.kind = tkParRi
     inc(c.bufpos)
     add(tok.literal, ')')
-  of '.': 
+  of '.':
     tok.kind = tkAny
     inc(c.bufpos)
     add(tok.literal, '.')
@@ -1331,16 +1327,16 @@ proc getTok(c: var PegLexer, tok: var TToken) =
     tok.kind = tkAnyRune
     inc(c.bufpos)
     add(tok.literal, '_')
-  of '\\': 
+  of '\\':
     getBuiltin(c, tok)
   of '\'', '"': getString(c, tok)
   of '$': getDollar(c, tok)
-  of '\0': 
+  of '\0':
     tok.kind = tkEof
     tok.literal = "[EOF]"
   of 'a'..'z', 'A'..'Z', '\128'..'\255':
     getSymbol(c, tok)
-    if c.buf[c.bufpos] in {'\'', '"'} or 
+    if c.buf[c.bufpos] in {'\'', '"'} or
         c.buf[c.bufpos] == '$' and c.buf[c.bufpos+1] in {'0'..'9'}:
       case tok.literal
       of "i": tok.modifier = modIgnoreCase
@@ -1388,7 +1384,7 @@ proc getTok(c: var PegLexer, tok: var TToken) =
     tok.kind = tkAt
     inc(c.bufpos)
     add(tok.literal, '@')
-    if c.buf[c.bufpos] == '@': 
+    if c.buf[c.bufpos] == '@':
       tok.kind = tkCurlyAt
       inc(c.bufpos)
       add(tok.literal, '@')
@@ -1407,7 +1403,7 @@ proc arrowIsNextTok(c: PegLexer): bool =
   result = c.buf[pos] == '<' and c.buf[pos+1] == '-'
 
 # ----------------------------- parser ----------------------------------------
-    
+
 type
   EInvalidPeg* = object of ValueError ## raised if an invalid
                                          ## PEG has been detected
@@ -1425,7 +1421,7 @@ proc pegError(p: PegParser, msg: string, line = -1, col = -1) =
   e.msg = errorStr(p, msg, line, col)
   raise e
 
-proc getTok(p: var PegParser) = 
+proc getTok(p: var PegParser) =
   getTok(p, p.tok)
   if p.tok.kind == tkInvalid: pegError(p, "invalid token")
 
@@ -1475,7 +1471,7 @@ proc builtin(p: var PegParser): Peg =
   of "white": result = unicodeWhitespace()
   else: pegError(p, "unknown built-in: " & p.tok.literal)
 
-proc token(terminal: Peg, p: PegParser): Peg = 
+proc token(terminal: Peg, p: PegParser): Peg =
   if p.skip.kind == pkEmpty: result = terminal
   else: result = sequence(p.skip, terminal)
 
@@ -1496,7 +1492,7 @@ proc primary(p: var PegParser): Peg =
   else: discard
   case p.tok.kind
   of tkIdentifier:
-    if p.identIsVerbatim: 
+    if p.identIsVerbatim:
       var m = p.tok.modifier
       if m == modNone: m = p.modifier
       result = modifiedTerm(p.tok.literal, m).token(p)
@@ -1539,17 +1535,17 @@ proc primary(p: var PegParser): Peg =
   of tkEscaped:
     result = term(p.tok.literal[0]).token(p)
     getTok(p)
-  of tkDollar: 
+  of tkDollar:
     result = endAnchor()
     getTok(p)
-  of tkHat: 
+  of tkHat:
     result = startAnchor()
     getTok(p)
   of tkBackref:
     var m = p.tok.modifier
     if m == modNone: m = p.modifier
     result = modifiedBackref(p.tok.index, m).token(p)
-    if p.tok.index < 0 or p.tok.index > p.captures: 
+    if p.tok.index < 0 or p.tok.index > p.captures:
       pegError(p, "invalid back reference index: " & $p.tok.index)
     getTok(p)
   else:
@@ -1573,7 +1569,7 @@ proc seqExpr(p: var PegParser): Peg =
   while true:
     case p.tok.kind
     of tkAmp, tkNot, tkAt, tkStringLit, tkCharSet, tkParLe, tkCurlyLe,
-       tkAny, tkAnyRune, tkBuiltin, tkEscaped, tkDollar, tkBackref, 
+       tkAny, tkAnyRune, tkBuiltin, tkEscaped, tkDollar, tkBackref,
        tkHat, tkCurlyAt:
       result = sequence(result, primary(p))
     of tkIdentifier:
@@ -1587,7 +1583,7 @@ proc parseExpr(p: var PegParser): Peg =
   while p.tok.kind == tkBar:
     getTok(p)
     result = result / seqExpr(p)
-  
+
 proc parseRule(p: var PegParser): NonTerminal =
   if p.tok.kind == tkIdentifier and arrowIsNextTok(p):
     result = getNonTerminal(p, p.tok.literal)
@@ -1601,7 +1597,7 @@ proc parseRule(p: var PegParser): NonTerminal =
     incl(result.flags, ntDeclared) # NOW inlining may be attempted
   else:
     pegError(p, "rule expected, but found: " & p.tok.literal)
-  
+
 proc rawParse(p: var PegParser): Peg =
   ## parses a rule or a PEG expression
   while p.tok.kind == tkBuiltin:
@@ -1680,27 +1676,29 @@ when isMainModule:
   assert(not match("W_HI_L", peg"\y 'while'"))
   assert(not match("W_HI_Le", peg"\y v'while'"))
   assert match("W_HI_Le", peg"y'while'")
-  
+
   assert($ +digits == $peg"\d+")
   assert "0158787".match(peg"\d+")
   assert "ABC 0232".match(peg"\w+\s+\d+")
   assert "ABC".match(peg"\d+ / \w+")
 
+  var accum: seq[string] = @[]
   for word in split("00232this02939is39an22example111", peg"\d+"):
-    writeln(stdout, word)
+    accum.add(word)
+  assert(accum == @["this", "is", "an", "example"])
 
   assert matchLen("key", ident) == 3
 
   var pattern = sequence(ident, *whitespace, term('='), *whitespace, ident)
   assert matchLen("key1=  cal9", pattern) == 11
-  
+
   var ws = newNonTerminal("ws", 1, 1)
   ws.rule = *whitespace
-  
+
   var expr = newNonTerminal("expr", 1, 1)
   expr.rule = sequence(capture(ident), *sequence(
                 nonterminal(ws), term('+'), nonterminal(ws), nonterminal(expr)))
-  
+
   var c: Captures
   var s = "a+b +  c +d+e+f"
   assert rawMatch(s, expr.rule, 0, c) == len(s)
@@ -1722,7 +1720,7 @@ when isMainModule:
     assert matches[0] == "abc"
   else:
     assert false
-  
+
   var g2 = peg"""S <- A B / C D
                  A <- 'a'+
                  B <- 'b'+
@@ -1748,18 +1746,20 @@ when isMainModule:
   else:
     assert false
 
+  accum = @[]
   for x in findAll("abcdef", peg".", 3):
-    echo x
+    accum.add(x)
+  assert(accum == @["d", "e", "f"])
 
   for x in findAll("abcdef", peg"^{.}", 3):
     assert x == "d"
-    
+
   if "f(a, b)" =~ peg"{[0-9]+} / ({\ident} '(' {@} ')')":
     assert matches[0] == "f"
     assert matches[1] == "a, b"
   else:
     assert false
-  
+
   assert match("eine übersicht und außerdem", peg"(\letter \white*)+")
   # ß is not a lower cased letter?!
   assert match("eine übersicht und auerdem", peg"(\lower \white*)+")
@@ -1783,3 +1783,9 @@ when isMainModule:
   if "foo" =~ peg"{'foo'}":
     assert matches[0] == "foo"
   else: assert false
+
+  let empty_test = peg"^\d*"
+  let str = "XYZ"
+
+  assert(str.find(empty_test) == 0)
+  assert(str.match(empty_test))
diff --git a/lib/pure/pegs.nimfix b/lib/pure/pegs.nimfix
deleted file mode 100644
index 8dd172a48..000000000
--- a/lib/pure/pegs.nimfix
+++ /dev/null
@@ -1,1770 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## Simple PEG (Parsing expression grammar) matching. Uses no memorization, but
-## uses superoperators and symbol inlining to improve performance. Note:
-## Matching performance is hopefully competitive with optimized regular
-## expression engines.
-##
-## .. include:: ../doc/pegdocs.txt
-##
-
-include "system/inclrtl"
-
-const
-  useUnicode = true ## change this to deactivate proper UTF-8 support
-
-import
-  strutils
-
-when useUnicode:
-  import unicode
-
-const
-  InlineThreshold = 5  ## number of leaves; -1 to disable inlining
-  MaxSubpatterns* = 10 ## defines the maximum number of subpatterns that
-                       ## can be captured. More subpatterns cannot be captured! 
-
-type
-  PegKind = enum
-    pkEmpty,
-    pkAny,              ## any character (.)
-    pkAnyRune,          ## any Unicode character (_)
-    pkNewLine,          ## CR-LF, LF, CR
-    pkLetter,           ## Unicode letter
-    pkLower,            ## Unicode lower case letter
-    pkUpper,            ## Unicode upper case letter
-    pkTitle,            ## Unicode title character
-    pkWhitespace,       ## Unicode whitespace character
-    pkTerminal,
-    pkTerminalIgnoreCase,
-    pkTerminalIgnoreStyle,
-    pkChar,             ## single character to match
-    pkCharChoice,
-    pkNonTerminal,
-    pkSequence,         ## a b c ... --> Internal DSL: peg(a, b, c)
-    pkOrderedChoice,    ## a / b / ... --> Internal DSL: a / b or /[a, b, c]
-    pkGreedyRep,        ## a*     --> Internal DSL: *a
-                        ## a+     --> (a a*)
-    pkGreedyRepChar,    ## x* where x is a single character (superop)
-    pkGreedyRepSet,     ## [set]* (superop)
-    pkGreedyAny,        ## .* or _* (superop)
-    pkOption,           ## a?     --> Internal DSL: ?a
-    pkAndPredicate,     ## &a     --> Internal DSL: &a
-    pkNotPredicate,     ## !a     --> Internal DSL: !a
-    pkCapture,          ## {a}    --> Internal DSL: capture(a)
-    pkBackRef,          ## $i     --> Internal DSL: backref(i)
-    pkBackRefIgnoreCase,
-    pkBackRefIgnoreStyle,
-    pkSearch,           ## @a     --> Internal DSL: !*a
-    pkCapturedSearch,   ## {@} a  --> Internal DSL: !*\a
-    pkRule,             ## a <- b
-    pkList,             ## a, b
-    pkStartAnchor       ## ^      --> Internal DSL: startAnchor()
-  NonTerminalFlag = enum
-    ntDeclared, ntUsed
-  NonTerminalObj = object         ## represents a non terminal symbol
-    name: string                  ## the name of the symbol
-    line: int                     ## line the symbol has been declared/used in
-    col: int                      ## column the symbol has been declared/used in
-    flags: set[NonTerminalFlag]   ## the nonterminal's flags
-    rule: TNode                   ## the rule that the symbol refers to
-  TNode {.shallow.} = object
-    case kind: PegKind
-    of pkEmpty..pkWhitespace: nil
-    of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string
-    of pkChar, pkGreedyRepChar: ch: char
-    of pkCharChoice, pkGreedyRepSet: charChoice: ref set[char]
-    of pkNonTerminal: nt: PNonTerminal
-    of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns]
-    else: sons: seq[TNode]
-  PNonTerminal* = ref NonTerminalObj
-  TPeg* = TNode
-
-block:
-  type
-    Peg = TNode
-    NonTerminal = PNonTerminal
-  {.deprecated: [TPeg: Peg, PNonTerminal: NonTerminal].}
-
-proc term*(t: string): TPeg {.nosideEffect, rtl, extern: "npegs$1Str".} =
-  ## constructs a PEG from a terminal string
-  if t.len != 1:
-    result.kind = pkTerminal
-    result.term = t
-  else:
-    result.kind = pkChar
-    result.ch = t[0]
-
-proc termIgnoreCase*(t: string): TPeg {.nosideEffect, rtl, extern: "npegs$1".} =
-  ## constructs a PEG from a terminal string; ignore case for matching
-  result.kind = pkTerminalIgnoreCase
-  result.term = t
-
-proc termIgnoreStyle*(t: string): TPeg {.nosideEffect, rtl, extern: "npegs$1".} =
-  ## constructs a PEG from a terminal string; ignore style for matching
-  result.kind = pkTerminalIgnoreStyle
-  result.term = t
-
-proc term*(t: char): TPeg {.nosideEffect, rtl, extern: "npegs$1Char".} =
-  ## constructs a PEG from a terminal char
-  assert t != '\0'
-  result.kind = pkChar
-  result.ch = t
-  
-proc charSet*(s: set[char]): TPeg {.nosideEffect, rtl, extern: "npegs$1".} =
-  ## constructs a PEG from a character set `s`
-  assert '\0' notin s
-  result.kind = pkCharChoice
-  new(result.charChoice)
-  result.charChoice[] = s
-
-proc len(a: TPeg): int {.inline.} = return a.sons.len
-proc add(d: var TPeg, s: TPeg) {.inline.} = add(d.sons, s)
-
-proc addChoice(dest: var TPeg, elem: TPeg) =
-  var L = dest.len-1
-  if L >= 0 and dest.sons[L].kind == pkCharChoice: 
-    # caution! Do not introduce false aliasing here!
-    case elem.kind
-    of pkCharChoice:
-      dest.sons[L] = charSet(dest.sons[L].charChoice[] + elem.charChoice[])
-    of pkChar: 
-      dest.sons[L] = charSet(dest.sons[L].charChoice[] + {elem.ch})
-    else: add(dest, elem)
-  else: add(dest, elem)
-
-template multipleOp(k: PegKind, localOpt: expr) =
-  result.kind = k
-  result.sons = @[]
-  for x in items(a):
-    if x.kind == k:
-      for y in items(x.sons):
-        localOpt(result, y)
-    else:
-      localOpt(result, x)
-  if result.len == 1:
-    result = result.sons[0]
-
-proc `/`*(a: varargs[TPeg]): TPeg {.
-  nosideEffect, rtl, extern: "npegsOrderedChoice".} =
-  ## constructs an ordered choice with the PEGs in `a`
-  multipleOp(pkOrderedChoice, addChoice)
-
-proc addSequence(dest: var TPeg, elem: TPeg) =
-  var L = dest.len-1
-  if L >= 0 and dest.sons[L].kind == pkTerminal: 
-    # caution! Do not introduce false aliasing here!
-    case elem.kind
-    of pkTerminal: 
-      dest.sons[L] = term(dest.sons[L].term & elem.term)
-    of pkChar: 
-      dest.sons[L] = term(dest.sons[L].term & elem.ch)
-    else: add(dest, elem)
-  else: add(dest, elem)
-
-proc sequence*(a: varargs[TPeg]): TPeg {.
-  nosideEffect, rtl, extern: "npegs$1".} =
-  ## constructs a sequence with all the PEGs from `a`
-  multipleOp(pkSequence, addSequence)
- 
-proc `?`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsOptional".} =
-  ## constructs an optional for the PEG `a`
-  if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar,
-                pkGreedyRepSet}:
-    # a* ?  --> a*
-    # a? ?  --> a?
-    result = a
-  else:
-    result.kind = pkOption
-    result.sons = @[a]
-
-proc `*`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsGreedyRep".} =
-  ## constructs a "greedy repetition" for the PEG `a`
-  case a.kind
-  of pkGreedyRep, pkGreedyRepChar, pkGreedyRepSet, pkGreedyAny, pkOption:
-    assert false
-    # produces endless loop!
-  of pkChar:
-    result.kind = pkGreedyRepChar
-    result.ch = a.ch
-  of pkCharChoice:
-    result.kind = pkGreedyRepSet
-    result.charChoice = a.charChoice # copying a reference suffices!
-  of pkAny, pkAnyRune:
-    result.kind = pkGreedyAny
-  else:
-    result.kind = pkGreedyRep
-    result.sons = @[a]
-
-proc `!*`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsSearch".} =
-  ## constructs a "search" for the PEG `a`
-  result.kind = pkSearch
-  result.sons = @[a]
-
-proc `!*\`*(a: TPeg): TPeg {.noSideEffect, rtl, 
-                             extern: "npgegsCapturedSearch".} =
-  ## constructs a "captured search" for the PEG `a`
-  result.kind = pkCapturedSearch
-  result.sons = @[a]
-
-proc `+`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsGreedyPosRep".} =
-  ## constructs a "greedy positive repetition" with the PEG `a`
-  return sequence(a, *a)
-  
-proc `&`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsAndPredicate".} =
-  ## constructs an "and predicate" with the PEG `a`
-  result.kind = pkAndPredicate
-  result.sons = @[a]
-
-proc `!`*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsNotPredicate".} =
-  ## constructs a "not predicate" with the PEG `a`
-  result.kind = pkNotPredicate
-  result.sons = @[a]
-
-proc any*: TPeg {.inline.} =
-  ## constructs the PEG `any character`:idx: (``.``)
-  result.kind = pkAny
-
-proc anyRune*: TPeg {.inline.} =
-  ## constructs the PEG `any rune`:idx: (``_``)
-  result.kind = pkAnyRune
-
-proc newLine*: TPeg {.inline.} =
-  ## constructs the PEG `newline`:idx: (``\n``)
-  result.kind = pkNewLine
-
-proc unicodeLetter*: TPeg {.inline.} = 
-  ## constructs the PEG ``\letter`` which matches any Unicode letter.
-  result.kind = pkLetter
-  
-proc unicodeLower*: TPeg {.inline.} = 
-  ## constructs the PEG ``\lower`` which matches any Unicode lowercase letter.
-  result.kind = pkLower 
-
-proc unicodeUpper*: TPeg {.inline.} = 
-  ## constructs the PEG ``\upper`` which matches any Unicode uppercase letter.
-  result.kind = pkUpper
-  
-proc unicodeTitle*: TPeg {.inline.} = 
-  ## constructs the PEG ``\title`` which matches any Unicode title letter.
-  result.kind = pkTitle
-
-proc unicodeWhitespace*: TPeg {.inline.} = 
-  ## constructs the PEG ``\white`` which matches any Unicode 
-  ## whitespace character.
-  result.kind = pkWhitespace
-
-proc startAnchor*: TPeg {.inline.} = 
-  ## constructs the PEG ``^`` which matches the start of the input.  
-  result.kind = pkStartAnchor
-
-proc endAnchor*: TPeg {.inline.} = 
-  ## constructs the PEG ``$`` which matches the end of the input.  
-  result = !any()
-
-proc capture*(a: TPeg): TPeg {.nosideEffect, rtl, extern: "npegsCapture".} =
-  ## constructs a capture with the PEG `a`
-  result.kind = pkCapture
-  result.sons = @[a]
-
-proc backref*(index: range[1..MaxSubpatterns]): TPeg {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
-  ## constructs a back reference of the given `index`. `index` starts counting
-  ## from 1.
-  result.kind = pkBackRef
-  result.index = index-1
-
-proc backrefIgnoreCase*(index: range[1..MaxSubpatterns]): TPeg {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
-  ## constructs a back reference of the given `index`. `index` starts counting
-  ## from 1. Ignores case for matching.
-  result.kind = pkBackRefIgnoreCase
-  result.index = index-1
-
-proc backrefIgnoreStyle*(index: range[1..MaxSubpatterns]): TPeg {.
-  nosideEffect, rtl, extern: "npegs$1".}= 
-  ## constructs a back reference of the given `index`. `index` starts counting
-  ## from 1. Ignores style for matching.
-  result.kind = pkBackRefIgnoreStyle
-  result.index = index-1
-
-proc spaceCost(n: TPeg): int =
-  case n.kind
-  of pkEmpty: discard
-  of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar,
-     pkGreedyRepChar, pkCharChoice, pkGreedyRepSet, 
-     pkAny..pkWhitespace, pkGreedyAny:
-    result = 1
-  of pkNonTerminal:
-    # we cannot inline a rule with a non-terminal
-    result = InlineThreshold+1
-  else:
-    for i in 0..n.len-1:
-      inc(result, spaceCost(n.sons[i]))
-      if result >= InlineThreshold: break
-
-proc nonterminal*(n: PNonTerminal): TPeg {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
-  ## constructs a PEG that consists of the nonterminal symbol
-  assert n != nil
-  if ntDeclared in n.flags and spaceCost(n.rule) < InlineThreshold:
-    when false: echo "inlining symbol: ", n.name
-    result = n.rule # inlining of rule enables better optimizations
-  else:
-    result.kind = pkNonTerminal
-    result.nt = n
-
-proc newNonTerminal*(name: string, line, column: int): PNonTerminal {.
-  nosideEffect, rtl, extern: "npegs$1".} =
-  ## constructs a nonterminal symbol
-  new(result)
-  result.name = name
-  result.line = line
-  result.col = column
-
-template letters*: expr =
-  ## expands to ``charset({'A'..'Z', 'a'..'z'})``
-  charSet({'A'..'Z', 'a'..'z'})
-  
-template digits*: expr =
-  ## expands to ``charset({'0'..'9'})``
-  charSet({'0'..'9'})
-
-template whitespace*: expr =
-  ## expands to ``charset({' ', '\9'..'\13'})``
-  charSet({' ', '\9'..'\13'})
-  
-template identChars*: expr =
-  ## expands to ``charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})``
-  charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'})
-  
-template identStartChars*: expr =
-  ## expands to ``charset({'A'..'Z', 'a'..'z', '_'})``
-  charSet({'a'..'z', 'A'..'Z', '_'})
-
-template ident*: expr =
-  ## same as ``[a-zA-Z_][a-zA-z_0-9]*``; standard identifier
-  sequence(charSet({'a'..'z', 'A'..'Z', '_'}),
-           *charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'}))
-  
-template natural*: expr =
-  ## same as ``\d+``
-  +digits
-
-# ------------------------- debugging -----------------------------------------
-
-proc esc(c: char, reserved = {'\0'..'\255'}): string = 
-  case c
-  of '\b': result = "\\b"
-  of '\t': result = "\\t"
-  of '\c': result = "\\c"
-  of '\L': result = "\\l"
-  of '\v': result = "\\v"
-  of '\f': result = "\\f"
-  of '\e': result = "\\e"
-  of '\a': result = "\\a"
-  of '\\': result = "\\\\"
-  of 'a'..'z', 'A'..'Z', '0'..'9', '_': result = $c
-  elif c < ' ' or c >= '\128': result = '\\' & $ord(c)
-  elif c in reserved: result = '\\' & c
-  else: result = $c
-  
-proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'"
-
-proc singleQuoteEsc(str: string): string = 
-  result = "'"
-  for c in items(str): add result, esc(c, {'\''})
-  add result, '\''
-  
-proc charSetEscAux(cc: set[char]): string = 
-  const reserved = {'^', '-', ']'}
-  result = ""
-  var c1 = 0
-  while c1 <= 0xff: 
-    if chr(c1) in cc: 
-      var c2 = c1
-      while c2 < 0xff and chr(succ(c2)) in cc: inc(c2)
-      if c1 == c2: 
-        add result, esc(chr(c1), reserved)
-      elif c2 == succ(c1): 
-        add result, esc(chr(c1), reserved) & esc(chr(c2), reserved)
-      else: 
-        add result, esc(chr(c1), reserved) & '-' & esc(chr(c2), reserved)
-      c1 = c2
-    inc(c1)
-  
-proc charSetEsc(cc: set[char]): string =
-  if card(cc) >= 128+64: 
-    result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']'
-  else: 
-    result = '[' & charSetEscAux(cc) & ']'
-  
-proc toStrAux(r: TPeg, res: var string) = 
-  case r.kind
-  of pkEmpty: add(res, "()")
-  of pkAny: add(res, '.')
-  of pkAnyRune: add(res, '_')
-  of pkLetter: add(res, "\\letter")
-  of pkLower: add(res, "\\lower")
-  of pkUpper: add(res, "\\upper")
-  of pkTitle: add(res, "\\title")
-  of pkWhitespace: add(res, "\\white")
-
-  of pkNewLine: add(res, "\\n")
-  of pkTerminal: add(res, singleQuoteEsc(r.term))
-  of pkTerminalIgnoreCase:
-    add(res, 'i')
-    add(res, singleQuoteEsc(r.term))
-  of pkTerminalIgnoreStyle:
-    add(res, 'y')
-    add(res, singleQuoteEsc(r.term))
-  of pkChar: add(res, singleQuoteEsc(r.ch))
-  of pkCharChoice: add(res, charSetEsc(r.charChoice[]))
-  of pkNonTerminal: add(res, r.nt.name)
-  of pkSequence:
-    add(res, '(')
-    toStrAux(r.sons[0], res)
-    for i in 1 .. high(r.sons):
-      add(res, ' ')
-      toStrAux(r.sons[i], res)
-    add(res, ')')
-  of pkOrderedChoice:
-    add(res, '(')
-    toStrAux(r.sons[0], res)
-    for i in 1 .. high(r.sons):
-      add(res, " / ")
-      toStrAux(r.sons[i], res)
-    add(res, ')')
-  of pkGreedyRep:
-    toStrAux(r.sons[0], res)
-    add(res, '*')
-  of pkGreedyRepChar:
-    add(res, singleQuoteEsc(r.ch))
-    add(res, '*')
-  of pkGreedyRepSet:
-    add(res, charSetEsc(r.charChoice[]))
-    add(res, '*')
-  of pkGreedyAny:
-    add(res, ".*")
-  of pkOption:
-    toStrAux(r.sons[0], res)
-    add(res, '?')
-  of pkAndPredicate:
-    add(res, '&')
-    toStrAux(r.sons[0], res)
-  of pkNotPredicate:
-    add(res, '!')
-    toStrAux(r.sons[0], res)
-  of pkSearch:
-    add(res, '@')
-    toStrAux(r.sons[0], res)
-  of pkCapturedSearch:
-    add(res, "{@}")
-    toStrAux(r.sons[0], res)
-  of pkCapture:
-    add(res, '{')
-    toStrAux(r.sons[0], res)    
-    add(res, '}')
-  of pkBackRef: 
-    add(res, '$')
-    add(res, $r.index)
-  of pkBackRefIgnoreCase: 
-    add(res, "i$")
-    add(res, $r.index)
-  of pkBackRefIgnoreStyle: 
-    add(res, "y$")
-    add(res, $r.index)
-  of pkRule:
-    toStrAux(r.sons[0], res)    
-    add(res, " <- ")
-    toStrAux(r.sons[1], res)
-  of pkList:
-    for i in 0 .. high(r.sons):
-      toStrAux(r.sons[i], res)
-      add(res, "\n")  
-  of pkStartAnchor:
-    add(res, '^')
-
-proc `$` *(r: TPeg): string {.nosideEffect, rtl, extern: "npegsToString".} =
-  ## converts a PEG to its string representation
-  result = ""
-  toStrAux(r, result)
-
-# --------------------- core engine -------------------------------------------
-
-type
-  Captures* = object ## contains the captured substrings.
-    matches: array[0..MaxSubpatterns-1, tuple[first, last: int]]
-    ml: int
-    origStart: int
-
-{.deprecated: [TCaptures: Captures].}
-
-proc bounds*(c: Captures, 
-             i: range[0..MaxSubpatterns-1]): tuple[first, last: int] = 
-  ## returns the bounds ``[first..last]`` of the `i`'th capture.
-  result = c.matches[i]
-
-when not useUnicode:
-  type
-    TRune = char
-  template fastRuneAt(s, i, ch: expr) =
-    ch = s[i]
-    inc(i)
-  template runeLenAt(s, i: expr): expr = 1
-
-  proc isAlpha(a: char): bool {.inline.} = return a in {'a'..'z','A'..'Z'}
-  proc isUpper(a: char): bool {.inline.} = return a in {'A'..'Z'}
-  proc isLower(a: char): bool {.inline.} = return a in {'a'..'z'}
-  proc isTitle(a: char): bool {.inline.} = return false
-  proc isWhiteSpace(a: char): bool {.inline.} = return a in {' ', '\9'..'\13'}
-
-proc rawMatch*(s: string, p: TPeg, start: int, c: var Captures): int {.
-               nosideEffect, rtl, extern: "npegs$1".} =
-  ## low-level matching proc that implements the PEG interpreter. Use this 
-  ## for maximum efficiency (every other PEG operation ends up calling this
-  ## proc).
-  ## Returns -1 if it does not match, else the length of the match
-  case p.kind
-  of pkEmpty: result = 0 # match of length 0
-  of pkAny:
-    if s[start] != '\0': result = 1
-    else: result = -1
-  of pkAnyRune:
-    if s[start] != '\0':
-      result = runeLenAt(s, start)
-    else:
-      result = -1
-  of pkLetter: 
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isAlpha(a): dec(result, start)
-      else: result = -1
-    else:
-      result = -1
-  of pkLower: 
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isLower(a): dec(result, start)
-      else: result = -1
-    else:
-      result = -1
-  of pkUpper: 
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isUpper(a): dec(result, start)
-      else: result = -1
-    else:
-      result = -1
-  of pkTitle: 
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isTitle(a): dec(result, start) 
-      else: result = -1
-    else:
-      result = -1
-  of pkWhitespace: 
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isWhiteSpace(a): dec(result, start)
-      else: result = -1
-    else:
-      result = -1
-  of pkGreedyAny:
-    result = len(s) - start
-  of pkNewLine:
-    if s[start] == '\L': result = 1
-    elif s[start] == '\C':
-      if s[start+1] == '\L': result = 2
-      else: result = 1
-    else: result = -1
-  of pkTerminal:
-    result = len(p.term)
-    for i in 0..result-1:
-      if p.term[i] != s[start+i]:
-        result = -1
-        break
-  of pkTerminalIgnoreCase:
-    var
-      i = 0
-      a, b: Rune
-    result = start
-    while i < len(p.term):
-      fastRuneAt(p.term, i, a)
-      fastRuneAt(s, result, b)
-      if toLower(a) != toLower(b):
-        result = -1
-        break
-    dec(result, start)
-  of pkTerminalIgnoreStyle:
-    var
-      i = 0
-      a, b: Rune
-    result = start
-    while i < len(p.term):
-      while true:
-        fastRuneAt(p.term, i, a)
-        if a != Rune('_'): break
-      while true:
-        fastRuneAt(s, result, b)
-        if b != Rune('_'): break
-      if toLower(a) != toLower(b):
-        result = -1
-        break
-    dec(result, start)
-  of pkChar:
-    if p.ch == s[start]: result = 1
-    else: result = -1
-  of pkCharChoice:
-    if contains(p.charChoice[], s[start]): result = 1
-    else: result = -1
-  of pkNonTerminal:
-    var oldMl = c.ml
-    when false: echo "enter: ", p.nt.name
-    result = rawMatch(s, p.nt.rule, start, c)
-    when false: echo "leave: ", p.nt.name
-    if result < 0: c.ml = oldMl
-  of pkSequence:
-    var oldMl = c.ml  
-    result = 0
-    for i in 0..high(p.sons):
-      var x = rawMatch(s, p.sons[i], start+result, c)
-      if x < 0:
-        c.ml = oldMl
-        result = -1
-        break
-      else: inc(result, x)
-  of pkOrderedChoice:
-    var oldMl = c.ml
-    for i in 0..high(p.sons):
-      result = rawMatch(s, p.sons[i], start, c)
-      if result >= 0: break
-      c.ml = oldMl
-  of pkSearch:
-    var oldMl = c.ml
-    result = 0
-    while start+result < s.len:
-      var x = rawMatch(s, p.sons[0], start+result, c)
-      if x >= 0:
-        inc(result, x)
-        return
-      inc(result)
-    result = -1
-    c.ml = oldMl
-  of pkCapturedSearch:
-    var idx = c.ml # reserve a slot for the subpattern
-    inc(c.ml)
-    result = 0
-    while start+result < s.len:
-      var x = rawMatch(s, p.sons[0], start+result, c)
-      if x >= 0:
-        if idx < MaxSubpatterns:
-          c.matches[idx] = (start, start+result-1)
-        #else: silently ignore the capture
-        inc(result, x)
-        return
-      inc(result)
-    result = -1
-    c.ml = idx
-  of pkGreedyRep:
-    result = 0
-    while true:
-      var x = rawMatch(s, p.sons[0], start+result, c)
-      # if x == 0, we have an endless loop; so the correct behaviour would be
-      # not to break. But endless loops can be easily introduced:
-      # ``(comment / \w*)*`` is such an example. Breaking for x == 0 does the
-      # expected thing in this case.
-      if x <= 0: break
-      inc(result, x)
-  of pkGreedyRepChar:
-    result = 0
-    var ch = p.ch
-    while ch == s[start+result]: inc(result)
-  of pkGreedyRepSet:
-    result = 0
-    while contains(p.charChoice[], s[start+result]): inc(result)
-  of pkOption:
-    result = max(0, rawMatch(s, p.sons[0], start, c))
-  of pkAndPredicate:
-    var oldMl = c.ml
-    result = rawMatch(s, p.sons[0], start, c)
-    if result >= 0: result = 0 # do not consume anything
-    else: c.ml = oldMl
-  of pkNotPredicate:
-    var oldMl = c.ml
-    result = rawMatch(s, p.sons[0], start, c)
-    if result < 0: result = 0
-    else:
-      c.ml = oldMl
-      result = -1
-  of pkCapture:
-    var idx = c.ml # reserve a slot for the subpattern
-    inc(c.ml)
-    result = rawMatch(s, p.sons[0], start, c)
-    if result >= 0:
-      if idx < MaxSubpatterns:
-        c.matches[idx] = (start, start+result-1)
-      #else: silently ignore the capture
-    else:
-      c.ml = idx
-  of pkBackRef..pkBackRefIgnoreStyle: 
-    if p.index >= c.ml: return -1
-    var (a, b) = c.matches[p.index]
-    var n: TPeg
-    n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef)) 
-    n.term = s.substr(a, b)
-    result = rawMatch(s, n, start, c)
-  of pkStartAnchor:
-    if c.origStart == start: result = 0
-    else: result = -1
-  of pkRule, pkList: assert false
-
-template fillMatches(s, caps, c: expr) =
-  for k in 0..c.ml-1:
-    caps[k] = substr(s, c.matches[k][0], c.matches[k][1])
-
-proc match*(s: string, pattern: TPeg, matches: var openArray[string],
-            start = 0): bool {.nosideEffect, rtl, extern: "npegs$1Capture".} =
-  ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and
-  ## the captured substrings in the array ``matches``. If it does not
-  ## match, nothing is written into ``matches`` and ``false`` is
-  ## returned.
-  var c: Captures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c) == len(s) - start
-  if result: fillMatches(s, matches, c)
-
-proc match*(s: string, pattern: TPeg, 
-            start = 0): bool {.nosideEffect, rtl, extern: "npegs$1".} =
-  ## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``.
-  var c: Captures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c) == len(s)-start
-
-proc matchLen*(s: string, pattern: TPeg, matches: var openArray[string],
-               start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} =
-  ## the same as ``match``, but it returns the length of the match,
-  ## if there is no match, -1 is returned. Note that a match length
-  ## of zero can happen. It's possible that a suffix of `s` remains
-  ## that does not belong to the match.
-  var c: Captures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c)
-  if result >= 0: fillMatches(s, matches, c)
-
-proc matchLen*(s: string, pattern: TPeg, 
-               start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} =
-  ## the same as ``match``, but it returns the length of the match,
-  ## if there is no match, -1 is returned. Note that a match length
-  ## of zero can happen. It's possible that a suffix of `s` remains
-  ## that does not belong to the match.
-  var c: Captures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c)
-
-proc find*(s: string, pattern: TPeg, matches: var openArray[string],
-           start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} =
-  ## returns the starting position of ``pattern`` in ``s`` and the captured
-  ## substrings in the array ``matches``. If it does not match, nothing
-  ## is written into ``matches`` and -1 is returned.
-  var c: Captures
-  c.origStart = start
-  for i in start .. s.len-1:
-    c.ml = 0
-    if rawMatch(s, pattern, i, c) >= 0:
-      fillMatches(s, matches, c)
-      return i
-  return -1
-  # could also use the pattern here: (!P .)* P
-  
-proc findBounds*(s: string, pattern: TPeg, matches: var openArray[string],
-                 start = 0): tuple[first, last: int] {.
-                 nosideEffect, rtl, extern: "npegs$1Capture".} =
-  ## returns the starting position and end position of ``pattern`` in ``s`` 
-  ## and the captured
-  ## substrings in the array ``matches``. If it does not match, nothing
-  ## is written into ``matches`` and (-1,0) is returned.
-  var c: Captures
-  c.origStart = start
-  for i in start .. s.len-1:
-    c.ml = 0
-    var L = rawMatch(s, pattern, i, c)
-    if L >= 0:
-      fillMatches(s, matches, c)
-      return (i, i+L-1)
-  return (-1, 0)
-  
-proc find*(s: string, pattern: TPeg, 
-           start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} =
-  ## returns the starting position of ``pattern`` in ``s``. If it does not
-  ## match, -1 is returned.
-  var c: Captures
-  c.origStart = start
-  for i in start .. s.len-1:
-    if rawMatch(s, pattern, i, c) >= 0: return i
-  return -1
-  
-iterator findAll*(s: string, pattern: TPeg, start = 0): string = 
-  ## yields all matching *substrings* of `s` that match `pattern`.
-  var c: Captures
-  c.origStart = start
-  var i = start
-  while i < s.len:
-    c.ml = 0
-    var L = rawMatch(s, pattern, i, c)
-    if L < 0:
-      inc(i, 1)
-    else:
-      yield substr(s, i, i+L-1)
-      inc(i, L)
-    
-proc findAll*(s: string, pattern: TPeg, start = 0): seq[string] {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
-  ## returns all matching *substrings* of `s` that match `pattern`.
-  ## If it does not match, @[] is returned.
-  accumulateResult(findAll(s, pattern, start))
-
-when not defined(nimhygiene):
-  {.pragma: inject.}
-  
-template `=~`*(s: string, pattern: TPeg): bool =
-  ## This calls ``match`` with an implicit declared ``matches`` array that 
-  ## can be used in the scope of the ``=~`` call: 
-  ## 
-  ## .. code-block:: nim
-  ##
-  ##   if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}": 
-  ##     # matches a key=value pair:
-  ##     echo("Key: ", matches[0])
-  ##     echo("Value: ", matches[1])
-  ##   elif line =~ peg"\s*{'#'.*}":
-  ##     # matches a comment
-  ##     # note that the implicit ``matches`` array is different from the
-  ##     # ``matches`` array of the first branch
-  ##     echo("comment: ", matches[0])
-  ##   else:
-  ##     echo("syntax error")
-  ##  
-  bind MaxSubpatterns
-  when not declaredInScope(matches):
-    var matches {.inject.}: array[0..MaxSubpatterns-1, string]
-  match(s, pattern, matches)
-
-# ------------------------- more string handling ------------------------------
-
-proc contains*(s: string, pattern: TPeg, start = 0): bool {.
-  nosideEffect, rtl, extern: "npegs$1".} =
-  ## same as ``find(s, pattern, start) >= 0``
-  return find(s, pattern, start) >= 0
-
-proc contains*(s: string, pattern: TPeg, matches: var openArray[string],
-              start = 0): bool {.nosideEffect, rtl, extern: "npegs$1Capture".} =
-  ## same as ``find(s, pattern, matches, start) >= 0``
-  return find(s, pattern, matches, start) >= 0
-
-proc startsWith*(s: string, prefix: TPeg, start = 0): bool {.
-  nosideEffect, rtl, extern: "npegs$1".} =
-  ## returns true if `s` starts with the pattern `prefix`
-  result = matchLen(s, prefix, start) >= 0
-
-proc endsWith*(s: string, suffix: TPeg, start = 0): bool {.
-  nosideEffect, rtl, extern: "npegs$1".} =
-  ## returns true if `s` ends with the pattern `prefix`
-  var c: Captures
-  c.origStart = start
-  for i in start .. s.len-1:
-    if rawMatch(s, suffix, i, c) == s.len - i: return true
-
-proc replacef*(s: string, sub: TPeg, by: string): string {.
-  nosideEffect, rtl, extern: "npegs$1".} =
-  ## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by`
-  ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
-  ##
-  ## .. code-block:: nim
-  ##   "var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2")
-  ##
-  ## Results in:
-  ##
-  ## .. code-block:: nim
-  ##
-  ##   "var1<-keykey; val2<-key2key2"
-  result = ""
-  var i = 0
-  var caps: array[0..MaxSubpatterns-1, string]
-  var c: Captures
-  while i < s.len:
-    c.ml = 0
-    var x = rawMatch(s, sub, i, c)
-    if x <= 0:
-      add(result, s[i])
-      inc(i)
-    else:
-      fillMatches(s, caps, c)
-      addf(result, by, caps)
-      inc(i, x)
-  add(result, substr(s, i))
-
-proc replace*(s: string, sub: TPeg, by = ""): string {.
-  nosideEffect, rtl, extern: "npegs$1".} =
-  ## Replaces `sub` in `s` by the string `by`. Captures cannot be accessed
-  ## in `by`.
-  result = ""
-  var i = 0
-  var c: Captures
-  while i < s.len:
-    var x = rawMatch(s, sub, i, c)
-    if x <= 0:
-      add(result, s[i])
-      inc(i)
-    else:
-      add(result, by)
-      inc(i, x)
-  add(result, substr(s, i))
-  
-proc parallelReplace*(s: string, subs: varargs[
-                      tuple[pattern: TPeg, repl: string]]): string {.
-                      nosideEffect, rtl, extern: "npegs$1".} = 
-  ## Returns a modified copy of `s` with the substitutions in `subs`
-  ## applied in parallel.
-  result = ""
-  var i = 0
-  var c: Captures
-  var caps: array[0..MaxSubpatterns-1, string]
-  while i < s.len:
-    block searchSubs:
-      for j in 0..high(subs):
-        c.ml = 0
-        var x = rawMatch(s, subs[j][0], i, c)
-        if x > 0:
-          fillMatches(s, caps, c)
-          addf(result, subs[j][1], caps)
-          inc(i, x)
-          break searchSubs
-      add(result, s[i])
-      inc(i)
-  # copy the rest:
-  add(result, substr(s, i))  
-  
-proc transformFile*(infile, outfile: string,
-                    subs: varargs[tuple[pattern: TPeg, repl: string]]) {.
-                    rtl, extern: "npegs$1".} =
-  ## reads in the file `infile`, performs a parallel replacement (calls
-  ## `parallelReplace`) and writes back to `outfile`. Raises ``EIO`` if an
-  ## error occurs. This is supposed to be used for quick scripting.
-  var x = readFile(infile).string
-  writeFile(outfile, x.parallelReplace(subs))
-  
-iterator split*(s: string, sep: TPeg): string =
-  ## Splits the string `s` into substrings.
-  ##
-  ## Substrings are separated by the PEG `sep`.
-  ## Examples:
-  ##
-  ## .. code-block:: nim
-  ##   for word in split("00232this02939is39an22example111", peg"\d+"):
-  ##     writeln(stdout, word)
-  ##
-  ## Results in:
-  ##
-  ## .. code-block:: nim
-  ##   "this"
-  ##   "is"
-  ##   "an"
-  ##   "example"
-  ##
-  var c: Captures
-  var
-    first = 0
-    last = 0
-  while last < len(s):
-    c.ml = 0
-    var x = rawMatch(s, sep, last, c)
-    if x > 0: inc(last, x)
-    first = last
-    while last < len(s):
-      inc(last)
-      c.ml = 0
-      x = rawMatch(s, sep, last, c)
-      if x > 0: break
-    if first < last:
-      yield substr(s, first, last-1)
-
-proc split*(s: string, sep: TPeg): seq[string] {.
-  nosideEffect, rtl, extern: "npegs$1".} =
-  ## Splits the string `s` into substrings.
-  accumulateResult(split(s, sep))
-
-# ------------------- scanner -------------------------------------------------
-
-type
-  TModifier = enum
-    modNone,
-    modVerbatim,
-    modIgnoreCase,
-    modIgnoreStyle
-  TTokKind = enum       ## enumeration of all tokens
-    tkInvalid,          ## invalid token
-    tkEof,              ## end of file reached
-    tkAny,              ## .
-    tkAnyRune,          ## _
-    tkIdentifier,       ## abc
-    tkStringLit,        ## "abc" or 'abc'
-    tkCharSet,          ## [^A-Z]
-    tkParLe,            ## '('
-    tkParRi,            ## ')'
-    tkCurlyLe,          ## '{'
-    tkCurlyRi,          ## '}'
-    tkCurlyAt,          ## '{@}'
-    tkArrow,            ## '<-'
-    tkBar,              ## '/'
-    tkStar,             ## '*'
-    tkPlus,             ## '+'
-    tkAmp,              ## '&'
-    tkNot,              ## '!'
-    tkOption,           ## '?'
-    tkAt,               ## '@'
-    tkBuiltin,          ## \identifier
-    tkEscaped,          ## \\
-    tkBackref,          ## '$'
-    tkDollar,           ## '$'
-    tkHat               ## '^'
-  
-  TToken {.final.} = object  ## a token
-    kind: TTokKind           ## the type of the token
-    modifier: TModifier
-    literal: string          ## the parsed (string) literal
-    charset: set[char]       ## if kind == tkCharSet
-    index: int               ## if kind == tkBackref
-  
-  PegLexer {.inheritable.} = object          ## the lexer object.
-    bufpos: int               ## the current position within the buffer
-    buf: cstring              ## the buffer itself
-    lineNumber: int           ## the current line number
-    lineStart: int            ## index of last line start in buffer
-    colOffset: int            ## column to add
-    filename: string
-
-const
-  tokKindToStr: array[TTokKind, string] = [
-    "invalid", "[EOF]", ".", "_", "identifier", "string literal",
-    "character set", "(", ")", "{", "}", "{@}",
-    "<-", "/", "*", "+", "&", "!", "?",
-    "@", "built-in", "escaped", "$", "$", "^"
-  ]
-
-proc handleCR(L: var PegLexer, pos: int): int =
-  assert(L.buf[pos] == '\c')
-  inc(L.lineNumber)
-  result = pos+1
-  if L.buf[result] == '\L': inc(result)
-  L.lineStart = result
-
-proc handleLF(L: var PegLexer, pos: int): int =
-  assert(L.buf[pos] == '\L')
-  inc(L.lineNumber)
-  result = pos+1
-  L.lineStart = result
-
-proc init(L: var PegLexer, input, filename: string, line = 1, col = 0) = 
-  L.buf = input
-  L.bufpos = 0
-  L.lineNumber = line
-  L.colOffset = col
-  L.lineStart = 0
-  L.filename = filename
-
-proc getColumn(L: PegLexer): int {.inline.} = 
-  result = abs(L.bufpos - L.lineStart) + L.colOffset
-
-proc getLine(L: PegLexer): int {.inline.} = 
-  result = L.lineNumber
-  
-proc errorStr(L: PegLexer, msg: string, line = -1, col = -1): string =
-  var line = if line < 0: getLine(L) else: line
-  var col = if col < 0: getColumn(L) else: col
-  result = "$1($2, $3) Error: $4" % [L.filename, $line, $col, msg]
-
-proc handleHexChar(c: var PegLexer, xi: var int) = 
-  case c.buf[c.bufpos]
-  of '0'..'9': 
-    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0'))
-    inc(c.bufpos)
-  of 'a'..'f': 
-    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10)
-    inc(c.bufpos)
-  of 'A'..'F': 
-    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
-    inc(c.bufpos)
-  else: discard
-
-proc getEscapedChar(c: var PegLexer, tok: var TToken) = 
-  inc(c.bufpos)
-  case c.buf[c.bufpos]
-  of 'r', 'R', 'c', 'C': 
-    add(tok.literal, '\c')
-    inc(c.bufpos)
-  of 'l', 'L': 
-    add(tok.literal, '\L')
-    inc(c.bufpos)
-  of 'f', 'F': 
-    add(tok.literal, '\f')
-    inc(c.bufpos)
-  of 'e', 'E': 
-    add(tok.literal, '\e')
-    inc(c.bufpos)
-  of 'a', 'A': 
-    add(tok.literal, '\a')
-    inc(c.bufpos)
-  of 'b', 'B': 
-    add(tok.literal, '\b')
-    inc(c.bufpos)
-  of 'v', 'V': 
-    add(tok.literal, '\v')
-    inc(c.bufpos)
-  of 't', 'T': 
-    add(tok.literal, '\t')
-    inc(c.bufpos)
-  of 'x', 'X': 
-    inc(c.bufpos)
-    var xi = 0
-    handleHexChar(c, xi)
-    handleHexChar(c, xi)
-    if xi == 0: tok.kind = tkInvalid
-    else: add(tok.literal, chr(xi))
-  of '0'..'9': 
-    var val = ord(c.buf[c.bufpos]) - ord('0')
-    inc(c.bufpos)
-    var i = 1
-    while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}): 
-      val = val * 10 + ord(c.buf[c.bufpos]) - ord('0')
-      inc(c.bufpos)
-      inc(i)
-    if val > 0 and val <= 255: add(tok.literal, chr(val))
-    else: tok.kind = tkInvalid
-  of '\0'..'\31':
-    tok.kind = tkInvalid
-  elif c.buf[c.bufpos] in strutils.Letters:
-    tok.kind = tkInvalid
-  else:
-    add(tok.literal, c.buf[c.bufpos])
-    inc(c.bufpos)
-  
-proc skip(c: var PegLexer) = 
-  var pos = c.bufpos
-  var buf = c.buf
-  while true: 
-    case buf[pos]
-    of ' ', '\t': 
-      inc(pos)
-    of '#':
-      while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
-    of '\c':
-      pos = handleCR(c, pos)
-      buf = c.buf
-    of '\L': 
-      pos = handleLF(c, pos)
-      buf = c.buf
-    else: 
-      break                   # EndOfFile also leaves the loop
-  c.bufpos = pos
-  
-proc getString(c: var PegLexer, tok: var TToken) = 
-  tok.kind = tkStringLit
-  var pos = c.bufpos + 1
-  var buf = c.buf
-  var quote = buf[pos-1]
-  while true: 
-    case buf[pos]
-    of '\\':
-      c.bufpos = pos
-      getEscapedChar(c, tok)
-      pos = c.bufpos
-    of '\c', '\L', '\0':
-      tok.kind = tkInvalid
-      break
-    elif buf[pos] == quote:
-      inc(pos)
-      break      
-    else:
-      add(tok.literal, buf[pos])
-      inc(pos)
-  c.bufpos = pos
-  
-proc getDollar(c: var PegLexer, tok: var TToken) = 
-  var pos = c.bufpos + 1
-  var buf = c.buf
-  if buf[pos] in {'0'..'9'}:
-    tok.kind = tkBackref
-    tok.index = 0
-    while buf[pos] in {'0'..'9'}:
-      tok.index = tok.index * 10 + ord(buf[pos]) - ord('0')
-      inc(pos)
-  else:
-    tok.kind = tkDollar
-  c.bufpos = pos
-  
-proc getCharSet(c: var PegLexer, tok: var TToken) = 
-  tok.kind = tkCharSet
-  tok.charset = {}
-  var pos = c.bufpos + 1
-  var buf = c.buf
-  var caret = false
-  if buf[pos] == '^':
-    inc(pos)
-    caret = true
-  while true:
-    var ch: char
-    case buf[pos]
-    of ']':
-      inc(pos)
-      break
-    of '\\':
-      c.bufpos = pos
-      getEscapedChar(c, tok)
-      pos = c.bufpos
-      ch = tok.literal[tok.literal.len-1]
-    of '\C', '\L', '\0':
-      tok.kind = tkInvalid
-      break
-    else: 
-      ch = buf[pos]
-      inc(pos)
-    incl(tok.charset, ch)
-    if buf[pos] == '-':
-      if buf[pos+1] == ']':
-        incl(tok.charset, '-')
-        inc(pos)
-      else:
-        inc(pos)
-        var ch2: char
-        case buf[pos]
-        of '\\':
-          c.bufpos = pos
-          getEscapedChar(c, tok)
-          pos = c.bufpos
-          ch2 = tok.literal[tok.literal.len-1]
-        of '\C', '\L', '\0':
-          tok.kind = tkInvalid
-          break
-        else: 
-          ch2 = buf[pos]
-          inc(pos)
-        for i in ord(ch)+1 .. ord(ch2):
-          incl(tok.charset, chr(i))
-  c.bufpos = pos
-  if caret: tok.charset = {'\1'..'\xFF'} - tok.charset
-  
-proc getSymbol(c: var PegLexer, tok: var TToken) = 
-  var pos = c.bufpos
-  var buf = c.buf
-  while true: 
-    add(tok.literal, buf[pos])
-    inc(pos)
-    if buf[pos] notin strutils.IdentChars: break
-  c.bufpos = pos
-  tok.kind = tkIdentifier
-
-proc getBuiltin(c: var PegLexer, tok: var TToken) =
-  if c.buf[c.bufpos+1] in strutils.Letters:
-    inc(c.bufpos)
-    getSymbol(c, tok)
-    tok.kind = tkBuiltin
-  else:
-    tok.kind = tkEscaped
-    getEscapedChar(c, tok) # may set tok.kind to tkInvalid
-
-proc getTok(c: var PegLexer, tok: var TToken) = 
-  tok.kind = tkInvalid
-  tok.modifier = modNone
-  setLen(tok.literal, 0)
-  skip(c)
-  case c.buf[c.bufpos]
-  of '{':
-    inc(c.bufpos)
-    if c.buf[c.bufpos] == '@' and c.buf[c.bufpos+1] == '}':
-      tok.kind = tkCurlyAt
-      inc(c.bufpos, 2)
-      add(tok.literal, "{@}")
-    else:
-      tok.kind = tkCurlyLe
-      add(tok.literal, '{')
-  of '}': 
-    tok.kind = tkCurlyRi
-    inc(c.bufpos)
-    add(tok.literal, '}')
-  of '[': 
-    getCharSet(c, tok)
-  of '(':
-    tok.kind = tkParLe
-    inc(c.bufpos)
-    add(tok.literal, '(')
-  of ')':
-    tok.kind = tkParRi
-    inc(c.bufpos)
-    add(tok.literal, ')')
-  of '.': 
-    tok.kind = tkAny
-    inc(c.bufpos)
-    add(tok.literal, '.')
-  of '_':
-    tok.kind = tkAnyRune
-    inc(c.bufpos)
-    add(tok.literal, '_')
-  of '\\': 
-    getBuiltin(c, tok)
-  of '\'', '"': getString(c, tok)
-  of '$': getDollar(c, tok)
-  of '\0': 
-    tok.kind = tkEof
-    tok.literal = "[EOF]"
-  of 'a'..'z', 'A'..'Z', '\128'..'\255':
-    getSymbol(c, tok)
-    if c.buf[c.bufpos] in {'\'', '"'} or 
-        c.buf[c.bufpos] == '$' and c.buf[c.bufpos+1] in {'0'..'9'}:
-      case tok.literal
-      of "i": tok.modifier = modIgnoreCase
-      of "y": tok.modifier = modIgnoreStyle
-      of "v": tok.modifier = modVerbatim
-      else: discard
-      setLen(tok.literal, 0)
-      if c.buf[c.bufpos] == '$':
-        getDollar(c, tok)
-      else:
-        getString(c, tok)
-      if tok.modifier == modNone: tok.kind = tkInvalid
-  of '+':
-    tok.kind = tkPlus
-    inc(c.bufpos)
-    add(tok.literal, '+')
-  of '*':
-    tok.kind = tkStar
-    inc(c.bufpos)
-    add(tok.literal, '+')
-  of '<':
-    if c.buf[c.bufpos+1] == '-':
-      inc(c.bufpos, 2)
-      tok.kind = tkArrow
-      add(tok.literal, "<-")
-    else:
-      add(tok.literal, '<')
-  of '/':
-    tok.kind = tkBar
-    inc(c.bufpos)
-    add(tok.literal, '/')
-  of '?':
-    tok.kind = tkOption
-    inc(c.bufpos)
-    add(tok.literal, '?')
-  of '!':
-    tok.kind = tkNot
-    inc(c.bufpos)
-    add(tok.literal, '!')
-  of '&':
-    tok.kind = tkAmp
-    inc(c.bufpos)
-    add(tok.literal, '!')
-  of '@':
-    tok.kind = tkAt
-    inc(c.bufpos)
-    add(tok.literal, '@')
-    if c.buf[c.bufpos] == '@': 
-      tok.kind = tkCurlyAt
-      inc(c.bufpos)
-      add(tok.literal, '@')
-  of '^':
-    tok.kind = tkHat
-    inc(c.bufpos)
-    add(tok.literal, '^')
-  else:
-    add(tok.literal, c.buf[c.bufpos])
-    inc(c.bufpos)
-
-proc arrowIsNextTok(c: PegLexer): bool =
-  # the only look ahead we need
-  var pos = c.bufpos
-  while c.buf[pos] in {'\t', ' '}: inc(pos)
-  result = c.buf[pos] == '<' and c.buf[pos+1] == '-'
-
-# ----------------------------- parser ----------------------------------------
-    
-type
-  EInvalidPeg* = object of ValueError ## raised if an invalid
-                                         ## PEG has been detected
-  PegParser = object of PegLexer ## the PEG parser object
-    tok: TToken
-    nonterms: seq[PNonTerminal]
-    modifier: TModifier
-    captures: int
-    identIsVerbatim: bool
-    skip: TPeg
-
-proc pegError(p: PegParser, msg: string, line = -1, col = -1) =
-  var e: ref EInvalidPeg
-  new(e)
-  e.msg = errorStr(p, msg, line, col)
-  raise e
-
-proc getTok(p: var PegParser) = 
-  getTok(p, p.tok)
-  if p.tok.kind == tkInvalid: pegError(p, "invalid token")
-
-proc eat(p: var PegParser, kind: TTokKind) =
-  if p.tok.kind == kind: getTok(p)
-  else: pegError(p, tokKindToStr[kind] & " expected")
-
-proc parseExpr(p: var PegParser): TPeg
-
-proc getNonTerminal(p: var PegParser, name: string): PNonTerminal =
-  for i in 0..high(p.nonterms):
-    result = p.nonterms[i]
-    if cmpIgnoreStyle(result.name, name) == 0: return
-  # forward reference:
-  result = newNonTerminal(name, getLine(p), getColumn(p))
-  add(p.nonterms, result)
-
-proc modifiedTerm(s: string, m: TModifier): TPeg =
-  case m
-  of modNone, modVerbatim: result = term(s)
-  of modIgnoreCase: result = termIgnoreCase(s)
-  of modIgnoreStyle: result = termIgnoreStyle(s)
-
-proc modifiedBackref(s: int, m: TModifier): TPeg =
-  case m
-  of modNone, modVerbatim: result = backref(s)
-  of modIgnoreCase: result = backrefIgnoreCase(s)
-  of modIgnoreStyle: result = backrefIgnoreStyle(s)
-
-proc builtin(p: var PegParser): TPeg =
-  # do not use "y", "skip" or "i" as these would be ambiguous
-  case p.tok.literal
-  of "n": result = newLine()
-  of "d": result = charSet({'0'..'9'})
-  of "D": result = charSet({'\1'..'\xff'} - {'0'..'9'})
-  of "s": result = charSet({' ', '\9'..'\13'})
-  of "S": result = charSet({'\1'..'\xff'} - {' ', '\9'..'\13'})
-  of "w": result = charSet({'a'..'z', 'A'..'Z', '_', '0'..'9'})
-  of "W": result = charSet({'\1'..'\xff'} - {'a'..'z','A'..'Z','_','0'..'9'})
-  of "a": result = charSet({'a'..'z', 'A'..'Z'})
-  of "A": result = charSet({'\1'..'\xff'} - {'a'..'z', 'A'..'Z'})
-  of "ident": result = pegs.ident
-  of "letter": result = unicodeLetter()
-  of "upper": result = unicodeUpper()
-  of "lower": result = unicodeLower()
-  of "title": result = unicodeTitle()
-  of "white": result = unicodeWhitespace()
-  else: pegError(p, "unknown built-in: " & p.tok.literal)
-
-proc token(terminal: TPeg, p: PegParser): TPeg = 
-  if p.skip.kind == pkEmpty: result = terminal
-  else: result = sequence(p.skip, terminal)
-
-proc primary(p: var PegParser): TPeg =
-  case p.tok.kind
-  of tkAmp:
-    getTok(p)
-    return &primary(p)
-  of tkNot:
-    getTok(p)
-    return !primary(p)
-  of tkAt:
-    getTok(p)
-    return !*primary(p)
-  of tkCurlyAt:
-    getTok(p)
-    return !*\primary(p).token(p)
-  else: discard
-  case p.tok.kind
-  of tkIdentifier:
-    if p.identIsVerbatim: 
-      var m = p.tok.modifier
-      if m == modNone: m = p.modifier
-      result = modifiedTerm(p.tok.literal, m).token(p)
-      getTok(p)
-    elif not arrowIsNextTok(p):
-      var nt = getNonTerminal(p, p.tok.literal)
-      incl(nt.flags, ntUsed)
-      result = nonterminal(nt).token(p)
-      getTok(p)
-    else:
-      pegError(p, "expression expected, but found: " & p.tok.literal)
-  of tkStringLit:
-    var m = p.tok.modifier
-    if m == modNone: m = p.modifier
-    result = modifiedTerm(p.tok.literal, m).token(p)
-    getTok(p)
-  of tkCharSet:
-    if '\0' in p.tok.charset:
-      pegError(p, "binary zero ('\\0') not allowed in character class")
-    result = charSet(p.tok.charset).token(p)
-    getTok(p)
-  of tkParLe:
-    getTok(p)
-    result = parseExpr(p)
-    eat(p, tkParRi)
-  of tkCurlyLe:
-    getTok(p)
-    result = capture(parseExpr(p)).token(p)
-    eat(p, tkCurlyRi)
-    inc(p.captures)
-  of tkAny:
-    result = any().token(p)
-    getTok(p)
-  of tkAnyRune:
-    result = anyRune().token(p)
-    getTok(p)
-  of tkBuiltin:
-    result = builtin(p).token(p)
-    getTok(p)
-  of tkEscaped:
-    result = term(p.tok.literal[0]).token(p)
-    getTok(p)
-  of tkDollar: 
-    result = endAnchor()
-    getTok(p)
-  of tkHat: 
-    result = startAnchor()
-    getTok(p)
-  of tkBackref:
-    var m = p.tok.modifier
-    if m == modNone: m = p.modifier
-    result = modifiedBackref(p.tok.index, m).token(p)
-    if p.tok.index < 0 or p.tok.index > p.captures: 
-      pegError(p, "invalid back reference index: " & $p.tok.index)
-    getTok(p)
-  else:
-    pegError(p, "expression expected, but found: " & p.tok.literal)
-    getTok(p) # we must consume a token here to prevent endless loops!
-  while true:
-    case p.tok.kind
-    of tkOption:
-      result = ?result
-      getTok(p)
-    of tkStar:
-      result = *result
-      getTok(p)
-    of tkPlus:
-      result = +result
-      getTok(p)
-    else: break
-
-proc seqExpr(p: var PegParser): TPeg =
-  result = primary(p)
-  while true:
-    case p.tok.kind
-    of tkAmp, tkNot, tkAt, tkStringLit, tkCharSet, tkParLe, tkCurlyLe,
-       tkAny, tkAnyRune, tkBuiltin, tkEscaped, tkDollar, tkBackref, 
-       tkHat, tkCurlyAt:
-      result = sequence(result, primary(p))
-    of tkIdentifier:
-      if not arrowIsNextTok(p):
-        result = sequence(result, primary(p))
-      else: break
-    else: break
-
-proc parseExpr(p: var PegParser): TPeg =
-  result = seqExpr(p)
-  while p.tok.kind == tkBar:
-    getTok(p)
-    result = result / seqExpr(p)
-  
-proc parseRule(p: var PegParser): PNonTerminal =
-  if p.tok.kind == tkIdentifier and arrowIsNextTok(p):
-    result = getNonTerminal(p, p.tok.literal)
-    if ntDeclared in result.flags:
-      pegError(p, "attempt to redefine: " & result.name)
-    result.line = getLine(p)
-    result.col = getColumn(p)
-    getTok(p)
-    eat(p, tkArrow)
-    result.rule = parseExpr(p)
-    incl(result.flags, ntDeclared) # NOW inlining may be attempted
-  else:
-    pegError(p, "rule expected, but found: " & p.tok.literal)
-  
-proc rawParse(p: var PegParser): TPeg =
-  ## parses a rule or a PEG expression
-  while p.tok.kind == tkBuiltin:
-    case p.tok.literal
-    of "i":
-      p.modifier = modIgnoreCase
-      getTok(p)
-    of "y":
-      p.modifier = modIgnoreStyle
-      getTok(p)
-    of "skip":
-      getTok(p)
-      p.skip = ?primary(p)
-    else: break
-  if p.tok.kind == tkIdentifier and arrowIsNextTok(p):
-    result = parseRule(p).rule
-    while p.tok.kind != tkEof:
-      discard parseRule(p)
-  else:
-    p.identIsVerbatim = true
-    result = parseExpr(p)
-  if p.tok.kind != tkEof:
-    pegError(p, "EOF expected, but found: " & p.tok.literal)
-  for i in 0..high(p.nonterms):
-    var nt = p.nonterms[i]
-    if ntDeclared notin nt.flags:
-      pegError(p, "undeclared identifier: " & nt.name, nt.line, nt.col)
-    elif ntUsed notin nt.flags and i > 0:
-      pegError(p, "unused rule: " & nt.name, nt.line, nt.col)
-
-proc parsePeg*(pattern: string, filename = "pattern", line = 1, col = 0): TPeg =
-  ## constructs a Peg object from `pattern`. `filename`, `line`, `col` are
-  ## used for error messages, but they only provide start offsets. `parsePeg`
-  ## keeps track of line and column numbers within `pattern`.
-  var p: PegParser
-  init(PegLexer(p), pattern, filename, line, col)
-  p.tok.kind = tkInvalid
-  p.tok.modifier = modNone
-  p.tok.literal = ""
-  p.tok.charset = {}
-  p.nonterms = @[]
-  p.identIsVerbatim = false
-  getTok(p)
-  result = rawParse(p)
-
-proc peg*(pattern: string): TPeg =
-  ## constructs a Peg object from the `pattern`. The short name has been
-  ## chosen to encourage its use as a raw string modifier::
-  ##
-  ##   peg"{\ident} \s* '=' \s* {.*}"
-  result = parsePeg(pattern, "pattern")
-
-proc escapePeg*(s: string): string =
-  ## escapes `s` so that it is matched verbatim when used as a peg.
-  result = ""
-  var inQuote = false
-  for c in items(s):
-    case c
-    of '\0'..'\31', '\'', '"', '\\':
-      if inQuote:
-        result.add('\'')
-        inQuote = false
-      result.add("\\x")
-      result.add(toHex(ord(c), 2))
-    else:
-      if not inQuote:
-        result.add('\'')
-        inQuote = true
-      result.add(c)
-  if inQuote: result.add('\'')
-
-when isMainModule:
-  assert escapePeg("abc''def'") == r"'abc'\x27\x27'def'\x27"
-  assert match("(a b c)", peg"'(' @ ')'")
-  assert match("W_HI_Le", peg"\y 'while'")
-  assert(not match("W_HI_L", peg"\y 'while'"))
-  assert(not match("W_HI_Le", peg"\y v'while'"))
-  assert match("W_HI_Le", peg"y'while'")
-  
-  assert($ +digits == $peg"\d+")
-  assert "0158787".match(peg"\d+")
-  assert "ABC 0232".match(peg"\w+\s+\d+")
-  assert "ABC".match(peg"\d+ / \w+")
-
-  for word in split("00232this02939is39an22example111", peg"\d+"):
-    writeln(stdout, word)
-
-  assert matchLen("key", ident) == 3
-
-  var pattern = sequence(ident, *whitespace, term('='), *whitespace, ident)
-  assert matchLen("key1=  cal9", pattern) == 11
-  
-  var ws = newNonTerminal("ws", 1, 1)
-  ws.rule = *whitespace
-  
-  var expr = newNonTerminal("expr", 1, 1)
-  expr.rule = sequence(capture(ident), *sequence(
-                nonterminal(ws), term('+'), nonterminal(ws), nonterminal(expr)))
-  
-  var c: Captures
-  var s = "a+b +  c +d+e+f"
-  assert rawMatch(s, expr.rule, 0, c) == len(s)
-  var a = ""
-  for i in 0..c.ml-1:
-    a.add(substr(s, c.matches[i][0], c.matches[i][1]))
-  assert a == "abcdef"
-  #echo expr.rule
-
-  #const filename = "lib/devel/peg/grammar.txt"
-  #var grammar = parsePeg(newFileStream(filename, fmRead), filename)
-  #echo "a <- [abc]*?".match(grammar)
-  assert find("_____abc_______", term("abc"), 2) == 5
-  assert match("_______ana", peg"A <- 'ana' / . A")
-  assert match("abcs%%%", peg"A <- ..A / .A / '%'")
-
-  var matches: array[0..MaxSubpatterns-1, string]
-  if "abc" =~ peg"{'a'}'bc' 'xyz' / {\ident}":
-    assert matches[0] == "abc"
-  else:
-    assert false
-  
-  var g2 = peg"""S <- A B / C D
-                 A <- 'a'+
-                 B <- 'b'+
-                 C <- 'c'+
-                 D <- 'd'+
-              """
-  assert($g2 == "((A B) / (C D))")
-  assert match("cccccdddddd", g2)
-  assert("var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2") ==
-         "var1<-keykey; var2<-key2key2")
-  assert("var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2") ==
-         "$1<-$2$2; $1<-$2$2")
-  assert "var1=key; var2=key2".endsWith(peg"{\ident}'='{\ident}")
-
-  if "aaaaaa" =~ peg"'aa' !. / ({'a'})+":
-    assert matches[0] == "a"
-  else:
-    assert false
-
-  if match("abcdefg", peg"c {d} ef {g}", matches, 2):
-    assert matches[0] == "d"
-    assert matches[1] == "g"
-  else:
-    assert false
-
-  for x in findAll("abcdef", peg".", 3):
-    echo x
-
-  for x in findAll("abcdef", peg"^{.}", 3):
-    assert x == "d"
-    
-  if "f(a, b)" =~ peg"{[0-9]+} / ({\ident} '(' {@} ')')":
-    assert matches[0] == "f"
-    assert matches[1] == "a, b"
-  else:
-    assert false
-  
-  assert match("eine übersicht und außerdem", peg"(\letter \white*)+")
-  # ß is not a lower cased letter?!
-  assert match("eine übersicht und auerdem", peg"(\lower \white*)+")
-  assert match("EINE ÜBERSICHT UND AUSSERDEM", peg"(\upper \white*)+")
-  assert(not match("456678", peg"(\letter)+"))
-
-  assert("var1 = key; var2 = key2".replacef(
-    peg"\skip(\s*) {\ident}'='{\ident}", "$1<-$2$2") ==
-         "var1<-keykey;var2<-key2key2")
-
-  assert match("prefix/start", peg"^start$", 7)
-
diff --git a/lib/pure/poly.nim b/lib/pure/poly.nim
index 286e5a8fd..58dcdc1ad 100644
--- a/lib/pure/poly.nim
+++ b/lib/pure/poly.nim
@@ -58,7 +58,7 @@ proc `[]=` *(p:var Poly;idx:int,v:float)=
     
       
 iterator items*(p:Poly):float=
-  ## Iterates through the corfficients of the polynomial.
+  ## Iterates through the coefficients of the polynomial.
   var i=p.degree
   while i>=0:
     yield p[i]
diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim
new file mode 100644
index 000000000..3b68a2381
--- /dev/null
+++ b/lib/pure/rationals.nim
@@ -0,0 +1,289 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Dennis Felsing
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+
+## This module implements rational numbers, consisting of a numerator `num` and
+## a denominator `den`, both of type int. The denominator can not be 0.
+
+import math
+import hashes
+
+type Rational*[T] = object
+  ## a rational number, consisting of a numerator and denominator
+  num*, den*: T
+
+proc initRational*[T](num, den: T): Rational[T] =
+  ## Create a new rational number.
+  result.num = num
+  result.den = den
+
+proc `//`*[T](num, den: T): Rational[T] = initRational[T](num, den)
+  ## A friendlier version of `initRational`. Example usage:
+  ##
+  ## .. code-block:: nim
+  ##   var x = 1//3 + 1//5
+
+proc `$`*[T](x: Rational[T]): string =
+  ## Turn a rational number into a string.
+  result = $x.num & "/" & $x.den
+
+proc toRational*[T](x: T): Rational[T] =
+  ## Convert some integer `x` to a rational number.
+  result.num = x
+  result.den = 1
+
+proc toFloat*[T](x: Rational[T]): float =
+  ## Convert a rational number `x` to a float.
+  x.num / x.den
+
+proc toInt*[T](x: Rational[T]): int =
+  ## Convert a rational number `x` to an int. Conversion rounds towards 0 if
+  ## `x` does not contain an integer value.
+  x.num div x.den
+
+proc reduce*[T](x: var Rational[T]) =
+  ## Reduce rational `x`.
+  let common = gcd(x.num, x.den)
+  if x.den > 0:
+    x.num = x.num div common
+    x.den = x.den div common
+  elif x.den < 0:
+    x.num = -x.num div common
+    x.den = -x.den div common
+  else:
+    raise newException(DivByZeroError, "division by zero")
+
+proc `+` *[T](x, y: Rational[T]): Rational[T] =
+  ## Add two rational numbers.
+  let common = lcm(x.den, y.den)
+  result.num = common div x.den * x.num + common div y.den * y.num
+  result.den = common
+  reduce(result)
+
+proc `+` *[T](x: Rational[T], y: T): Rational[T] =
+  ## Add rational `x` to int `y`.
+  result.num = x.num + y * x.den
+  result.den = x.den
+
+proc `+` *[T](x: T, y: Rational[T]): Rational[T] =
+  ## Add int `x` to rational `y`.
+  result.num = x * y.den + y.num
+  result.den = y.den
+
+proc `+=` *[T](x: var Rational[T], y: Rational[T]) =
+  ## Add rational `y` to rational `x`.
+  let common = lcm(x.den, y.den)
+  x.num = common div x.den * x.num + common div y.den * y.num
+  x.den = common
+  reduce(x)
+
+proc `+=` *[T](x: var Rational[T], y: T) =
+  ## Add int `y` to rational `x`.
+  x.num += y * x.den
+
+proc `-` *[T](x: Rational[T]): Rational[T] =
+  ## Unary minus for rational numbers.
+  result.num = -x.num
+  result.den = x.den
+
+proc `-` *[T](x, y: Rational[T]): Rational[T] =
+  ## Subtract two rational numbers.
+  let common = lcm(x.den, y.den)
+  result.num = common div x.den * x.num - common div y.den * y.num
+  result.den = common
+  reduce(result)
+
+proc `-` *[T](x: Rational[T], y: T): Rational[T] =
+  ## Subtract int `y` from rational `x`.
+  result.num = x.num - y * x.den
+  result.den = x.den
+
+proc `-` *[T](x: T, y: Rational[T]): Rational[T] =
+  ## Subtract rational `y` from int `x`.
+  result.num = - x * y.den + y.num
+  result.den = y.den
+
+proc `-=` *[T](x: var Rational[T], y: Rational[T]) =
+  ## Subtract rational `y` from rational `x`.
+  let common = lcm(x.den, y.den)
+  x.num = common div x.den * x.num - common div y.den * y.num
+  x.den = common
+  reduce(x)
+
+proc `-=` *[T](x: var Rational[T], y: T) =
+  ## Subtract int `y` from rational `x`.
+  x.num -= y * x.den
+
+proc `*` *[T](x, y: Rational[T]): Rational[T] =
+  ## Multiply two rational numbers.
+  result.num = x.num * y.num
+  result.den = x.den * y.den
+  reduce(result)
+
+proc `*` *[T](x: Rational[T], y: T): Rational[T] =
+  ## Multiply rational `x` with int `y`.
+  result.num = x.num * y
+  result.den = x.den
+  reduce(result)
+
+proc `*` *[T](x: T, y: Rational[T]): Rational[T] =
+  ## Multiply int `x` with rational `y`.
+  result.num = x * y.num
+  result.den = y.den
+  reduce(result)
+
+proc `*=` *[T](x: var Rational[T], y: Rational[T]) =
+  ## Multiply rationals `y` to `x`.
+  x.num *= y.num
+  x.den *= y.den
+  reduce(x)
+
+proc `*=` *[T](x: var Rational[T], y: T) =
+  ## Multiply int `y` to rational `x`.
+  x.num *= y
+  reduce(x)
+
+proc reciprocal*[T](x: Rational[T]): Rational[T] =
+  ## Calculate the reciprocal of `x`. (1/x)
+  if x.num > 0:
+    result.num = x.den
+    result.den = x.num
+  elif x.num < 0:
+    result.num = -x.den
+    result.den = -x.num
+  else:
+    raise newException(DivByZeroError, "division by zero")
+
+proc `/`*[T](x, y: Rational[T]): Rational[T] =
+  ## Divide rationals `x` by `y`.
+  result.num = x.num * y.den
+  result.den = x.den * y.num
+  reduce(result)
+
+proc `/`*[T](x: Rational[T], y: T): Rational[T] =
+  ## Divide rational `x` by int `y`.
+  result.num = x.num
+  result.den = x.den * y
+  reduce(result)
+
+proc `/`*[T](x: T, y: Rational[T]): Rational[T] =
+  ## Divide int `x` by Rational `y`.
+  result.num = x * y.den
+  result.den = y.num
+  reduce(result)
+
+proc `/=`*[T](x: var Rational[T], y: Rational[T]) =
+  ## Divide rationals `x` by `y` in place.
+  x.num *= y.den
+  x.den *= y.num
+  reduce(x)
+
+proc `/=`*[T](x: var Rational[T], y: T) =
+  ## Divide rational `x` by int `y` in place.
+  x.den *= y
+  reduce(x)
+
+proc cmp*(x, y: Rational): int {.procvar.} =
+  ## Compares two rationals.
+  (x - y).num
+
+proc `<` *(x, y: Rational): bool =
+  (x - y).num < 0
+
+proc `<=` *(x, y: Rational): bool =
+  (x - y).num <= 0
+
+proc `==` *(x, y: Rational): bool =
+  (x - y).num == 0
+
+proc abs*[T](x: Rational[T]): Rational[T] =
+  result.num = abs x.num
+  result.den = abs x.den
+
+proc hash*[T](x: Rational[T]): THash =
+  ## Computes hash for rational `x`
+  # reduce first so that hash(x) == hash(y) for x == y
+  var copy = x
+  reduce(copy)
+
+  var h: THash = 0
+  h = h !& hash(copy.num)
+  h = h !& hash(copy.den)
+  result = !$h
+  
+when isMainModule:
+  var
+    z = Rational[int](num: 0, den: 1)
+    o = initRational(num=1, den=1)
+    a = initRational(1, 2)
+    b = -1 // -2
+    m1 = -1 // 1
+    tt = 10 // 2
+
+  assert( a     == a )
+  assert( (a-a) == z )
+  assert( (a+b) == o )
+  assert( (a/b) == o )
+  assert( (a*b) == 1 // 4 )
+  assert( (3/a) == 6 // 1 )
+  assert( (a/3) == 1 // 6 )
+  assert( a*b   == 1 // 4 )
+  assert( tt*z  == z )
+  assert( 10*a  == tt )
+  assert( a*10  == tt )
+  assert( tt/10 == a  )
+  assert( a-m1  == 3 // 2 )
+  assert( a+m1  == -1 // 2 )
+  assert( m1+tt == 16 // 4 )
+  assert( m1-tt == 6 // -1 )
+
+  assert( z < o )
+  assert( z <= o )
+  assert( z == z )
+  assert( cmp(z, o) < 0 )
+  assert( cmp(o, z) > 0 )
+
+  assert( o == o )
+  assert( o >= o )
+  assert( not(o > o) )
+  assert( cmp(o, o) == 0 )
+  assert( cmp(z, z) == 0 )
+  assert( hash(o) == hash(o) )
+
+  assert( a == b )
+  assert( a >= b )
+  assert( not(b > a) )
+  assert( cmp(a, b) == 0 )
+  assert( hash(a) == hash(b) )
+
+  var x = 1//3
+
+  x *= 5//1
+  assert( x == 5//3 )
+  x += 2 // 9
+  assert( x == 17//9 )
+  x -= 9//18
+  assert( x == 25//18 )
+  x /= 1//2
+  assert( x == 50//18 )
+
+  var y = 1//3
+
+  y *= 4
+  assert( y == 4//3 )
+  y += 5
+  assert( y == 19//3 )
+  y -= 2
+  assert( y == 13//3 )
+  y /= 9
+  assert( y == 13//27 )
+
+  assert toRational(5) == 5//1
+  assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
+  assert toInt(z) == 0
diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim
index 62a011999..a30c23ada 100644
--- a/lib/pure/rawsockets.nim
+++ b/lib/pure/rawsockets.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -39,6 +39,9 @@ export
   SO_KEEPALIVE, SO_OOBINLINE, SO_REUSEADDR,
   MSG_PEEK
 
+when defined(macosx):
+    export SO_NOSIGPIPE
+
 type
   Port* = distinct uint16  ## port type
   
diff --git a/lib/pure/rawsockets.pretty.nim b/lib/pure/rawsockets.pretty.nim
deleted file mode 100644
index 46bfba9e7..000000000
--- a/lib/pure/rawsockets.pretty.nim
+++ /dev/null
@@ -1,426 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module implements a low-level cross-platform sockets interface. Look
-## at the ``net`` module for the higher-level version.
-
-# TODO: Clean up the exports a bit and everything else in general.
-
-import unsigned, os
-
-when hostOS == "solaris":
-  {.passl: "-lsocket -lnsl".}
-
-const useWinVersion = defined(Windows) or defined(nimdoc)
-
-when useWinVersion:
-  import winlean
-  export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
-         WSAEDISCON, ERROR_NETNAME_DELETED
-else:
-  import posix
-  export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL,
-    EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET
-
-export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen,
-  inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto
-
-export
-  SO_ERROR,
-  SOL_SOCKET,
-  SOMAXCONN,
-  SO_ACCEPTCONN, SO_BROADCAST, SO_DEBUG, SO_DONTROUTE,
-  SO_KEEPALIVE, SO_OOBINLINE, SO_REUSEADDR,
-  MSG_PEEK
-
-type
-  Port* = distinct uint16  ## port type
-  
-  Domain* = enum    ## domain, which specifies the protocol family of the
-                    ## created socket. Other domains than those that are listed
-                    ## here are unsupported.
-    AF_UNIX,        ## for local socket (using a file). Unsupported on Windows.
-    AF_INET = 2,    ## for network protocol IPv4 or
-    AF_INET6 = 23   ## for network protocol IPv6.
-
-  SockType* = enum     ## second argument to `socket` proc
-    SOCK_STREAM = 1,   ## reliable stream-oriented service or Stream Sockets
-    SOCK_DGRAM = 2,    ## datagram service or Datagram Sockets
-    SOCK_RAW = 3,      ## raw protocols atop the network layer.
-    SOCK_SEQPACKET = 5 ## reliable sequenced packet service
-
-  Protocol* = enum      ## third argument to `socket` proc
-    IPPROTO_TCP = 6,    ## Transmission control protocol. 
-    IPPROTO_UDP = 17,   ## User datagram protocol.
-    IPPROTO_IP,         ## Internet protocol. Unsupported on Windows.
-    IPPROTO_IPV6,       ## Internet Protocol Version 6. Unsupported on Windows.
-    IPPROTO_RAW,        ## Raw IP Packets Protocol. Unsupported on Windows.
-    IPPROTO_ICMP        ## Control message protocol. Unsupported on Windows.
-
-  Servent* = object ## information about a service
-    name*: string
-    aliases*: seq[string]
-    port*: Port
-    proto*: string
-
-  Hostent* = object ## information about a given host
-    name*: string
-    aliases*: seq[string]
-    addrtype*: Domain
-    length*: int
-    addrList*: seq[string]
-
-{.deprecated: [TPort: Port, TDomain: Domain, TType: SockType,
-    TProtocol: Protocol, TServent: Servent, THostent: Hostent].}
-
-when useWinVersion:
-  let
-    osInvalidSocket* = winlean.INVALID_SOCKET
-
-  const
-    IOCPARM_MASK* = 127
-    IOC_IN* = int(-2147483648)
-    FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or 
-                             (102 shl 8) or 126
-
-  proc ioctlsocket*(s: SocketHandle, cmd: clong, 
-                   argptr: ptr clong): cint {.
-                   stdcall, importc: "ioctlsocket", dynlib: "ws2_32.dll".}
-else:
-  let
-    osInvalidSocket* = posix.INVALID_SOCKET
-
-proc `==`*(a, b: Port): bool {.borrow.}
-  ## ``==`` for ports.
-
-proc `$`*(p: Port): string {.borrow.}
-  ## returns the port number as a string
-
-proc toInt*(domain: Domain): cint
-  ## Converts the TDomain enum to a platform-dependent ``cint``.
-
-proc toInt*(typ: SockType): cint
-  ## Converts the TType enum to a platform-dependent ``cint``.
-
-proc toInt*(p: Protocol): cint
-  ## Converts the TProtocol enum to a platform-dependent ``cint``.
-
-when not useWinVersion:
-  proc toInt(domain: Domain): cint =
-    case domain
-    of AF_UNIX:        result = posix.AF_UNIX
-    of AF_INET:        result = posix.AF_INET
-    of AF_INET6:       result = posix.AF_INET6
-    else: discard
-
-  proc toInt(typ: SockType): cint =
-    case typ
-    of SOCK_STREAM:    result = posix.SOCK_STREAM
-    of SOCK_DGRAM:     result = posix.SOCK_DGRAM
-    of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET
-    of SOCK_RAW:       result = posix.SOCK_RAW
-    else: discard
-
-  proc toInt(p: Protocol): cint =
-    case p
-    of IPPROTO_TCP:    result = posix.IPPROTO_TCP
-    of IPPROTO_UDP:    result = posix.IPPROTO_UDP
-    of IPPROTO_IP:     result = posix.IPPROTO_IP
-    of IPPROTO_IPV6:   result = posix.IPPROTO_IPV6
-    of IPPROTO_RAW:    result = posix.IPPROTO_RAW
-    of IPPROTO_ICMP:   result = posix.IPPROTO_ICMP
-    else: discard
-
-else:
-  proc toInt(domain: Domain): cint = 
-    result = toU16(ord(domain))
-
-  proc toInt(typ: SockType): cint =
-    result = cint(ord(typ))
-  
-  proc toInt(p: Protocol): cint =
-    result = cint(ord(p))
-
-
-proc newRawSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
-             protocol: Protocol = IPPROTO_TCP): SocketHandle =
-  ## Creates a new socket; returns `InvalidSocket` if an error occurs.
-  socket(toInt(domain), toInt(typ), toInt(protocol))
-
-proc close*(socket: SocketHandle) =
-  ## closes a socket.
-  when useWinVersion:
-    discard winlean.closesocket(socket)
-  else:
-    discard posix.close(socket)
-  # TODO: These values should not be discarded. An EOS should be raised.
-  # http://stackoverflow.com/questions/12463473/what-happens-if-you-call-close-on-a-bsd-socket-multiple-times
-
-proc bindAddr*(socket: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint =
-  result = bindSocket(socket, name, namelen)
-
-proc listen*(socket: SocketHandle, backlog = SOMAXCONN): cint {.tags: [ReadIOEffect].} =
-  ## Marks ``socket`` as accepting connections. 
-  ## ``Backlog`` specifies the maximum length of the 
-  ## queue of pending connections.
-  when useWinVersion:
-    result = winlean.listen(socket, cint(backlog))
-  else:
-    result = posix.listen(socket, cint(backlog))
-
-proc getAddrInfo*(address: string, port: Port, af: Domain = AF_INET, typ: SockType = SOCK_STREAM,
-                 prot: Protocol = IPPROTO_TCP): ptr AddrInfo =
-  ##
-  ##
-  ## **Warning**: The resulting ``ptr TAddrInfo`` must be freed using ``dealloc``!
-  var hints: AddrInfo
-  result = nil
-  hints.ai_family = toInt(af)
-  hints.ai_socktype = toInt(typ)
-  hints.ai_protocol = toInt(prot)
-  var gaiResult = getaddrinfo(address, $port, addr(hints), result)
-  if gaiResult != 0'i32:
-    when useWinVersion:
-      raiseOSError(osLastError())
-    else:
-      raise newException(OSError, $gai_strerror(gaiResult))
-
-proc dealloc*(ai: ptr AddrInfo) =
-  freeaddrinfo(ai)
-
-proc ntohl*(x: int32): int32 = 
-  ## Converts 32-bit integers from network to host byte order.
-  ## On machines where the host byte order is the same as network byte order,
-  ## this is a no-op; otherwise, it performs a 4-byte swap operation.
-  when cpuEndian == bigEndian: result = x
-  else: result = (x shr 24'i32) or
-                 (x shr 8'i32 and 0xff00'i32) or
-                 (x shl 8'i32 and 0xff0000'i32) or
-                 (x shl 24'i32)
-
-proc ntohs*(x: int16): int16 =
-  ## Converts 16-bit integers from network to host byte order. On machines
-  ## where the host byte order is the same as network byte order, this is
-  ## a no-op; otherwise, it performs a 2-byte swap operation.
-  when cpuEndian == bigEndian: result = x
-  else: result = (x shr 8'i16) or (x shl 8'i16)
-
-proc htonl*(x: int32): int32 =
-  ## Converts 32-bit integers from host to network byte order. On machines
-  ## where the host byte order is the same as network byte order, this is
-  ## a no-op; otherwise, it performs a 4-byte swap operation.
-  result = rawsockets.ntohl(x)
-
-proc htons*(x: int16): int16 =
-  ## Converts 16-bit positive integers from host to network byte order.
-  ## On machines where the host byte order is the same as network byte
-  ## order, this is a no-op; otherwise, it performs a 2-byte swap operation.
-  result = rawsockets.ntohs(x)
-
-proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
-  ## Searches the database from the beginning and finds the first entry for 
-  ## which the service name specified by ``name`` matches the s_name member
-  ## and the protocol name specified by ``proto`` matches the s_proto member.
-  ##
-  ## On posix this will search through the ``/etc/services`` file.
-  when useWinVersion:
-    var s = winlean.getservbyname(name, proto)
-  else:
-    var s = posix.getservbyname(name, proto)
-  if s == nil: raise newException(OSError, "Service not found.")
-  result.name = $s.s_name
-  result.aliases = cstringArrayToSeq(s.s_aliases)
-  result.port = Port(s.s_port)
-  result.proto = $s.s_proto
-  
-proc getServByPort*(port: Port, proto: string): Servent {.tags: [ReadIOEffect].} = 
-  ## Searches the database from the beginning and finds the first entry for 
-  ## which the port specified by ``port`` matches the s_port member and the 
-  ## protocol name specified by ``proto`` matches the s_proto member.
-  ##
-  ## On posix this will search through the ``/etc/services`` file.
-  when useWinVersion:
-    var s = winlean.getservbyport(ze(int16(port)).cint, proto)
-  else:
-    var s = posix.getservbyport(ze(int16(port)).cint, proto)
-  if s == nil: raise newException(OSError, "Service not found.")
-  result.name = $s.s_name
-  result.aliases = cstringArrayToSeq(s.s_aliases)
-  result.port = Port(s.s_port)
-  result.proto = $s.s_proto
-
-proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
-  ## This function will lookup the hostname of an IP Address.
-  var myaddr: InAddr
-  myaddr.s_addr = inet_addr(ip)
-  
-  when useWinVersion:
-    var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
-                                  cint(rawsockets.AF_INET))
-    if s == nil: raiseOSError(osLastError())
-  else:
-    var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen, 
-                                cint(posix.AF_INET))
-    if s == nil:
-      raise newException(OSError, $hstrerror(h_errno))
-  
-  result.name = $s.h_name
-  result.aliases = cstringArrayToSeq(s.h_aliases)
-  when useWinVersion:
-    result.addrtype = Domain(s.h_addrtype)
-  else:
-    if s.h_addrtype == posix.AF_INET:
-      result.addrtype = AF_INET
-    elif s.h_addrtype == posix.AF_INET6:
-      result.addrtype = AF_INET6
-    else:
-      raise newException(OSError, "unknown h_addrtype")
-  result.addrList = cstringArrayToSeq(s.h_addr_list)
-  result.length = int(s.h_length)
-
-proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} = 
-  ## This function will lookup the IP address of a hostname.
-  when useWinVersion:
-    var s = winlean.gethostbyname(name)
-  else:
-    var s = posix.gethostbyname(name)
-  if s == nil: raiseOSError(osLastError())
-  result.name = $s.h_name
-  result.aliases = cstringArrayToSeq(s.h_aliases)
-  when useWinVersion:
-    result.addrtype = Domain(s.h_addrtype)
-  else:
-    if s.h_addrtype == posix.AF_INET:
-      result.addrtype = AF_INET
-    elif s.h_addrtype == posix.AF_INET6:
-      result.addrtype = AF_INET6
-    else:
-      raise newException(OSError, "unknown h_addrtype")
-  result.addrList = cstringArrayToSeq(s.h_addr_list)
-  result.length = int(s.h_length)
-
-proc getSockName*(socket: SocketHandle): Port = 
-  ## returns the socket's associated port number.
-  var name: Sockaddr_in
-  when useWinVersion:
-    name.sin_family = int16(ord(AF_INET))
-  else:
-    name.sin_family = posix.AF_INET
-  #name.sin_port = htons(cint16(port))
-  #name.sin_addr.s_addr = htonl(INADDR_ANY)
-  var namelen = sizeof(name).SockLen
-  if getsockname(socket, cast[ptr SockAddr](addr(name)),
-                 addr(namelen)) == -1'i32:
-    raiseOSError(osLastError())
-  result = Port(rawsockets.ntohs(name.sin_port))
-
-proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {.
-  tags: [ReadIOEffect].} = 
-  ## getsockopt for integer options.
-  var res: cint
-  var size = sizeof(res).SockLen
-  if getsockopt(socket, cint(level), cint(optname), 
-                addr(res), addr(size)) < 0'i32:
-    raiseOSError(osLastError())
-  result = int(res)
-
-proc setSockOptInt*(socket: SocketHandle, level, optname, optval: int) {.
-  tags: [WriteIOEffect].} =
-  ## setsockopt for integer options.
-  var value = cint(optval)
-  if setsockopt(socket, cint(level), cint(optname), addr(value),  
-                sizeof(value).SockLen) < 0'i32:
-    raiseOSError(osLastError())
-
-proc setBlocking*(s: SocketHandle, blocking: bool) =
-  ## Sets blocking mode on socket.
-  ##
-  ## Raises EOS on error.
-  when useWinVersion:
-    var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking
-    if ioctlsocket(s, FIONBIO, addr(mode)) == -1:
-      raiseOSError(osLastError())
-  else: # BSD sockets
-    var x: int = fcntl(s, F_GETFL, 0)
-    if x == -1:
-      raiseOSError(osLastError())
-    else:
-      var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK
-      if fcntl(s, F_SETFL, mode) == -1:
-        raiseOSError(osLastError())
-
-proc timeValFromMilliseconds(timeout = 500): Timeval =
-  if timeout != -1:
-    var seconds = timeout div 1000
-    result.tv_sec = seconds.int32
-    result.tv_usec = ((timeout - seconds * 1000) * 1000).int32
-
-proc createFdSet(fd: var FdSet, s: seq[SocketHandle], m: var int) = 
-  FD_ZERO(fd)
-  for i in items(s): 
-    m = max(m, int(i))
-    fdSet(i, fd)
-   
-proc pruneSocketSet(s: var seq[SocketHandle], fd: var FdSet) = 
-  var i = 0
-  var L = s.len
-  while i < L:
-    if FD_ISSET(s[i], fd) == 0'i32:
-      s[i] = s[L-1]
-      dec(L)
-    else:
-      inc(i)
-  setLen(s, L)
-
-proc select*(readfds: var seq[SocketHandle], timeout = 500): int =
-  ## Traditional select function. This function will return the number of
-  ## sockets that are ready to be read from, written to, or which have errors.
-  ## If there are none; 0 is returned. 
-  ## ``Timeout`` is in miliseconds and -1 can be specified for no timeout.
-  ## 
-  ## A socket is removed from the specific ``seq`` when it has data waiting to
-  ## be read/written to or has errors (``exceptfds``).
-  var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout)
-  
-  var rd: FdSet
-  var m = 0
-  createFdSet((rd), readfds, m)
-  
-  if timeout != -1:
-    result = int(select(cint(m+1), addr(rd), nil, nil, addr(tv)))
-  else:
-    result = int(select(cint(m+1), addr(rd), nil, nil, nil))
-  
-  pruneSocketSet(readfds, (rd))
-
-proc selectWrite*(writefds: var seq[SocketHandle],
-                  timeout = 500): int {.tags: [ReadIOEffect].} =
-  ## When a socket in ``writefds`` is ready to be written to then a non-zero
-  ## value will be returned specifying the count of the sockets which can be
-  ## written to. The sockets which can be written to will also be removed
-  ## from ``writefds``.
-  ##
-  ## ``timeout`` is specified in miliseconds and ``-1`` can be specified for
-  ## an unlimited time.
-  var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout)
-  
-  var wr: FdSet
-  var m = 0
-  createFdSet((wr), writefds, m)
-  
-  if timeout != -1:
-    result = int(select(cint(m+1), nil, addr(wr), nil, addr(tv)))
-  else:
-    result = int(select(cint(m+1), nil, addr(wr), nil, nil))
-  
-  pruneSocketSet(writefds, (wr))
-
-when defined(Windows):
-  var wsa: WSAData
-  if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError())
diff --git a/lib/pure/redis.nim b/lib/pure/redis.nim
index 52d81b3a4..aa2e0f9bd 100644
--- a/lib/pure/redis.nim
+++ b/lib/pure/redis.nim
@@ -285,6 +285,30 @@ proc keys*(r: Redis, pattern: string): RedisList =
   r.sendCommand("KEYS", pattern)
   return r.readArray()
 
+proc scan*(r: Redis, cursor: var BiggestInt): RedisList =
+  ## Find all keys matching the given pattern and yield it to client in portions
+  ## using default Redis values for MATCH and COUNT parameters
+  r.sendCommand("SCAN", $cursor)
+  let reply = r.readArray()
+  cursor = strutils.parseBiggestInt(reply[0])
+  return reply[1..high(reply)]
+
+proc scan*(r: Redis, cursor: var BiggestInt, pattern: string): RedisList =
+  ## Find all keys matching the given pattern and yield it to client in portions
+  ## using cursor as a client query identifier. Using default Redis value for COUNT argument
+  r.sendCommand("SCAN", $cursor, ["MATCH", pattern])
+  let reply = r.readArray()
+  cursor = strutils.parseBiggestInt(reply[0])
+  return reply[1..high(reply)]
+
+proc scan*(r: Redis, cursor: var BiggestInt, pattern: string, count: int): RedisList = 
+  ## Find all keys matching the given pattern and yield it to client in portions
+  ## using cursor as a client query identifier.
+  r.sendCommand("SCAN", $cursor, ["MATCH", pattern, "COUNT", $count])
+  let reply = r.readArray()
+  cursor = strutils.parseBiggestInt(reply[0])
+  return reply[1..high(reply)]
+
 proc move*(r: Redis, key: string, db: int): bool =
   ## Move a key to another database. Returns `true` on a successful move.
   r.sendCommand("MOVE", key, $db)
@@ -798,6 +822,22 @@ proc zunionstore*(r: Redis, destination: string, numkeys: string,
   
   return r.readInteger()
 
+# HyperLogLog
+
+proc pfadd*(r: Redis, key: string, elements: varargs[string]): RedisInteger = 
+  ## Add variable number of elements into special 'HyperLogLog' set type
+  r.sendCommand("PFADD", key, elements)
+  return r.readInteger()
+
+proc pfcount*(r: Redis, key: string): RedisInteger =
+  ## Count approximate number of elements in 'HyperLogLog'
+  r.sendCommand("PFCOUNT", key)
+  return r.readInteger()
+
+proc pfmerge*(r: Redis, destination: string, sources: varargs[string]) =
+  ## Merge several source HyperLogLog's into one specified by destKey
+  r.sendCommand("PFMERGE", destination, sources)
+  raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
 # Pub/Sub
 
@@ -1040,7 +1080,7 @@ proc assertListsIdentical(listA, listB: seq[string]) =
     assert(item == listB[i])
     i = i + 1
   
-when isMainModule:
+when not defined(testing) and isMainModule:
   when false:
     var r = open()
 
diff --git a/lib/pure/romans.nim b/lib/pure/romans.nim
index 79fb75526..0c182843a 100644
--- a/lib/pure/romans.nim
+++ b/lib/pure/romans.nim
@@ -44,16 +44,13 @@ proc decimalToRoman*(number: range[1..3_999]): string =
     ("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9),
     ("V", 5), ("IV", 4), ("I", 1)]
   result = ""
-  var decVal = number
+  var decVal: int = number
   for key, val in items(romanComposites):
     while decVal >= val:
       dec(decVal, val)
       result.add(key)
 
 when isMainModule:
-  import math
-  randomize()
-  for i in 1 .. 100:
-    var rnd = 1 + random(3990)
-    assert rnd == rnd.decimalToRoman.romanToDecimal
+  for i in 1 .. 3_999:
+    assert i == i.decimalToRoman.romanToDecimal
 
diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim
index 995dff2aa..5c7fedfe3 100644
--- a/lib/pure/ropes.nim
+++ b/lib/pure/ropes.nim
@@ -43,7 +43,7 @@ proc isConc(r: Rope): bool {.inline.} = return isNil(r.data)
 # Note that the left and right pointers are not needed for leafs.
 # Leaves have relatively high memory overhead (~30 bytes on a 32
 # bit machine) and we produce many of them. This is why we cache and
-# share leafs accross different rope trees.
+# share leafs across different rope trees.
 # To cache them they are inserted in another tree, a splay tree for best
 # performance. But for the caching tree we use the leaf's left and right
 # pointers.
@@ -52,9 +52,9 @@ proc len*(a: Rope): int {.rtl, extern: "nro$1".} =
   ## the rope's length
   if a == nil: result = 0
   else: result = a.length
-  
+
 proc newRope(): Rope = new(result)
-proc newRope(data: string): Rope = 
+proc newRope(data: string): Rope =
   new(result)
   result.length = len(data)
   result.data = data
@@ -65,18 +65,18 @@ var
 
 when countCacheMisses:
   var misses, hits: int
-  
-proc splay(s: string, tree: Rope, cmpres: var int): Rope = 
+
+proc splay(s: string, tree: Rope, cmpres: var int): Rope =
   var c: int
   var t = tree
   N.left = nil
   N.right = nil               # reset to nil
   var le = N
   var r = N
-  while true: 
+  while true:
     c = cmp(s, t.data)
-    if c < 0: 
-      if (t.left != nil) and (s < t.left.data): 
+    if c < 0:
+      if (t.left != nil) and (s < t.left.data):
         var y = t.left
         t.left = y.right
         y.right = t
@@ -85,8 +85,8 @@ proc splay(s: string, tree: Rope, cmpres: var int): Rope =
       r.left = t
       r = t
       t = t.left
-    elif c > 0: 
-      if (t.right != nil) and (s > t.right.data): 
+    elif c > 0:
+      if (t.right != nil) and (s > t.right.data):
         var y = t.right
         t.right = y.left
         y.left = t
@@ -95,8 +95,8 @@ proc splay(s: string, tree: Rope, cmpres: var int): Rope =
       le.right = t
       le = t
       t = t.right
-    else: 
-      break 
+    else:
+      break
   cmpres = c
   le.right = t.left
   r.left = t.right
@@ -104,50 +104,50 @@ proc splay(s: string, tree: Rope, cmpres: var int): Rope =
   t.right = N.left
   result = t
 
-proc insertInCache(s: string, tree: Rope): Rope = 
+proc insertInCache(s: string, tree: Rope): Rope =
   var t = tree
-  if t == nil: 
+  if t == nil:
     result = newRope(s)
     when countCacheMisses: inc(misses)
     return 
   var cmp: int
   t = splay(s, t, cmp)
-  if cmp == 0: 
+  if cmp == 0:
     # We get here if it's already in the Tree
     # Don't add it again
     result = t
     when countCacheMisses: inc(hits)
-  else: 
+  else:
     when countCacheMisses: inc(misses)
     result = newRope(s)
-    if cmp < 0: 
+    if cmp < 0:
       result.left = t.left
       result.right = t
       t.left = nil
-    else: 
+    else:
       # i > t.item:
       result.right = t.right
       result.left = t
       t.right = nil
 
 proc rope*(s: string): Rope {.rtl, extern: "nro$1Str".} =
-  ## Converts a string to a rope. 
-  if s.len == 0: 
+  ## Converts a string to a rope.
+  if s.len == 0:
     result = nil
-  elif cacheEnabled: 
+  elif cacheEnabled:
     result = insertInCache(s, cache)
     cache = result
-  else: 
+  else:
     result = newRope(s)
-  
-proc rope*(i: BiggestInt): Rope {.rtl, extern: "nro$1BiggestInt".} = 
-  ## Converts an int to a rope. 
+
+proc rope*(i: BiggestInt): Rope {.rtl, extern: "nro$1BiggestInt".} =
+  ## Converts an int to a rope.
   result = rope($i)
 
 proc rope*(f: BiggestFloat): Rope {.rtl, extern: "nro$1BiggestFloat".} =
-  ## Converts a float to a rope. 
+  ## Converts a float to a rope.
   result = rope($f)
-  
+
 proc enableCache*() {.rtl, extern: "nro$1".} =
   ## Enables the caching of leaves. This reduces the memory footprint at
   ## the cost of runtime efficiency.
@@ -160,9 +160,9 @@ proc disableCache*() {.rtl, extern: "nro$1".} =
 
 proc `&`*(a, b: Rope): Rope {.rtl, extern: "nroConcRopeRope".} =
   ## the concatenation operator for ropes.
-  if a == nil: 
+  if a == nil:
     result = b
-  elif b == nil: 
+  elif b == nil:
     result = a
   else:
     result = newRope()
@@ -177,16 +177,16 @@ proc `&`*(a, b: Rope): Rope {.rtl, extern: "nroConcRopeRope".} =
     else:
       result.left = a
       result.right = b
-  
-proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} = 
+
+proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} =
   ## the concatenation operator for ropes.
   result = a & rope(b)
-  
-proc `&`*(a: string, b: Rope): Rope {.rtl, extern: "nroConcStrRope".} = 
+
+proc `&`*(a: string, b: Rope): Rope {.rtl, extern: "nroConcStrRope".} =
   ## the concatenation operator for ropes.
   result = rope(a) & b
-  
-proc `&`*(a: openArray[Rope]): Rope {.rtl, extern: "nroConcOpenArray".} = 
+
+proc `&`*(a: openArray[Rope]): Rope {.rtl, extern: "nroConcOpenArray".} =
   ## the concatenation operator for an openarray of ropes.
   for i in countup(0, high(a)): result = result & a[i]
 
@@ -219,7 +219,7 @@ iterator leaves*(r: Rope): string =
   ## iterates over any leaf string in the rope `r`.
   if r != nil:
     var stack = @[r]
-    while stack.len > 0: 
+    while stack.len > 0:
       var it = stack.pop
       while isConc(it):
         stack.add(it.right)
@@ -227,7 +227,7 @@ iterator leaves*(r: Rope): string =
         assert(it != nil)
       assert(it.data != nil)
       yield it.data
-  
+
 iterator items*(r: Rope): char =
   ## iterates over any character in the rope `r`.
   for s in leaves(r):
@@ -237,7 +237,7 @@ proc write*(f: File, r: Rope) {.rtl, extern: "nro$1".} =
   ## writes a rope to a file.
   for s in leaves(r): write(f, s)
 
-proc `$`*(r: Rope): string  {.rtl, extern: "nroToString".}= 
+proc `$`*(r: Rope): string  {.rtl, extern: "nroToString".}=
   ## converts a rope back to a string.
   result = newString(r.len)
   setLen(result, 0)
@@ -251,25 +251,25 @@ when false:
     new(result)
     result.length = -idx
   
-  proc compileFrmt(frmt: string): Rope = 
+  proc compileFrmt(frmt: string): Rope =
     var i = 0
     var length = len(frmt)
     result = nil
     var num = 0
-    while i < length: 
-      if frmt[i] == '$': 
+    while i < length:
+      if frmt[i] == '$':
         inc(i)
         case frmt[i]
-        of '$': 
+        of '$':
           add(result, "$")
           inc(i)
-        of '#': 
+        of '#':
           inc(i)
           add(result, compiledArg(num+1))
           inc(num)
-        of '0'..'9': 
+        of '0'..'9':
           var j = 0
-          while true: 
+          while true:
             j = j * 10 + ord(frmt[i]) - ord('0')
             inc(i)
             if frmt[i] notin {'0'..'9'}: break 
@@ -285,13 +285,13 @@ when false:
           add(s, compiledArg(j))
         else: raise newException(EInvalidValue, "invalid format string")
       var start = i
-      while i < length: 
+      while i < length:
         if frmt[i] != '$': inc(i)
-        else: break 
-      if i - 1 >= start: 
+        else: break
+      if i - 1 >= start:
         add(result, substr(frmt, start, i-1))
-  
-proc `%`*(frmt: string, args: openArray[Rope]): Rope {. 
+
+proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
   rtl, extern: "nroFormat".} =
   ## `%` substitution operator for ropes. Does not support the ``$identifier``
   ## nor ``${identifier}`` notations.
@@ -299,23 +299,23 @@ proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
   var length = len(frmt)
   result = nil
   var num = 0
-  while i < length: 
-    if frmt[i] == '$': 
+  while i < length:
+    if frmt[i] == '$':
       inc(i)
       case frmt[i]
-      of '$': 
+      of '$':
         add(result, "$")
         inc(i)
-      of '#': 
+      of '#':
         inc(i)
         add(result, args[num])
         inc(num)
-      of '0'..'9': 
+      of '0'..'9':
         var j = 0
-        while true: 
+        while true:
           j = j * 10 + ord(frmt[i]) - ord('0')
           inc(i)
-          if frmt[i] notin {'0'..'9'}: break 
+          if frmt[i] notin {'0'..'9'}: break
         add(result, args[j-1])
       of '{':
         inc(i)
@@ -325,13 +325,14 @@ proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
           inc(i)
         if frmt[i] == '}': inc(i)
         else: raise newException(ValueError, "invalid format string")
+
         add(result, args[j-1])
       else: raise newException(ValueError, "invalid format string")
     var start = i
-    while i < length: 
+    while i < length:
       if frmt[i] != '$': inc(i)
-      else: break 
-    if i - 1 >= start: 
+      else: break
+    if i - 1 >= start:
       add(result, substr(frmt, start, i - 1))
 
 proc addf*(c: var Rope, frmt: string, args: openArray[Rope]) {.
@@ -339,29 +340,46 @@ proc addf*(c: var Rope, frmt: string, args: openArray[Rope]) {.
   ## shortcut for ``add(c, frmt % args)``.
   add(c, frmt % args)
 
+const
+  bufSize = 1024              # 1 KB is reasonable
+
 proc equalsFile*(r: Rope, f: File): bool {.rtl, extern: "nro$1File".} =
   ## returns true if the contents of the file `f` equal `r`.
-  var bufSize = 1024 # reasonable start value
-  var buf = alloc(bufSize)
+  var 
+    buf: array[bufSize, char]
+    bpos = buf.len
+    blen = buf.len
+
   for s in leaves(r):
-    if s.len > bufSize:
-      bufSize = max(bufSize * 2, s.len)
-      buf = realloc(buf, bufSize)
-    var readBytes = readBuffer(f, buf, s.len)
-    result = readBytes == s.len and equalMem(buf, cstring(s), s.len)
-    if not result: break
-  if result:
-    result = readBuffer(f, buf, 1) == 0 # really at the end of file?
-  dealloc(buf)
+    var spos = 0
+    let slen = s.len
+    while spos < slen:
+      if bpos == blen:
+        # Read more data
+        bpos = 0
+        blen = readBuffer(f, addr(buf[0]), buf.len)
+        if blen == 0:  # no more data in file
+          result = false
+          return
+      let n = min(blen - bpos, slen - spos)
+      # TODO There's gotta be a better way of comparing here...
+      if not equalMem(addr(buf[bpos]), 
+                      cast[pointer](cast[int](cstring(s))+spos), n):
+        result = false
+        return
+      spos += n
+      bpos += n
+
+  result = readBuffer(f, addr(buf[0]), 1) == 0  # check that we've read all
 
-proc equalsFile*(r: Rope, f: string): bool {.rtl, extern: "nro$1Str".} =
+proc equalsFile*(r: Rope, filename: string): bool {.rtl, extern: "nro$1Str".} =
   ## returns true if the contents of the file `f` equal `r`. If `f` does not
   ## exist, false is returned.
-  var bin: File
-  result = open(bin, f)
+  var f: File
+  result = open(f, filename)
   if result:
-    result = equalsFile(r, bin)
-    close(bin)
+    result = equalsFile(r, f)
+    close(f)
 
 new(N) # init dummy node for splay algorithm
 
diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim
index 1c988c609..6901ecf58 100644
--- a/lib/pure/selectors.nim
+++ b/lib/pure/selectors.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -23,7 +23,7 @@ proc `$`*(x: SocketHandle): string {.borrow.}
 
 type
   Event* = enum
-    EvRead, EvWrite
+    EvRead, EvWrite, EvError
 
   SelectorKey* = ref object
     fd*: SocketHandle
@@ -35,7 +35,7 @@ type
 when defined(nimdoc):
   type
     Selector* = ref object
-      ## An object which holds file descripters to be checked for read/write
+      ## An object which holds file descriptors to be checked for read/write
       ## status.
       fds: Table[SocketHandle, SelectorKey]
 
@@ -48,12 +48,21 @@ when defined(nimdoc):
                events: set[Event]): SelectorKey {.discardable.} =
     ## Updates the events which ``fd`` wants notifications for.
 
+  proc unregister*(s: Selector, fd: SocketHandle): SelectorKey {.discardable.} =
+    ## Unregisters file descriptor ``fd`` from selector ``s``.
+
+  proc close*(s: Selector) =
+    ## Closes the selector
+
   proc select*(s: Selector, timeout: int): seq[ReadyInfo] =
     ## The ``events`` field of the returned ``key`` contains the original events
     ## for which the ``fd`` was bound. This is contrary to the ``events`` field
     ## of the ``TReadyInfo`` tuple which determines which events are ready
     ## on the ``fd``.
 
+  proc newSelector*(): Selector =
+    ## Creates a new selector
+
   proc contains*(s: Selector, fd: SocketHandle): bool =
     ## Determines whether selector contains a file descriptor.
 
@@ -78,8 +87,6 @@ elif defined(linux):
   
   proc register*(s: Selector, fd: SocketHandle, events: set[Event],
       data: RootRef): SelectorKey {.discardable.} =
-    ## Registers file descriptor ``fd`` to selector ``s`` with a set of TEvent
-    ## ``events``.
     var event = createEventStruct(events, fd)
     if events != {}:
       if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0:
@@ -92,7 +99,6 @@ elif defined(linux):
   
   proc update*(s: Selector, fd: SocketHandle,
       events: set[Event]): SelectorKey {.discardable.} =
-    ## Updates the events which ``fd`` wants notifications for.
     if s.fds[fd].events != events:
       if events == {}:
         # This fd is idle -- it should not be registered to epoll.
@@ -146,12 +152,17 @@ elif defined(linux):
     ## on the ``fd``.
     result = @[]
     let evNum = epoll_wait(s.epollFD, addr s.events[0], 64.cint, timeout.cint)
-    if evNum < 0: raiseOSError(osLastError())
+    if evNum < 0:
+      let err = osLastError()
+      if err.cint == EINTR:
+        return @[]
+      raiseOSError(osLastError())
     if evNum == 0: return @[]
     for i in 0 .. <evNum:
       let fd = s.events[i].data.fd.SocketHandle
     
       var evSet: set[Event] = {}
+      if (s.events[i].events and EPOLLERR) != 0 or (s.events[i].events and EPOLLHUP) != 0: evSet = evSet + {EvError}
       if (s.events[i].events and EPOLLIN) != 0: evSet = evSet + {EvRead}
       if (s.events[i].events and EPOLLOUT) != 0: evSet = evSet + {EvWrite}
       let selectorKey = s.fds[fd]
@@ -199,7 +210,6 @@ elif not defined(nimdoc):
 
   proc update*(s: Selector, fd: SocketHandle,
       events: set[Event]): SelectorKey {.discardable.} =
-    ## Updates the events which ``fd`` wants notifications for.
     if not s.fds.hasKey(fd):
       raise newException(ValueError, "File descriptor not found.")
 
@@ -286,7 +296,7 @@ proc contains*(s: Selector, key: SelectorKey): bool =
    TReadyInfo: ReadyInfo, PSelector: Selector].}
 
 
-when isMainModule and not defined(nimdoc):
+when not defined(testing) and isMainModule and not defined(nimdoc):
   # Select()
   import sockets
   type
@@ -294,7 +304,7 @@ when isMainModule and not defined(nimdoc):
       sock: Socket
   
   var sock = socket()
-  if sock == sockets.InvalidSocket: raiseOSError(osLastError())
+  if sock == sockets.invalidSocket: raiseOSError(osLastError())
   #sock.setBlocking(false)
   sock.connect("irc.freenode.net", Port(6667))
   
diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim
index 26f0c9591..c1bc259a5 100644
--- a/lib/pure/smtp.nim
+++ b/lib/pure/smtp.nim
@@ -238,7 +238,7 @@ proc sendMail*(smtp: AsyncSmtp, fromAddr: string,
   await smtp.sock.send("MAIL FROM:<" & fromAddr & ">\c\L")
   await smtp.checkReply("250")
   for address in items(toAddrs):
-    await smtp.sock.send("RCPT TO:<" & smtp.address & ">\c\L")
+    await smtp.sock.send("RCPT TO:<" & address & ">\c\L")
     await smtp.checkReply("250")
   
   # Send the message
@@ -253,7 +253,7 @@ proc close*(smtp: AsyncSmtp) {.async.} =
   await smtp.sock.send("QUIT\c\L")
   smtp.sock.close()
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   #var msg = createMessage("Test subject!", 
   #     "Hello, my name is dom96.\n What\'s yours?", @["dominik@localhost"])
   #echo(msg)
diff --git a/lib/pure/smtp.nimrod.cfg b/lib/pure/smtp.nim.cfg
index 521e21de4..521e21de4 100644
--- a/lib/pure/smtp.nimrod.cfg
+++ b/lib/pure/smtp.nim.cfg
diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim
index 11eeefcb9..3afb545c8 100644
--- a/lib/pure/sockets.nim
+++ b/lib/pure/sockets.nim
@@ -657,6 +657,8 @@ proc close*(socket: Socket) =
   when defined(ssl):
     if socket.isSSL:
       discard SSLShutdown(socket.sslHandle)
+      SSLFree(socket.sslHandle)
+      socket.sslHandle = nil
 
 proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
   ## Searches the database from the beginning and finds the first entry for 
@@ -851,7 +853,7 @@ proc connectAsync*(socket: Socket, name: string, port = Port(0),
                      af: Domain = AF_INET) {.tags: [ReadIOEffect].} =
   ## A variant of ``connect`` for non-blocking sockets.
   ##
-  ## This procedure will immediatelly return, it will not block until a connection
+  ## This procedure will immediately return, it will not block until a connection
   ## is made. It is up to the caller to make sure the connection has been established
   ## by checking (using ``select``) whether the socket is writeable.
   ##
@@ -1467,7 +1469,7 @@ proc recvAsync*(socket: Socket, s: var TaintedString): bool {.
           of SSL_ERROR_ZERO_RETURN:
             raiseSslError("TLS/SSL connection failed to initiate, socket closed prematurely.")
           of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT:
-            raiseSslError("Unexpected error occured.") # This should just not happen.
+            raiseSslError("Unexpected error occurred.") # This should just not happen.
           of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ:
             return false
           of SSL_ERROR_WANT_X509_LOOKUP:
@@ -1610,7 +1612,7 @@ proc sendAsync*(socket: Socket, data: string): int {.tags: [WriteIOEffect].} =
           of SSL_ERROR_ZERO_RETURN:
             raiseSslError("TLS/SSL connection failed to initiate, socket closed prematurely.")
           of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT:
-            raiseSslError("Unexpected error occured.") # This should just not happen.
+            raiseSslError("Unexpected error occurred.") # This should just not happen.
           of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ:
             return 0
           of SSL_ERROR_WANT_X509_LOOKUP:
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index 31aa7497d..e706f2016 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -122,41 +122,41 @@ proc read[T](s: Stream, result: var T) =
     raise newEIO("cannot read from stream")
 
 proc readChar*(s: Stream): char =
-  ## reads a char from the stream `s`. Raises `EIO` if an error occured.
+  ## reads a char from the stream `s`. Raises `EIO` if an error occurred.
   ## Returns '\0' as an EOF marker.
   if readData(s, addr(result), sizeof(result)) != 1: result = '\0'
 
 proc readBool*(s: Stream): bool = 
-  ## reads a bool from the stream `s`. Raises `EIO` if an error occured.
+  ## reads a bool from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
 proc readInt8*(s: Stream): int8 = 
-  ## reads an int8 from the stream `s`. Raises `EIO` if an error occured.
+  ## reads an int8 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
 proc readInt16*(s: Stream): int16 = 
-  ## reads an int16 from the stream `s`. Raises `EIO` if an error occured.
+  ## reads an int16 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
 proc readInt32*(s: Stream): int32 = 
-  ## reads an int32 from the stream `s`. Raises `EIO` if an error occured.
+  ## reads an int32 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
 proc readInt64*(s: Stream): int64 = 
-  ## reads an int64 from the stream `s`. Raises `EIO` if an error occured.
+  ## reads an int64 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
 proc readFloat32*(s: Stream): float32 = 
-  ## reads a float32 from the stream `s`. Raises `EIO` if an error occured.
+  ## reads a float32 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
 proc readFloat64*(s: Stream): float64 = 
-  ## reads a float64 from the stream `s`. Raises `EIO` if an error occured.
+  ## reads a float64 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
 proc readStr*(s: Stream, length: int): TaintedString = 
   ## reads a string of length `length` from the stream `s`. Raises `EIO` if 
-  ## an error occured.
+  ## an error occurred.
   result = newString(length).TaintedString
   var L = readData(s, addr(string(result)[0]), length)
   if L != length: setLen(result.string, L)
@@ -183,7 +183,7 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
 
 proc readLine*(s: Stream): TaintedString =
   ## Reads a line from a stream `s`. Note: This is not very efficient. Raises 
-  ## `EIO` if an error occured.
+  ## `EIO` if an error occurred.
   result = TaintedString""
   while true:
     var c = readChar(s)
@@ -224,10 +224,12 @@ proc ssReadData(s: Stream, buffer: pointer, bufLen: int): int =
 
 proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) = 
   var s = StringStream(s)
-  if bufLen > 0: 
-    setLen(s.data, s.data.len + bufLen)
-    copyMem(addr(s.data[s.pos]), buffer, bufLen)
-    inc(s.pos, bufLen)
+  if bufLen <= 0:
+    return
+  if s.pos + bufLen > s.data.len:
+    setLen(s.data, s.pos + bufLen)
+  copyMem(addr(s.data[s.pos]), buffer, bufLen)
+  inc(s.pos, bufLen)
 
 proc ssClose(s: Stream) =
   var s = StringStream(s)
@@ -284,7 +286,7 @@ when not defined(js):
   proc newFileStream*(filename: string, mode: FileMode): FileStream =
     ## creates a new stream from the file named `filename` with the mode `mode`.
     ## If the file cannot be opened, nil is returned. See the `system
-    ## <system.html>`_ module for a list of available TFileMode enums.
+    ## <system.html>`_ module for a list of available FileMode enums.
     var f: File
     if open(f, filename, mode): result = newFileStream(f)
 
diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim
index 5b7149d8e..7fdd994f2 100644
--- a/lib/pure/strtabs.nim
+++ b/lib/pure/strtabs.nim
@@ -112,7 +112,7 @@ proc `[]`*(t: StringTableRef, key: string): string {.rtl, extern: "nstGet".} =
 proc mget*(t: StringTableRef, key: string): var string {.
              rtl, extern: "nstTake".} =
   ## retrieves the location at ``t[key]``. If `key` is not in `t`, the
-  ## ``EInvalidKey`` exception is raised.
+  ## ``KeyError`` exception is raised.
   var index = rawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: raise newException(KeyError, "key does not exist: " & key)
@@ -158,7 +158,7 @@ proc getValue(t: StringTableRef, flags: set[FormatFlag], key: string): string =
   else: result = ""
   if result.len == 0:
     if useKey in flags: result = '$' & key
-    elif not (useEmpty in flags): raiseFormatException(key)
+    elif useEmpty notin flags: raiseFormatException(key)
 
 proc newStringTable*(mode: StringTableMode): StringTableRef {.
   rtl, extern: "nst$1".} =
@@ -168,6 +168,12 @@ proc newStringTable*(mode: StringTableMode): StringTableRef {.
   result.counter = 0
   newSeq(result.data, startSize)
 
+proc clear*(s: StringTableRef, mode: StringTableMode) =
+  ## resets a string table to be empty again.
+  s.mode = mode
+  s.counter = 0
+  s.data.setLen(startSize)
+
 proc newStringTable*(keyValuePairs: varargs[string],
                      mode: StringTableMode): StringTableRef {.
   rtl, extern: "nst$1WithPairs".} =
@@ -227,7 +233,7 @@ proc `$`*(t: StringTableRef): string {.rtl, extern: "nstDollar".} =
     result = "{:}"
   else:
     result = "{"
-    for key, val in pairs(t): 
+    for key, val in pairs(t):
       if result.len > 1: result.add(", ")
       result.add(key)
       result.add(": ")
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 4f449cb0e..59cebf7fa 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -386,7 +386,7 @@ proc split*(s: string, sep: string): seq[string] {.noSideEffect,
   ## `split iterator <#split.i,string,string>`_.
   accumulateResult(split(s, sep))
 
-proc toHex*(x: BiggestInt, len: int): string {.noSideEffect,
+proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
   rtl, extern: "nsuToHex".} =
   ## Converts `x` to its hexadecimal representation.
   ##
@@ -395,13 +395,15 @@ proc toHex*(x: BiggestInt, len: int): string {.noSideEffect,
   const
     HexChars = "0123456789ABCDEF"
   var
-    shift: BiggestInt
+    n = x
   result = newString(len)
   for j in countdown(len-1, 0):
-    result[j] = HexChars[toU32(x shr shift) and 0xF'i32]
-    shift = shift + 4
+    result[j] = HexChars[n and 0xF]
+    n = n shr 4
+    # handle negative overflow
+    if n == 0 and x < 0: n = -1
 
-proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect,
+proc intToStr*(x: int, minchars: Positive = 1): string {.noSideEffect,
   rtl, extern: "nsuIntToStr".} =
   ## Converts `x` to its decimal representation.
   ##
@@ -497,30 +499,51 @@ proc parseEnum*[T: enum](s: string, default: T): T =
       return e
   result = default
 
-proc repeatChar*(count: int, c: char = ' '): string {.noSideEffect,
+proc repeat*(c: char, count: Natural): string {.noSideEffect,
   rtl, extern: "nsuRepeatChar".} =
   ## Returns a string of length `count` consisting only of
   ## the character `c`. You can use this proc to left align strings. Example:
   ##
   ## .. code-block:: nim
+  ##   proc tabexpand(indent: int, text: string, tabsize: int = 4) =
+  ##     echo '\t'.repeat(indent div tabsize), ' '.repeat(indent mod tabsize), text
+  ##
+  ##   tabexpand(4, "At four")
+  ##   tabexpand(5, "At five")
+  ##   tabexpand(6, "At six")
+  result = newString(count)
+  for i in 0..count-1: result[i] = c
+
+proc repeat*(s: string, n: Natural): string {.noSideEffect,
+  rtl, extern: "nsuRepeatStr".} =
+  ## Returns String `s` concatenated `n` times.  Example:
+  ##
+  ## .. code-block:: nim
+  ##   echo "+++ STOP ".repeat(4), "+++"
+  result = newStringOfCap(n * s.len)
+  for i in 1..n: result.add(s)
+
+template spaces*(n: Natural): string =  repeat(' ',n)
+  ## Returns a String with `n` space characters. You can use this proc
+  ## to left align strings. Example:
+  ##
+  ## .. code-block:: nim
   ##   let
   ##     width = 15
   ##     text1 = "Hello user!"
   ##     text2 = "This is a very long string"
-  ##   echo text1 & repeatChar(max(0, width - text1.len)) & "|"
-  ##   echo text2 & repeatChar(max(0, width - text2.len)) & "|"
-  result = newString(count)
-  for i in 0..count-1: result[i] = c
+  ##   echo text1 & spaces(max(0, width - text1.len)) & "|"
+  ##   echo text2 & spaces(max(0, width - text2.len)) & "|"
 
-proc repeatStr*(count: int, s: string): string {.noSideEffect,
-  rtl, extern: "nsuRepeatStr".} =
-  ## Returns `s` concatenated `count` times.
-  result = newStringOfCap(count*s.len)
-  for i in 0..count-1: result.add(s)
+proc repeatChar*(count: Natural, c: char = ' '): string {.deprecated.} = repeat(c, count)
+  ## deprecated: use repeat() or spaces()
 
-proc align*(s: string, count: int, padding = ' '): string {.
+proc repeatStr*(count: Natural, s: string): string {.deprecated.} = repeat(s, count)
+  ## deprecated: use repeat(string, count) or string.repeat(count)
+
+proc align*(s: string, count: Natural, padding = ' '): string {.
   noSideEffect, rtl, extern: "nsuAlignString".} =
-  ## Aligns a string `s` with `padding`, so that is of length `count`.
+  ## Aligns a string `s` with `padding`, so that it is of length `count`.
   ##
   ## `padding` characters (by default spaces) are added before `s` resulting in
   ## right alignment. If ``s.len >= count``, no spaces are added and `s` is
@@ -659,7 +682,7 @@ proc endsWith*(s, suffix: string): bool {.noSideEffect,
     inc(i)
   if suffix[i] == '\0': return true
 
-proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect,
+proc continuesWith*(s, substr: string, start: Natural): bool {.noSideEffect,
   rtl, extern: "nsuContinuesWith".} =
   ## Returns true iff ``s`` continues with ``substr`` at position ``start``.
   ##
@@ -670,8 +693,8 @@ proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect,
     if s[i+start] != substr[i]: return false
     inc(i)
 
-proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect,
-                                                           inline.} =
+proc addSep*(dest: var string, sep = ", ", startLen: Natural = 0)
+  {.noSideEffect, inline.} =
   ## Adds a separator to `dest` only if its length is bigger than `startLen`.
   ##
   ## A shorthand for:
@@ -761,7 +784,7 @@ proc findAux(s, sub: string, start: int, a: SkipTable): int =
     inc(j, a[s[j+m]])
   return -1
 
-proc find*(s, sub: string, start: int = 0): int {.noSideEffect,
+proc find*(s, sub: string, start: Natural = 0): int {.noSideEffect,
   rtl, extern: "nsuFindStr".} =
   ## Searches for `sub` in `s` starting at position `start`.
   ##
@@ -770,7 +793,7 @@ proc find*(s, sub: string, start: int = 0): int {.noSideEffect,
   preprocessSub(sub, a)
   result = findAux(s, sub, start, a)
 
-proc find*(s: string, sub: char, start: int = 0): int {.noSideEffect,
+proc find*(s: string, sub: char, start: Natural = 0): int {.noSideEffect,
   rtl, extern: "nsuFindChar".} =
   ## Searches for `sub` in `s` starting at position `start`.
   ##
@@ -779,7 +802,7 @@ proc find*(s: string, sub: char, start: int = 0): int {.noSideEffect,
     if sub == s[i]: return i
   return -1
 
-proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect,
+proc find*(s: string, chars: set[char], start: Natural = 0): int {.noSideEffect,
   rtl, extern: "nsuFindCharSet".} =
   ## Searches for `chars` in `s` starting at position `start`.
   ##
@@ -815,8 +838,8 @@ proc rfind*(s: string, sub: char, start: int = -1): int {.noSideEffect,
 
 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`
+  ## Count the occurrences of a substring `sub` in the string `s`.
+  ## Overlapping occurrences of `sub` only count when `overlapping`
   ## is set to true.
   var i = 0
   while true:
@@ -831,14 +854,14 @@ proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffe
 
 proc count*(s: string, sub: char): int {.noSideEffect,
   rtl, extern: "nsuCountChar".} =
-  ## Count the occurences of the character `sub` in the string `s`.
+  ## Count the occurrences 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`.
+  ## Count the occurrences of the group of character `subs` in the string `s`.
   for c in s:
     if c in subs:
       inc result
@@ -898,7 +921,7 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect,
   rtl, extern: "nsuReplaceWord".} =
   ## Replaces `sub` in `s` by the string `by`.
   ##
-  ## Each occurance of `sub` has to be surrounded by word boundaries
+  ## Each occurrence of `sub` has to be surrounded by word boundaries
   ## (comparable to ``\\w`` in regular expressions), otherwise it is not
   ## replaced.
   const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}
@@ -910,7 +933,7 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect,
     var j = findAux(s, sub, i, a)
     if j < 0: break
     # word boundary?
-    if (j == 0 or s[j-1] notin wordChars) and 
+    if (j == 0 or s[j-1] notin wordChars) and
         (j+sub.len >= s.len or s[j+sub.len] notin wordChars):
       add result, substr(s, i, j - 1)
       add result, by
@@ -953,7 +976,7 @@ proc parseOctInt*(s: string): int {.noSideEffect,
     of '\0': break
     else: raise newException(ValueError, "invalid integer: " & s)
 
-proc toOct*(x: BiggestInt, len: int): string {.noSideEffect,
+proc toOct*(x: BiggestInt, len: Positive): string {.noSideEffect,
   rtl, extern: "nsuToOct".} =
   ## Converts `x` into its octal representation.
   ##
@@ -969,7 +992,7 @@ proc toOct*(x: BiggestInt, len: int): string {.noSideEffect,
     shift = shift + 3
     mask = mask shl 3
 
-proc toBin*(x: BiggestInt, len: int): string {.noSideEffect,
+proc toBin*(x: BiggestInt, len: Positive): string {.noSideEffect,
   rtl, extern: "nsuToBin".} =
   ## Converts `x` into its binary representation.
   ##
@@ -1042,18 +1065,20 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
   ## ValueError exception will be raised.
   result = newStringOfCap(s.len)
   var i = 0
-  if s[0 .. prefix.len-1] != prefix:
+  if not s.startsWith(prefix):
     raise newException(ValueError,
                        "String does not start with a prefix of: " & prefix)
-  i.inc()
+  inc(i)
   while true:
     if i == s.len-suffix.len: break
     case s[i]
     of '\\':
       case s[i+1]:
       of 'x':
-        let j = parseHexInt(s[i+2 .. i+3])
-        result.add(chr(j))
+        inc i
+        var c: int
+        i += parseutils.parseHex(s, c, i)
+        result.add(chr(c))
         inc(i, 2)
       of '\\':
         result.add('\\')
@@ -1066,8 +1091,8 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
     of '\0': break
     else:
       result.add(s[i])
-    i.inc()
-  if s[i .. -1] != suffix:
+    inc(i)
+  if not s.endsWith(suffix):
     raise newException(ValueError,
                        "String does not end with a suffix of: " & suffix)
 
@@ -1196,7 +1221,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
   ## of significant digits to be printed.
   ## `precision`'s default value is the maximum number of meaningful digits
   ## after the decimal point for Nim's ``biggestFloat`` type.
-  ## 
+  ##
   ## If ``precision == 0``, it tries to format it nicely.
   const floatFormatToChar: array[FloatFormatMode, char] = ['g', 'f', 'e']
   var
@@ -1261,7 +1286,7 @@ proc findNormalized(x: string, inArray: openArray[string]): int =
   return -1
 
 proc invalidFormatString() {.noinline.} =
-  raise newException(ValueError, "invalid format string")  
+  raise newException(ValueError, "invalid format string")
 
 proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {.
   noSideEffect, rtl, extern: "nsuAddf".} =
@@ -1377,21 +1402,28 @@ when isMainModule:
   doAssert align("a", 0) == "a"
   doAssert align("1232", 6) == "  1232"
   doAssert align("1232", 6, '#') == "##1232"
-  echo wordWrap(""" this is a long text --  muchlongerthan10chars and here
-                   it goes""", 10, false)
+
+  let
+    inp = """ this is a long text --  muchlongerthan10chars and here
+               it goes"""
+    outp = " this is a\nlong text\n--\nmuchlongerthan10chars\nand here\nit goes"
+  doAssert wordWrap(inp, 10, false) == outp
+
   doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
-  doAssert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11"
+  doAssert formatBiggestFloat(0.00000000001, ffScientific, 1) in
+                                                   ["1.0e-11", "1.0e-011"]
 
   doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
-  echo formatSize(1'i64 shl 31 + 300'i64) # == "4,GB"
-  echo formatSize(1'i64 shl 31)
+  when not defined(testing):
+    echo formatSize(1'i64 shl 31 + 300'i64) # == "4,GB"
+    echo formatSize(1'i64 shl 31)
 
   doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] ==
            "The cat eats fish."
 
   doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz "
   doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz  abc"
-  
+
   type MyEnum = enum enA, enB, enC, enuD, enE
   doAssert parseEnum[MyEnum]("enu_D") == enuD
 
diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim
index adcfdd288..d213c99e6 100644
--- a/lib/pure/subexes.nim
+++ b/lib/pure/subexes.nim
@@ -353,11 +353,11 @@ when isMainModule:
 
   proc `%`(formatstr: string, a: openarray[string]): string =
     result = newStringOfCap(formatstr.len + a.len shl 4)
-    addf(result, formatstr.TSubex, a)
+    addf(result, formatstr.Subex, a)
 
   proc `%`(formatstr: string, a: string): string =
     result = newStringOfCap(formatstr.len + a.len)
-    addf(result, formatstr.TSubex, [a])
+    addf(result, formatstr.Subex, [a])
 
 
   doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
@@ -386,8 +386,13 @@ when isMainModule:
     longishA, 
     longish)"""
   
-  echo "type TMyEnum* = enum\n  $', '2i'\n  '{..}" % ["fieldA", 
-    "fieldB", "FiledClkad", "fieldD", "fieldE", "longishFieldName"]
+  assert "type TMyEnum* = enum\n  $', '2i'\n  '{..}" % ["fieldA",
+    "fieldB", "FiledClkad", "fieldD", "fieldE", "longishFieldName"] ==
+    strutils.unindent """
+      type TMyEnum* = enum
+        fieldA, fieldB, 
+        FiledClkad, fieldD, 
+        fieldE, longishFieldName"""
   
   doAssert subex"$1($', '{2..})" % ["f", "a", "b", "c"] == "f(a, b, c)"
   
@@ -395,7 +400,12 @@ when isMainModule:
   
   doAssert subex"$['''|'|''''|']']#" % "0" == "'|"
   
-  echo subex("type\n  TEnum = enum\n    $', '40c'\n    '{..}") % [
-    "fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"]
+  assert subex("type\n  TEnum = enum\n    $', '40c'\n    '{..}") % [
+    "fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"] ==
+    strutils.unindent """
+      type
+        TEnum = enum
+          fieldNameA, fieldNameB, fieldNameC, 
+          fieldNameD"""
   
   
diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim
index 1c1d973ee..29f700db5 100644
--- a/lib/pure/terminal.nim
+++ b/lib/pure/terminal.nim
@@ -45,6 +45,21 @@ when defined(windows):
   var
     oldAttr = getAttributes()
 
+else:
+  import termios, unsigned
+
+  proc setRaw(fd: FileHandle, time: cint = TCSAFLUSH) =
+    var mode: Termios
+    discard fd.tcgetattr(addr mode)
+    mode.c_iflag = mode.c_iflag and not Tcflag(BRKINT or ICRNL or INPCK or
+      ISTRIP or IXON)
+    mode.c_oflag = mode.c_oflag and not Tcflag(OPOST)
+    mode.c_cflag = (mode.c_cflag and not Tcflag(CSIZE or PARENB)) or CS8
+    mode.c_lflag = mode.c_lflag and not Tcflag(ECHO or ICANON or IEXTEN or ISIG)
+    mode.c_cc[VMIN] = 1.cuchar
+    mode.c_cc[VTIME] = 0.cuchar
+    discard fd.tcsetattr(time, addr mode)
+
 proc setCursorPos*(x, y: int) =
   ## sets the terminal's cursor to the (x,y) position. (0,0) is the
   ## upper left of the screen.
@@ -185,13 +200,15 @@ proc eraseScreen* =
     var numwrote: DWORD
     var origin: TCOORD # is inititalized to 0, 0
     var hStdout = conHandle
+
     if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0:
       raiseOSError(osLastError())
-    if FillConsoleOutputCharacter(hStdout, ' ', scrbuf.dwSize.X*scrbuf.dwSize.Y,
+    let numChars = int32(scrbuf.dwSize.X)*int32(scrbuf.dwSize.Y)
+
+    if FillConsoleOutputCharacter(hStdout, ' ', numChars,
                                   origin, addr(numwrote)) == 0:
       raiseOSError(osLastError())
-    if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes,
-                                  scrbuf.dwSize.X * scrbuf.dwSize.Y,
+    if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, numChars,
                                   origin, addr(numwrote)) == 0:
       raiseOSError(osLastError())
     setCursorXPos(0)
@@ -327,7 +344,7 @@ proc isatty*(f: File): bool =
   else:
     proc isatty(fildes: FileHandle): cint {.
       importc: "_isatty", header: "<io.h>".}
-  
+
   result = isatty(getFileHandle(f)) != 0'i32
 
 proc styledEchoProcessArg(s: string) = write stdout, s
@@ -347,7 +364,19 @@ macro styledEcho*(m: varargs[expr]): stmt =
   result.add(newCall(bindSym"write", bindSym"stdout", newStrLitNode("\n")))
   result.add(newCall(bindSym"resetAttributes"))
 
-when isMainModule:
+when not defined(windows):
+  proc getch*(): char =
+    ## Read a single character from the terminal, blocking until it is entered.
+    ## The character is not printed to the terminal. This is not available for
+    ## Windows.
+    let fd = getFileHandle(stdin)
+    var oldMode: Termios
+    discard fd.tcgetattr(addr oldMode)
+    fd.setRaw()
+    result = stdin.readChar()
+    discard fd.tcsetattr(TCSADRAIN, addr oldMode)
+
+when not defined(testing) and isMainModule:
   system.addQuitProc(resetAttributes)
   write(stdout, "never mind")
   eraseLine()
@@ -357,5 +386,5 @@ when isMainModule:
   setForeGroundColor(fgBlue)
   writeln(stdout, "ordinary text")
 
-  styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore}) 
-  
+  styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore})
+
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 1cabd381b..5f8835c6a 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -16,7 +16,7 @@
                       # of the standard library!
 
 import
-  strutils
+  strutils, parseutils
 
 include "system/inclrtl"
 
@@ -26,81 +26,87 @@ type
   WeekDay* = enum ## represents a weekday
     dMon, dTue, dWed, dThu, dFri, dSat, dSun
 
-var
-  timezone {.importc, header: "<time.h>".}: int
-  tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
+when not defined(JS):
+  var
+    timezone {.importc, header: "<time.h>".}: int
+    tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
 
 when defined(posix) and not defined(JS):
   type
-    TimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int
+    TimeImpl {.importc: "time_t", header: "<time.h>".} = int
     Time* = distinct TimeImpl ## distinct type that represents a time
                               ## measured as number of seconds since the epoch
-    
-    Timeval {.importc: "struct timeval", 
+
+    Timeval {.importc: "struct timeval",
               header: "<sys/select.h>".} = object ## struct timeval
-      tv_sec: int  ## Seconds. 
-      tv_usec: int ## Microseconds. 
-      
+      tv_sec: int  ## Seconds.
+      tv_usec: int ## Microseconds.
+
   # we cannot import posix.nim here, because posix.nim depends on times.nim.
-  # Ok, we could, but I don't want circular dependencies. 
+  # Ok, we could, but I don't want circular dependencies.
   # And gettimeofday() is not defined in the posix module anyway. Sigh.
-  
+
   proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {.
     importc: "gettimeofday", header: "<sys/time.h>".}
 
+  # we also need tzset() to make sure that tzname is initialized
+  proc tzset() {.importc, header: "<time.h>".}
+  # calling tzset() implicitly to initialize tzname data.
+  tzset()
+
 elif defined(windows):
   import winlean
-  
+
   when defined(vcc):
     # newest version of Visual C++ defines time_t to be of 64 bits
     type TimeImpl {.importc: "time_t", header: "<time.h>".} = int64
   else:
     type TimeImpl {.importc: "time_t", header: "<time.h>".} = int32
-  
+
   type
     Time* = distinct TimeImpl
 
 elif defined(JS):
   type
     Time* {.importc.} = object
-      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): Time {.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.}
+      getDay: proc (): int {.tags: [], raises: [], benign.}
+      getFullYear: proc (): int {.tags: [], raises: [], benign.}
+      getHours: proc (): int {.tags: [], raises: [], benign.}
+      getMilliseconds: proc (): int {.tags: [], raises: [], benign.}
+      getMinutes: proc (): int {.tags: [], raises: [], benign.}
+      getMonth: proc (): int {.tags: [], raises: [], benign.}
+      getSeconds: proc (): int {.tags: [], raises: [], benign.}
+      getTime: proc (): int {.tags: [], raises: [], benign.}
+      getTimezoneOffset: proc (): int {.tags: [], raises: [], benign.}
+      getDate: proc (): int {.tags: [], raises: [], benign.}
+      getUTCDate: proc (): int {.tags: [], raises: [], benign.}
+      getUTCFullYear: proc (): int {.tags: [], raises: [], benign.}
+      getUTCHours: proc (): int {.tags: [], raises: [], benign.}
+      getUTCMilliseconds: proc (): int {.tags: [], raises: [], benign.}
+      getUTCMinutes: proc (): int {.tags: [], raises: [], benign.}
+      getUTCMonth: proc (): int {.tags: [], raises: [], benign.}
+      getUTCSeconds: proc (): int {.tags: [], raises: [], benign.}
+      getUTCDay: proc (): int {.tags: [], raises: [], benign.}
+      getYear: proc (): int {.tags: [], raises: [], benign.}
+      parse: proc (s: cstring): Time {.tags: [], raises: [], benign.}
+      setDate: proc (x: int) {.tags: [], raises: [], benign.}
+      setFullYear: proc (x: int) {.tags: [], raises: [], benign.}
+      setHours: proc (x: int) {.tags: [], raises: [], benign.}
+      setMilliseconds: proc (x: int) {.tags: [], raises: [], benign.}
+      setMinutes: proc (x: int) {.tags: [], raises: [], benign.}
+      setMonth: proc (x: int) {.tags: [], raises: [], benign.}
+      setSeconds: proc (x: int) {.tags: [], raises: [], benign.}
+      setTime: proc (x: int) {.tags: [], raises: [], benign.}
+      setUTCDate: proc (x: int) {.tags: [], raises: [], benign.}
+      setUTCFullYear: proc (x: int) {.tags: [], raises: [], benign.}
+      setUTCHours: proc (x: int) {.tags: [], raises: [], benign.}
+      setUTCMilliseconds: proc (x: int) {.tags: [], raises: [], benign.}
+      setUTCMinutes: proc (x: int) {.tags: [], raises: [], benign.}
+      setUTCMonth: proc (x: int) {.tags: [], raises: [], benign.}
+      setUTCSeconds: proc (x: int) {.tags: [], raises: [], benign.}
+      setYear: proc (x: int) {.tags: [], raises: [], benign.}
+      toGMTString: proc (): cstring {.tags: [], raises: [], benign.}
+      toLocaleString: proc (): cstring {.tags: [], raises: [], benign.}
 
 type
   TimeInfo* = object of RootObj ## represents a time in different parts
@@ -139,51 +145,51 @@ type
 {.deprecated: [TMonth: Month, TWeekDay: WeekDay, TTime: Time,
     TTimeInterval: TimeInterval, TTimeInfo: TimeInfo].}
 
-proc getTime*(): Time {.tags: [TimeEffect], gcsafe.}
+proc getTime*(): Time {.tags: [TimeEffect], benign.}
   ## gets the current calendar time as a UNIX epoch value (number of seconds
   ## elapsed since 1970) with integer precission. Use epochTime for higher
   ## resolution.
-proc getLocalTime*(t: Time): TimeInfo {.tags: [TimeEffect], raises: [], gcsafe.}
+proc getLocalTime*(t: Time): TimeInfo {.tags: [TimeEffect], raises: [], benign.}
   ## converts the calendar time `t` to broken-time representation,
   ## expressed relative to the user's specified time zone.
-proc getGMTime*(t: Time): TimeInfo {.tags: [TimeEffect], raises: [], gcsafe.}
+proc getGMTime*(t: Time): TimeInfo {.tags: [TimeEffect], raises: [], benign.}
   ## converts the calendar time `t` to broken-down time representation,
   ## expressed in Coordinated Universal Time (UTC).
 
-proc timeInfoToTime*(timeInfo: TimeInfo): Time {.tags: [], gcsafe.}
+proc timeInfoToTime*(timeInfo: TimeInfo): Time {.tags: [], benign.}
   ## converts a broken-down time structure to
   ## calendar time representation. The function ignores the specified
   ## contents of the structure members `weekday` and `yearday` and recomputes
   ## them from the other information in the broken-down time structure.
 
-proc fromSeconds*(since1970: float): Time {.tags: [], raises: [], gcsafe.}
+proc fromSeconds*(since1970: float): Time {.tags: [], raises: [], benign.}
   ## Takes a float which contains the number of seconds since the unix epoch and
   ## returns a time object.
 
-proc fromSeconds*(since1970: int64): Time {.tags: [], raises: [], gcsafe.} = 
+proc fromSeconds*(since1970: int64): Time {.tags: [], raises: [], benign.} =
   ## Takes an int which contains the number of seconds since the unix epoch and
   ## returns a time object.
   fromSeconds(float(since1970))
 
-proc toSeconds*(time: Time): float {.tags: [], raises: [], gcsafe.}
+proc toSeconds*(time: Time): float {.tags: [], raises: [], benign.}
   ## Returns the time in seconds since the unix epoch.
 
-proc `$` *(timeInfo: TimeInfo): string {.tags: [], raises: [], gcsafe.}
+proc `$` *(timeInfo: TimeInfo): string {.tags: [], raises: [], benign.}
   ## converts a `TimeInfo` object to a string representation.
-proc `$` *(time: Time): string {.tags: [], raises: [], gcsafe.}
+proc `$` *(time: Time): string {.tags: [], raises: [], benign.}
   ## converts a calendar time to a string representation.
 
 proc `-`*(a, b: Time): int64 {.
-  rtl, extern: "ntDiffTime", tags: [], raises: [].}
+  rtl, extern: "ntDiffTime", tags: [], raises: [], benign.}
   ## computes the difference of two calendar times. Result is in seconds.
 
 proc `<`*(a, b: Time): bool {.
-  rtl, extern: "ntLtTime", tags: [], raises: [].} = 
+  rtl, extern: "ntLtTime", tags: [], raises: [].} =
   ## returns true iff ``a < b``, that is iff a happened before b.
   result = a - b < 0
-  
+
 proc `<=` * (a, b: Time): bool {.
-  rtl, extern: "ntLeTime", tags: [], raises: [].}= 
+  rtl, extern: "ntLeTime", tags: [], raises: [].}=
   ## returns true iff ``a <= b``.
   result = a - b <= 0
 
@@ -194,18 +200,18 @@ proc `==`*(a, b: Time): bool {.
 
 when not defined(JS):
   proc getTzname*(): tuple[nonDST, DST: string] {.tags: [TimeEffect], raises: [],
-    gcsafe.}
+    benign.}
     ## returns the local timezone; ``nonDST`` is the name of the local non-DST
     ## timezone, ``DST`` is the name of the local DST timezone.
 
-proc getTimezone*(): int {.tags: [TimeEffect], raises: [], gcsafe.}
+proc getTimezone*(): int {.tags: [TimeEffect], raises: [], benign.}
   ## returns the offset of the local (non-DST) timezone in seconds west of UTC.
 
-proc getStartMilsecs*(): int {.deprecated, tags: [TimeEffect], gcsafe.}
+proc getStartMilsecs*(): int {.deprecated, tags: [TimeEffect], benign.}
   ## get the miliseconds from the start of the program. **Deprecated since
   ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
 
-proc initInterval*(miliseconds, seconds, minutes, hours, days, months, 
+proc initInterval*(miliseconds, seconds, minutes, hours, days, months,
                    years: int = 0): TimeInterval =
   ## creates a new ``TimeInterval``.
   result.miliseconds = miliseconds
@@ -221,9 +227,9 @@ proc isLeapYear*(year: int): bool =
 
   if year mod 400 == 0:
     return true
-  elif year mod 100 == 0: 
+  elif year mod 100 == 0:
     return false
-  elif year mod 4 == 0: 
+  elif year mod 4 == 0:
     return true
   else:
     return false
@@ -232,7 +238,7 @@ proc getDaysInMonth*(month: Month, year: int): int =
   ## gets the amount of days in a ``month`` of a ``year``
 
   # http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month
-  case month 
+  case month
   of mFeb: result = if isLeapYear(year): 29 else: 28
   of mApr, mJun, mSep, mNov: result = 30
   else: result = 31
@@ -244,7 +250,7 @@ proc toSeconds(a: TimeInfo, interval: TimeInterval): float =
   var anew = a
   var newinterv = interval
   result = 0
-  
+
   newinterv.months += interval.years * 12
   var curMonth = anew.month
   for mth in 1 .. newinterv.months:
@@ -284,18 +290,18 @@ proc `-`*(a: TimeInfo, interval: TimeInterval): TimeInfo =
   else:
     result = getLocalTime(fromSeconds(t - secs))
 
-when not defined(JS):  
+when not defined(JS):
   proc epochTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].}
     ## gets time after the UNIX epoch (1970) in seconds. It is a float
-    ## because sub-second resolution is likely to be supported (depending 
+    ## because sub-second resolution is likely to be supported (depending
     ## on the hardware/OS).
 
   proc cpuTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].}
     ## gets time spent that the CPU spent to run the current process in
     ## seconds. This may be more useful for benchmarking than ``epochTime``.
     ## However, it may measure the real time instead (depending on the OS).
-    ## The value of the result has no meaning. 
-    ## To generate useful timing values, take the difference between 
+    ## The value of the result has no meaning.
+    ## To generate useful timing values, take the difference between
     ## the results of two ``cpuTime`` calls:
     ##
     ## .. code-block:: nim
@@ -316,10 +322,10 @@ when not defined(JS):
         weekday {.importc: "tm_wday".},
         yearday {.importc: "tm_yday".},
         isdst {.importc: "tm_isdst".}: cint
-  
+
     TimeInfoPtr = ptr StructTM
     Clock {.importc: "clock_t".} = distinct int
-  
+
   proc localtime(timer: ptr Time): TimeInfoPtr {.
     importc: "localtime", header: "<time.h>", tags: [].}
   proc gmtime(timer: ptr Time): TimeInfoPtr {.
@@ -335,12 +341,12 @@ when not defined(JS):
   #  strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {.
   #    importc: "strftime", header: "<time.h>".}
   proc getClock(): Clock {.importc: "clock", header: "<time.h>", tags: [TimeEffect].}
-  proc difftime(a, b: Time): float {.importc: "difftime", header: "<time.h>", 
+  proc difftime(a, b: Time): float {.importc: "difftime", header: "<time.h>",
     tags: [].}
-  
+
   var
     clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
-    
+
   # our own procs on top of that:
   proc tmToTimeInfo(tm: StructTM, local: bool): TimeInfo =
     const
@@ -364,7 +370,7 @@ when not defined(JS):
           "UTC",
       timezone: if local: getTimezone() else: 0
     )
-  
+
   proc timeInfoToTM(t: TimeInfo): StructTM =
     const
       weekDays: array [WeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8]
@@ -377,11 +383,11 @@ when not defined(JS):
     result.weekday = weekDays[t.weekday]
     result.yearday = t.yearday
     result.isdst = if t.isDST: 1 else: 0
-  
+
   when not defined(useNimRtl):
     proc `-` (a, b: Time): int64 =
       return toBiggestInt(difftime(a, b))
-  
+
   proc getStartMilsecs(): int =
     #echo "clocks per sec: ", clocksPerSec, "clock: ", int(getClock())
     #return getClock() div (clocksPerSec div 1000)
@@ -394,37 +400,37 @@ when not defined(JS):
       posix_gettimeofday(a)
       result = a.tv_sec * 1000'i64 + a.tv_usec div 1000'i64
       #echo "result: ", result
-    
+
   proc getTime(): Time = return timec(nil)
   proc getLocalTime(t: Time): TimeInfo =
     var a = t
     result = tmToTimeInfo(localtime(addr(a))[], true)
     # copying is needed anyway to provide reentrancity; thus
     # the conversion is not expensive
-  
+
   proc getGMTime(t: Time): TimeInfo =
     var a = t
     result = tmToTimeInfo(gmtime(addr(a))[], false)
     # copying is needed anyway to provide reentrancity; thus
     # the conversion is not expensive
-  
+
   proc timeInfoToTime(timeInfo: TimeInfo): Time =
     var cTimeInfo = timeInfo # for C++ we have to make a copy,
     # because the header of mktime is broken in my version of libc
     return mktime(timeInfoToTM(cTimeInfo))
 
-  proc toStringTillNL(p: cstring): string = 
+  proc toStringTillNL(p: cstring): string =
     result = ""
     var i = 0
-    while p[i] != '\0' and p[i] != '\10' and p[i] != '\13': 
+    while p[i] != '\0' and p[i] != '\10' and p[i] != '\13':
       add(result, p[i])
       inc(i)
-    
+
   proc `$`(timeInfo: TimeInfo): string =
     # BUGFIX: asctime returns a newline at the end!
     var p = asctime(timeInfoToTM(timeInfo))
     result = toStringTillNL(p)
-  
+
   proc `$`(time: Time): string =
     # BUGFIX: ctime returns a newline at the end!
     var a = time
@@ -434,17 +440,17 @@ when not defined(JS):
     epochDiff = 116444736000000000'i64
     rateDiff = 10000000'i64 # 100 nsecs
 
-  proc unixTimeToWinTime*(t: Time): int64 = 
+  proc unixTimeToWinTime*(t: Time): int64 =
     ## converts a UNIX `Time` (``time_t``) to a Windows file time
     result = int64(t) * rateDiff + epochDiff
-    
-  proc winTimeToUnixTime*(t: int64): Time = 
+
+  proc winTimeToUnixTime*(t: int64): Time =
     ## converts a Windows time to a UNIX `Time` (``time_t``)
     result = Time((t - epochDiff) div rateDiff)
- 
+
   proc getTzname(): tuple[nonDST, DST: string] =
     return ($tzname[0], $tzname[1])
-  
+
   proc getTimezone(): int =
     return timezone
 
@@ -453,7 +459,7 @@ when not defined(JS):
   proc toSeconds(time: Time): float = float(time)
 
   when not defined(useNimRtl):
-    proc epochTime(): float = 
+    proc epochTime(): float =
       when defined(posix):
         var a: Timeval
         posix_gettimeofday(a)
@@ -467,14 +473,14 @@ when not defined(JS):
         result = toFloat(int(secs)) + toFloat(int(subsecs)) * 0.0000001
       else:
         {.error: "unknown OS".}
-      
-    proc cpuTime(): float = 
+
+    proc cpuTime(): float =
       result = toFloat(int(getClock())) / toFloat(clocksPerSec)
-    
+
 elif defined(JS):
   proc newDate(): Time {.importc: "new Date".}
   proc internGetTime(): Time {.importc: "new Date", tags: [].}
-  
+
   proc newDate(value: float): Time {.importc: "new Date".}
   proc newDate(value: string): Time {.importc: "new Date".}
   proc getTime(): Time =
@@ -482,15 +488,15 @@ elif defined(JS):
     return newDate()
 
   const
-    weekDays: array [0..6, TWeekDay] = [
+    weekDays: array [0..6, WeekDay] = [
       dSun, dMon, dTue, dWed, dThu, dFri, dSat]
-  
+
   proc getLocalTime(t: Time): TimeInfo =
     result.second = t.getSeconds()
     result.minute = t.getMinutes()
     result.hour = t.getHours()
     result.monthday = t.getDate()
-    result.month = TMonth(t.getMonth())
+    result.month = Month(t.getMonth())
     result.year = t.getFullYear()
     result.weekday = weekDays[t.getDay()]
     result.yearday = 0
@@ -500,11 +506,11 @@ elif defined(JS):
     result.minute = t.getUTCMinutes()
     result.hour = t.getUTCHours()
     result.monthday = t.getUTCDate()
-    result.month = TMonth(t.getUTCMonth())
+    result.month = Month(t.getUTCMonth())
     result.year = t.getUTCFullYear()
     result.weekday = weekDays[t.getUTCDay()]
     result.yearday = 0
-  
+
   proc timeInfoToTime*(timeInfo: TimeInfo): Time =
     result = internGetTime()
     result.setSeconds(timeInfo.second)
@@ -513,16 +519,16 @@ elif defined(JS):
     result.setMonth(ord(timeInfo.month))
     result.setFullYear(timeInfo.year)
     result.setDate(timeInfo.monthday)
-  
+
   proc `$`(timeInfo: TimeInfo): string = return $(timeInfoToTime(timeInfo))
   proc `$`(time: Time): string = return $time.toLocaleString()
-    
-  proc `-` (a, b: Time): int64 = 
+
+  proc `-` (a, b: Time): int64 =
     return a.getTime() - b.getTime()
-  
+
   var
     startMilsecs = getTime()
-  
+
   proc getStartMilsecs(): int =
     ## get the miliseconds from the start of the program
     return int(getTime() - startMilsecs)
@@ -535,6 +541,8 @@ elif defined(JS):
 
   proc getTimezone(): int = result = newDate().getTimezoneOffset()
 
+  proc epochTime*(): float {.tags: [TimeEffect].} = newDate().toSeconds()
+
 proc getDateStr*(): string {.rtl, extern: "nt$1", tags: [TimeEffect].} =
   ## gets the current date as a string of the format ``YYYY-MM-DD``.
   var ti = getLocalTime(getTime())
@@ -554,8 +562,8 @@ proc `$`*(day: WeekDay): string =
   return lookup[day]
 
 proc `$`*(m: Month): string =
-  ## stingify operator for ``TMonth``.
-  const lookup: array[Month, string] = ["January", "February", "March", 
+  ## stingify operator for ``Month``.
+  const lookup: array[Month, string] = ["January", "February", "March",
       "April", "May", "June", "July", "August", "September", "October",
       "November", "December"]
   return lookup[m]
@@ -628,25 +636,25 @@ proc formatToken(info: TimeInfo, token: string, buf: var string) =
     var fr = ($info.year).len()-2
     if fr < 0: fr = 0
     var fyear = ($info.year)[fr .. ($info.year).len()-1]
-    if fyear.len != 2: fyear = repeatChar(2-fyear.len(), '0') & fyear
+    if fyear.len != 2: fyear = repeat('0', 2-fyear.len()) & fyear
     buf.add(fyear)
   of "yyy":
     var fr = ($info.year).len()-3
     if fr < 0: fr = 0
     var fyear = ($info.year)[fr .. ($info.year).len()-1]
-    if fyear.len != 3: fyear = repeatChar(3-fyear.len(), '0') & fyear
+    if fyear.len != 3: fyear = repeat('0', 3-fyear.len()) & fyear
     buf.add(fyear)
   of "yyyy":
     var fr = ($info.year).len()-4
     if fr < 0: fr = 0
     var fyear = ($info.year)[fr .. ($info.year).len()-1]
-    if fyear.len != 4: fyear = repeatChar(4-fyear.len(), '0') & fyear
+    if fyear.len != 4: fyear = repeat('0', 4-fyear.len()) & fyear
     buf.add(fyear)
   of "yyyyy":
     var fr = ($info.year).len()-5
     if fr < 0: fr = 0
     var fyear = ($info.year)[fr .. ($info.year).len()-1]
-    if fyear.len != 5: fyear = repeatChar(5-fyear.len(), '0') & fyear
+    if fyear.len != 5: fyear = repeat('0', 5-fyear.len()) & fyear
     buf.add(fyear)
   of "z":
     let hrs = (info.timezone div 60) div 60
@@ -676,7 +684,7 @@ proc formatToken(info: TimeInfo, token: string, buf: var string) =
 proc format*(info: TimeInfo, f: string): string =
   ## This function formats `info` as specified by `f`. The following format
   ## specifiers are available:
-  ## 
+  ##
   ## ==========  =================================================================================  ================================================
   ## Specifier   Description                                                                        Example
   ## ==========  =================================================================================  ================================================
@@ -723,14 +731,14 @@ proc format*(info: TimeInfo, f: string): string =
 
       currentF = ""
       if f[i] == '\0': break
-      
+
       if f[i] == '\'':
         inc(i) # Skip '
         while f[i] != '\'' and f.len-1 > i:
           result.add(f[i])
           inc(i)
       else: result.add(f[i])
-      
+
     else:
       # Check if the letter being added matches previous accumulated buffer.
       if currentF.len < 1 or currentF[high(currentF)] == f[i]:
@@ -744,37 +752,364 @@ proc format*(info: TimeInfo, f: string): string =
 
 {.pop.}
 
+proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
+  ## Helper of the parse proc to parse individual tokens.
+  var sv: int
+  case token
+  of "d":
+    var pd = parseInt(value[j..j+1], sv)
+    info.monthday = sv
+    j += pd
+  of "dd":
+    info.monthday = value[j..j+1].parseInt()
+    j += 2
+  of "ddd":
+    case value[j..j+2].toLower()
+    of "sun":
+      info.weekday = dSun
+    of "mon":
+      info.weekday = dMon
+    of "tue":
+      info.weekday = dTue
+    of "wed":
+      info.weekday = dWed
+    of "thu":
+      info.weekday = dThu
+    of "fri":
+      info.weekday = dFri
+    of "sat":
+      info.weekday = dSat
+    else:
+      raise newException(ValueError, "invalid day of week ")
+    j += 3
+  of "dddd":
+    if value.len >= j+6 and value[j..j+5].cmpIgnoreCase("sunday") == 0:
+      info.weekday = dSun
+      j += 6
+    elif value.len >= j+6 and value[j..j+5].cmpIgnoreCase("monday") == 0:
+      info.weekday = dMon
+      j += 6
+    elif value.len >= j+7 and value[j..j+6].cmpIgnoreCase("tuesday") == 0:
+      info.weekday = dTue
+      j += 7
+    elif value.len >= j+9 and value[j..j+8].cmpIgnoreCase("wednesday") == 0:
+      info.weekday = dWed
+      j += 9
+    elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("thursday") == 0:
+      info.weekday = dThu
+      j += 8
+    elif value.len >= j+6 and value[j..j+5].cmpIgnoreCase("friday") == 0:
+      info.weekday = dFri
+      j += 6
+    elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("saturday") == 0:
+      info.weekday = dSat
+      j += 8
+    else:
+      raise newException(ValueError, "invalid day of week ")
+  of "h", "H":
+    var pd = parseInt(value[j..j+1], sv)
+    info.hour = sv
+    j += pd
+  of "hh", "HH":
+    info.hour = value[j..j+1].parseInt()
+    j += 2
+  of "m":
+    var pd = parseInt(value[j..j+1], sv)
+    info.minute = sv
+    j += pd
+  of "mm":
+    info.minute = value[j..j+1].parseInt()
+    j += 2
+  of "M":
+    var pd = parseInt(value[j..j+1], sv)
+    info.month = Month(sv-1)
+    info.monthday = sv
+    j += pd
+  of "MM":
+    var month = value[j..j+1].parseInt()
+    j += 2
+    info.month = Month(month-1)
+  of "MMM":
+    case value[j..j+2].toLower():
+    of "jan":
+      info.month =  mJan
+    of "feb":
+      info.month =  mFeb
+    of "mar":
+      info.month =  mMar
+    of "apr":
+      info.month =  mApr
+    of "may":
+      info.month =  mMay
+    of "jun":
+      info.month =  mJun
+    of "jul":
+      info.month =  mJul
+    of "aug":
+      info.month =  mAug
+    of "sep":
+      info.month =  mSep
+    of "oct":
+      info.month =  mOct
+    of "nov":
+      info.month =  mNov
+    of "dec":
+      info.month =  mDec
+    else:
+      raise newException(ValueError, "invalid month")
+    j += 3
+  of "MMMM":
+    if value.len >= j+7 and value[j..j+6].cmpIgnoreCase("january") == 0:
+      info.month =  mJan
+      j += 7
+    elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("february") == 0:
+      info.month =  mFeb
+      j += 8
+    elif value.len >= j+5 and value[j..j+4].cmpIgnoreCase("march") == 0:
+      info.month =  mMar
+      j += 5
+    elif value.len >= j+5 and value[j..j+4].cmpIgnoreCase("april") == 0:
+      info.month =  mApr
+      j += 5
+    elif value.len >= j+3 and value[j..j+2].cmpIgnoreCase("may") == 0:
+      info.month =  mMay
+      j += 3
+    elif value.len >= j+4 and value[j..j+3].cmpIgnoreCase("june") == 0:
+      info.month =  mJun
+      j += 4
+    elif value.len >= j+4 and value[j..j+3].cmpIgnoreCase("july") == 0:
+      info.month =  mJul
+      j += 4
+    elif value.len >= j+6 and value[j..j+5].cmpIgnoreCase("august") == 0:
+      info.month =  mAug
+      j += 6
+    elif value.len >= j+9 and value[j..j+8].cmpIgnoreCase("september") == 0:
+      info.month =  mSep
+      j += 9
+    elif value.len >= j+7 and value[j..j+6].cmpIgnoreCase("october") == 0:
+      info.month =  mOct
+      j += 7
+    elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("november") == 0:
+      info.month =  mNov
+      j += 8
+    elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("december") == 0:
+      info.month =  mDec
+      j += 8
+    else:
+      raise newException(ValueError, "invalid month")
+  of "s":
+    var pd = parseInt(value[j..j+1], sv)
+    info.second = sv
+    j += pd
+  of "ss":
+    info.second = value[j..j+1].parseInt()
+    j += 2
+  of "t":
+    if value[j] == 'P' and info.hour > 0 and info.hour < 12:
+      info.hour += 12
+    j += 1
+  of "tt":
+    if value[j..j+1] == "PM" and info.hour > 0 and info.hour < 12:
+      info.hour += 12
+    j += 2
+  of "yy":
+    # Assumes current century
+    var year = value[j..j+1].parseInt()
+    var thisCen = getLocalTime(getTime()).year div 100
+    info.year = thisCen*100 + year
+    j += 2
+  of "yyyy":
+    info.year = value[j..j+3].parseInt()
+    j += 4
+  of "z":
+    if value[j] == '+':
+      info.timezone = parseInt($value[j+1])
+    elif value[j] == '-':
+      info.timezone = 0-parseInt($value[j+1])
+    else:
+      raise newException(ValueError, "Sign for timezone " & value[j])
+    j += 2
+  of "zz":
+    if value[j] == '+':
+      info.timezone = value[j+1..j+2].parseInt()
+    elif value[j] == '-':
+      info.timezone = 0-value[j+1..j+2].parseInt()
+    else:
+      raise newException(ValueError, "Sign for timezone " & value[j])
+    j += 3
+  of "zzz":
+    if value[j] == '+':
+      info.timezone = value[j+1..j+2].parseInt()
+    elif value[j] == '-':
+      info.timezone = 0-value[j+1..j+2].parseInt()
+    else:
+      raise newException(ValueError, "Sign for timezone " & value[j])
+    j += 6
+  of "ZZZ":
+    info.tzname = value[j..j+2].toUpper()
+    j += 3
+  else:
+    # Ignore the token and move forward in the value string by the same length
+    j += token.len
+
+proc parse*(value, layout: string): TimeInfo =
+  ## This function parses a date/time string using the standard format identifiers (below)
+  ## The function defaults information not provided in the format string from the running program (timezone, month, year, etc)
+  ##
+  ## ==========  =================================================================================  ================================================
+  ## Specifier   Description                                                                        Example
+  ## ==========  =================================================================================  ================================================
+  ##    d        Numeric value of the day of the month, it will be one or two digits long.          ``1/04/2012 -> 1``, ``21/04/2012 -> 21``
+  ##    dd       Same as above, but always two digits.                                              ``1/04/2012 -> 01``, ``21/04/2012 -> 21``
+  ##    ddd      Three letter string which indicates the day of the week.                           ``Saturday -> Sat``, ``Monday -> Mon``
+  ##    dddd     Full string for the day of the week.                                               ``Saturday -> Saturday``, ``Monday -> Monday``
+  ##    h        The hours in one digit if possible. Ranging from 0-12.                             ``5pm -> 5``, ``2am -> 2``
+  ##    hh       The hours in two digits always. If the hour is one digit 0 is prepended.           ``5pm -> 05``, ``11am -> 11``
+  ##    H        The hours in one digit if possible, randing from 0-24.                             ``5pm -> 17``, ``2am -> 2``
+  ##    HH       The hours in two digits always. 0 is prepended if the hour is one digit.           ``5pm -> 17``, ``2am -> 02``
+  ##    m        The minutes in 1 digit if possible.                                                ``5:30 -> 30``, ``2:01 -> 1``
+  ##    mm       Same as above but always 2 digits, 0 is prepended if the minute is one digit.      ``5:30 -> 30``, ``2:01 -> 01``
+  ##    M        The month in one digit if possible.                                                ``September -> 9``, ``December -> 12``
+  ##    MM       The month in two digits always. 0 is prepended.                                    ``September -> 09``, ``December -> 12``
+  ##    MMM      Abbreviated three-letter form of the month.                                        ``September -> Sep``, ``December -> Dec``
+  ##    MMMM     Full month string, properly capitalized.                                           ``September -> September``
+  ##    s        Seconds as one digit if possible.                                                  ``00:00:06 -> 6``
+  ##    ss       Same as above but always two digits. 0 is prepended.                               ``00:00:06 -> 06``
+  ##    t        ``A`` when time is in the AM. ``P`` when time is in the PM.
+  ##    tt       Same as above, but ``AM`` and ``PM`` instead of ``A`` and ``P`` respectively.
+  ##    yy       Displays the year to two digits.                                                   ``2012 -> 12``
+  ##    yyyy     Displays the year to four digits.                                                  ``2012 -> 2012``
+  ##    z        Displays the timezone offset from UTC.                                             ``GMT+7 -> +7``, ``GMT-5 -> -5``
+  ##    zz       Same as above but with leading 0.                                                  ``GMT+7 -> +07``, ``GMT-5 -> -05``
+  ##    zzz      Same as above but with ``:00``.                                                    ``GMT+7 -> +07:00``, ``GMT-5 -> -05:00``
+  ##    ZZZ      Displays the name of the timezone.                                                 ``GMT -> GMT``, ``EST -> EST``
+  ## ==========  =================================================================================  ================================================
+  ##
+  ## Other strings can be inserted by putting them in ``''``. For example
+  ## ``hh'->'mm`` will give ``01->56``.  The following characters can be
+  ## inserted without quoting them: ``:`` ``-`` ``(`` ``)`` ``/`` ``[`` ``]``
+  ## ``,``. However you don't need to necessarily separate format specifiers, a
+  ## unambiguous format string like ``yyyyMMddhhmmss`` is valid too.
+  var i = 0 # pointer for format string
+  var j = 0 # pointer for value string
+  var token = ""
+  # Assumes current day of month, month and year, but time is reset to 00:00:00. Weekday will be reset after parsing.
+  var info = getLocalTime(getTime())
+  info.hour = 0
+  info.minute = 0
+  info.second = 0
+  while true:
+    case layout[i]
+    of ' ', '-', '/', ':', '\'', '\0', '(', ')', '[', ']', ',':
+      if token.len > 0:
+        parseToken(info, token, value, j)
+      # Reset token
+      token = ""
+      # Break if at end of line
+      if layout[i] == '\0': break
+      # Skip separator and everything between single quotes
+      # These are literals in both the layout and the value string
+      if layout[i] == '\'':
+        inc(i)
+        inc(j)
+        while layout[i] != '\'' and layout.len-1 > i:
+          inc(i)
+          inc(j)
+      else:
+        inc(i)
+        inc(j)
+    else:
+      # Check if the letter being added matches previous accumulated buffer.
+      if token.len < 1 or token[high(token)] == layout[i]:
+        token.add(layout[i])
+        inc(i)
+      else:
+        parseToken(info, token, value, j)
+        token = ""
+  # Reset weekday as it might not have been provided and the default may be wrong
+  info.weekday = getLocalTime(timeInfoToTime(info)).weekday
+  return info
+
+
 when isMainModule:
   # $ date --date='@2147483647'
   # Tue 19 Jan 03:14:07 GMT 2038
 
   var t = getGMTime(fromSeconds(2147483647))
-  echo t.format("ddd dd MMM hh:mm:ss ZZZ yyyy")
-  echo t.format("ddd ddMMMhhmmssZZZyyyy")
   assert t.format("ddd dd MMM hh:mm:ss ZZZ yyyy") == "Tue 19 Jan 03:14:07 UTC 2038"
   assert t.format("ddd ddMMMhh:mm:ssZZZyyyy") == "Tue 19Jan03:14:07UTC2038"
-  
+
   assert t.format("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" &
-    " ss t tt y yy yyy yyyy yyyyy z zz zzz ZZZ") == 
+    " ss t tt y yy yyy yyyy yyyyy z zz zzz ZZZ") ==
     "19 19 Tue Tuesday 3 03 3 03 14 14 1 01 Jan January 7 07 A AM 8 38 038 2038 02038 0 00 00:00 UTC"
 
   assert t.format("yyyyMMddhhmmss") == "20380119031407"
-  
+
   var t2 = getGMTime(fromSeconds(160070789)) # Mon 27 Jan 16:06:29 GMT 1975
   assert t2.format("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" &
     " ss t tt y yy yyy yyyy yyyyy z zz zzz ZZZ") ==
     "27 27 Mon Monday 4 04 16 16 6 06 1 01 Jan January 29 29 P PM 5 75 975 1975 01975 0 00 00:00 UTC"
-  
+
   when not defined(JS) and sizeof(Time) == 8:
     var t3 = getGMTime(fromSeconds(889067643645)) # Fri  7 Jun 19:20:45 BST 30143
     assert t3.format("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" &
-      " ss t tt y yy yyy yyyy yyyyy z zz zzz ZZZ") == 
+      " ss t tt y yy yyy yyyy yyyyy z zz zzz ZZZ") ==
       "7 07 Fri Friday 6 06 18 18 20 20 6 06 Jun June 45 45 P PM 3 43 143 0143 30143 0 00 00:00 UTC"
-    assert t3.format(":,[]()-/") == ":,[]()-/" 
-  
+    assert t3.format(":,[]()-/") == ":,[]()-/"
+
   var t4 = getGMTime(fromSeconds(876124714)) # Mon  6 Oct 08:58:34 BST 1997
   assert t4.format("M MM MMM MMMM") == "10 10 Oct October"
-  
+
   # Interval tests
   assert((t4 - initInterval(years = 2)).format("yyyy") == "1995")
   assert((t4 - initInterval(years = 7, minutes = 34, seconds = 24)).format("yyyy mm ss") == "1990 24 10")
+
+  var s = "Tuesday at 09:04am on Dec 15, 2015"
+  var f = "dddd at hh:mmtt on MMM d, yyyy"
+  assert($s.parse(f) == "Tue Dec 15 09:04:00 2015")
+  # ANSIC       = "Mon Jan _2 15:04:05 2006"
+  s = "Thu Jan 12 15:04:05 2006"
+  f = "ddd MMM dd HH:mm:ss yyyy"
+  assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
+  # UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
+  s = "Thu Jan 12 15:04:05 MST 2006"
+  f = "ddd MMM dd HH:mm:ss ZZZ yyyy"
+  assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
+  # RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
+  s = "Thu Jan 12 15:04:05 -07:00 2006"
+  f = "ddd MMM dd HH:mm:ss zzz yyyy"
+  assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
+  # RFC822      = "02 Jan 06 15:04 MST"
+  s = "12 Jan 16 15:04 MST"
+  f = "dd MMM yy HH:mm ZZZ"
+  assert($s.parse(f) == "Tue Jan 12 15:04:00 2016")
+  # RFC822Z     = "02 Jan 06 15:04 -0700" # RFC822 with numeric zone
+  s = "12 Jan 16 15:04 -07:00"
+  f = "dd MMM yy HH:mm zzz"
+  assert($s.parse(f) == "Tue Jan 12 15:04:00 2016")
+  # RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
+  s = "Monday, 12-Jan-06 15:04:05 MST"
+  f = "dddd, dd-MMM-yy HH:mm:ss ZZZ"
+  assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
+  # RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
+  s = "Thu, 12 Jan 2006 15:04:05 MST"
+  f = "ddd, dd MMM yyyy HH:mm:ss ZZZ"
+  assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
+  # RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" # RFC1123 with numeric zone
+  s = "Thu, 12 Jan 2006 15:04:05 -07:00"
+  f = "ddd, dd MMM yyyy HH:mm:ss zzz"
+  assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
+  # RFC3339     = "2006-01-02T15:04:05Z07:00"
+  s = "2006-01-12T15:04:05Z-07:00"
+  f = "yyyy-MM-ddTHH:mm:ssZzzz"
+  assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
+  # RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
+  s = "2006-01-12T15:04:05.999999999Z-07:00"
+  f = "yyyy-MM-ddTHH:mm:ss.999999999Zzzz"
+  assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
+  # Kitchen     = "3:04PM"
+  s = "3:04PM"
+  f = "h:mmtt"
+  assert "15:04:00" in $s.parse(f)
+  when not defined(testing):
+    echo "Kitchen: " & $s.parse(f)
diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim
index c2eb001f6..5fd3c2418 100644
--- a/lib/pure/unicode.nim
+++ b/lib/pure/unicode.nim
@@ -19,7 +19,7 @@ type
   Rune16* = distinct int16 ## 16 bit Unicode character
 
 {.deprecated: [TRune: Rune, TRune16: Rune16].}
-  
+
 proc `<=%`*(a, b: Rune): bool = return int(a) <=% int(b)
 proc `<%`*(a, b: Rune): bool = return int(a) <% int(b)
 proc `==`*(a, b: Rune): bool = return int(a) == int(b)
@@ -39,7 +39,7 @@ proc runeLen*(s: string): int {.rtl, extern: "nuc$1".} =
     else: inc i
     inc(result)
 
-proc runeLenAt*(s: string, i: int): int =
+proc runeLenAt*(s: string, i: Natural): int =
   ## returns the number of bytes the rune starting at ``s[i]`` takes.
   if ord(s[i]) <=% 127: result = 1
   elif ord(s[i]) shr 5 == 0b110: result = 2
@@ -58,7 +58,7 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) =
     when doInc: inc(i)
   elif ord(s[i]) shr 5 == 0b110:
     # assert(ord(s[i+1]) shr 6 == 0b10)
-    result = Rune((ord(s[i]) and (ones(5))) shl 6 or 
+    result = Rune((ord(s[i]) and (ones(5))) shl 6 or
                   (ord(s[i+1]) and ones(6)))
     when doInc: inc(i, 2)
   elif ord(s[i]) shr 4 == 0b1110:
@@ -77,7 +77,7 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) =
              (ord(s[i+2]) and ones(6)) shl 6 or
              (ord(s[i+3]) and ones(6)))
     when doInc: inc(i, 4)
-  elif ord(s[i]) shr 2 == 0b111110: 
+  elif ord(s[i]) shr 2 == 0b111110:
     # assert(ord(s[i+1]) shr 6 == 0b10)
     # assert(ord(s[i+2]) shr 6 == 0b10)
     # assert(ord(s[i+3]) shr 6 == 0b10)
@@ -88,7 +88,7 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) =
              (ord(s[i+3]) and ones(6)) shl 6 or
              (ord(s[i+4]) and ones(6)))
     when doInc: inc(i, 5)
-  elif ord(s[i]) shr 1 == 0b1111110: 
+  elif ord(s[i]) shr 1 == 0b1111110:
     # assert(ord(s[i+1]) shr 6 == 0b10)
     # assert(ord(s[i+2]) shr 6 == 0b10)
     # assert(ord(s[i+3]) shr 6 == 0b10)
@@ -105,11 +105,36 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) =
     result = Rune(ord(s[i]))
     when doInc: inc(i)
 
-proc runeAt*(s: string, i: int): Rune =
+proc validateUtf8*(s: string): int =
+  ## returns the position of the invalid byte in ``s`` if the string ``s`` does
+  ## not hold valid UTF-8 data. Otherwise -1 is returned.
+  var i = 0
+  let L = s.len
+  while i < L:
+    if ord(s[i]) <=% 127:
+      inc(i)
+    elif ord(s[i]) shr 5 == 0b110:
+      if i+1 < L and ord(s[i+1]) shr 6 == 0b10: inc(i, 2)
+      else: return i
+    elif ord(s[i]) shr 4 == 0b1110:
+      if i+2 < L and ord(s[i+1]) shr 6 == 0b10 and ord(s[i+2]) shr 6 == 0b10:
+        inc i, 3
+      else: return i
+    elif ord(s[i]) shr 3 == 0b11110:
+      if i+3 < L and ord(s[i+1]) shr 6 == 0b10 and
+                     ord(s[i+2]) shr 6 == 0b10 and
+                     ord(s[i+3]) shr 6 == 0b10:
+        inc i, 4
+      else: return i
+    else:
+      return i
+  return -1
+
+proc runeAt*(s: string, i: Natural): Rune =
   ## returns the unicode character in `s` at byte index `i`
   fastRuneAt(s, i, result, false)
 
-proc toUTF8*(c: Rune): string {.rtl, extern: "nuc$1".} = 
+proc toUTF8*(c: Rune): string {.rtl, extern: "nuc$1".} =
   ## converts a rune into its UTF8 representation
   var i = RuneImpl(c)
   if i <=% 127:
@@ -118,21 +143,35 @@ proc toUTF8*(c: Rune): string {.rtl, extern: "nuc$1".} =
   elif i <=% 0x07FF:
     result = newString(2)
     result[0] = chr((i shr 6) or 0b110_00000)
-    result[1] = chr((i and ones(6)) or 0b10_000000)
+    result[1] = chr((i and ones(6)) or 0b10_0000_00)
   elif i <=% 0xFFFF:
     result = newString(3)
     result[0] = chr(i shr 12 or 0b1110_0000)
     result[1] = chr(i shr 6 and ones(6) or 0b10_0000_00)
     result[2] = chr(i and ones(6) or 0b10_0000_00)
-  elif i <=% 0x0010FFFF:
+  elif i <=% 0x001FFFFF:
     result = newString(4)
     result[0] = chr(i shr 18 or 0b1111_0000)
     result[1] = chr(i shr 12 and ones(6) or 0b10_0000_00)
     result[2] = chr(i shr 6 and ones(6) or 0b10_0000_00)
     result[3] = chr(i and ones(6) or 0b10_0000_00)
+  elif i <=% 0x03FFFFFF:
+    result = newString(5)
+    result[0] = chr(i shr 24 or 0b111110_00)
+    result[1] = chr(i shr 18 and ones(6) or 0b10_0000_00)
+    result[2] = chr(i shr 12 and ones(6) or 0b10_0000_00)
+    result[3] = chr(i shr 6 and ones(6) or 0b10_0000_00)
+    result[4] = chr(i and ones(6) or 0b10_0000_00)
+  elif i <=% 0x7FFFFFFF:
+    result = newString(6)
+    result[0] = chr(i shr 30 or 0b1111110_0)
+    result[1] = chr(i shr 24 and ones(6) or 0b10_0000_00)
+    result[2] = chr(i shr 18 and ones(6) or 0b10_0000_00)
+    result[3] = chr(i shr 12 and ones(6) or 0b10_0000_00)
+    result[4] = chr(i shr 6 and ones(6) or 0b10_0000_00)
+    result[5] = chr(i and ones(6) or 0b10_0000_00)
   else:
-    result = newString(1)
-    result[0] = chr(i)
+    discard # error, exception?
 
 proc `$`*(rune: Rune): string =
   ## converts a rune to a string
@@ -145,967 +184,967 @@ proc `$`*(runes: seq[Rune]): string =
 
 const
   alphaRanges = [
-    0x00d8,  0x00f6,  #  - 
-    0x00f8,  0x01f5,  #  -    
-    0x0250,  0x02a8,  #  -    
-    0x038e,  0x03a1,  #  -    
-    0x03a3,  0x03ce,  #  -    
-    0x03d0,  0x03d6,  #  -    
-    0x03e2,  0x03f3,  #  -    
-    0x0490,  0x04c4,  #  -    
-    0x0561,  0x0587,  #  -    
-    0x05d0,  0x05ea,  #  -    
-    0x05f0,  0x05f2,  #  -    
-    0x0621,  0x063a,  #  -    
-    0x0640,  0x064a,  #  -    
-    0x0671,  0x06b7,  #  -    
-    0x06ba,  0x06be,  #  -    
-    0x06c0,  0x06ce,  #  -    
-    0x06d0,  0x06d3,  #  -    
-    0x0905,  0x0939,  #  -    
-    0x0958,  0x0961,  #  -    
-    0x0985,  0x098c,  #  -    
-    0x098f,  0x0990,  #  -    
-    0x0993,  0x09a8,  #  -    
-    0x09aa,  0x09b0,  #  -    
-    0x09b6,  0x09b9,  #  -    
-    0x09dc,  0x09dd,  #  -    
-    0x09df,  0x09e1,  #  -    
-    0x09f0,  0x09f1,  #  -    
-    0x0a05,  0x0a0a,  #  -    
-    0x0a0f,  0x0a10,  #  -    
-    0x0a13,  0x0a28,  #  -    
-    0x0a2a,  0x0a30,  #  -    
-    0x0a32,  0x0a33,  #  -    
-    0x0a35,  0x0a36,  #  -    
-    0x0a38,  0x0a39,  #  -    
-    0x0a59,  0x0a5c,  #  -    
-    0x0a85,  0x0a8b,  #  -    
-    0x0a8f,  0x0a91,  #  -    
-    0x0a93,  0x0aa8,  #  -    
-    0x0aaa,  0x0ab0,  #  -    
-    0x0ab2,  0x0ab3,  #  -    
-    0x0ab5,  0x0ab9,  #  -    
-    0x0b05,  0x0b0c,  #  -    
-    0x0b0f,  0x0b10,  #  -    
-    0x0b13,  0x0b28,  #  -    
-    0x0b2a,  0x0b30,  #  -    
-    0x0b32,  0x0b33,  #  -    
-    0x0b36,  0x0b39,  #  -    
-    0x0b5c,  0x0b5d,  #  -    
-    0x0b5f,  0x0b61,  #  -    
-    0x0b85,  0x0b8a,  #  -    
-    0x0b8e,  0x0b90,  #  -    
-    0x0b92,  0x0b95,  #  -    
-    0x0b99,  0x0b9a,  #  -    
-    0x0b9e,  0x0b9f,  #  -    
-    0x0ba3,  0x0ba4,  #  -    
-    0x0ba8,  0x0baa,  #  -    
-    0x0bae,  0x0bb5,  #  -    
-    0x0bb7,  0x0bb9,  #  -    
-    0x0c05,  0x0c0c,  #  -    
-    0x0c0e,  0x0c10,  #  -    
-    0x0c12,  0x0c28,  #  -    
-    0x0c2a,  0x0c33,  #  -    
-    0x0c35,  0x0c39,  #  -    
-    0x0c60,  0x0c61,  #  -    
-    0x0c85,  0x0c8c,  #  -    
-    0x0c8e,  0x0c90,  #  -    
-    0x0c92,  0x0ca8,  #  -    
-    0x0caa,  0x0cb3,  #  -    
-    0x0cb5,  0x0cb9,  #  -    
-    0x0ce0,  0x0ce1,  #  -    
-    0x0d05,  0x0d0c,  #  -    
-    0x0d0e,  0x0d10,  #  -    
-    0x0d12,  0x0d28,  #  -    
-    0x0d2a,  0x0d39,  #  -    
-    0x0d60,  0x0d61,  #  -    
-    0x0e01,  0x0e30,  #  -    
-    0x0e32,  0x0e33,  #  -    
-    0x0e40,  0x0e46,  #  -    
-    0x0e5a,  0x0e5b,  #  -    
-    0x0e81,  0x0e82,  #  -    
-    0x0e87,  0x0e88,  #  -    
-    0x0e94,  0x0e97,  #  -    
-    0x0e99,  0x0e9f,  #  -    
-    0x0ea1,  0x0ea3,  #  -    
-    0x0eaa,  0x0eab,  #  -    
-    0x0ead,  0x0eae,  #  -    
-    0x0eb2,  0x0eb3,  #  -    
-    0x0ec0,  0x0ec4,  #  -    
-    0x0edc,  0x0edd,  #  -    
-    0x0f18,  0x0f19,  #  -    
-    0x0f40,  0x0f47,  #  -    
-    0x0f49,  0x0f69,  #  -    
-    0x10d0,  0x10f6,  #  -    
-    0x1100,  0x1159,  #  -    
-    0x115f,  0x11a2,  #  -    
-    0x11a8,  0x11f9,  #  -    
-    0x1e00,  0x1e9b,  #  -    
-    0x1f50,  0x1f57,  #  -    
-    0x1f80,  0x1fb4,  #  -    
-    0x1fb6,  0x1fbc,  #  -    
-    0x1fc2,  0x1fc4,  #  -    
-    0x1fc6,  0x1fcc,  #  -    
-    0x1fd0,  0x1fd3,  #  -    
-    0x1fd6,  0x1fdb,  #  -    
-    0x1fe0,  0x1fec,  #  -    
-    0x1ff2,  0x1ff4,  #  -    
-    0x1ff6,  0x1ffc,  #  -    
-    0x210a,  0x2113,  #  -    
-    0x2115,  0x211d,  #  -    
-    0x2120,  0x2122,  #  -    
-    0x212a,  0x2131,  #  -    
-    0x2133,  0x2138,  #  -    
-    0x3041,  0x3094,  #  -    
-    0x30a1,  0x30fa,  #  -    
-    0x3105,  0x312c,  #  -    
-    0x3131,  0x318e,  #  -    
-    0x3192,  0x319f,  #  -    
-    0x3260,  0x327b,  #  -    
-    0x328a,  0x32b0,  #  -    
-    0x32d0,  0x32fe,  #  -    
-    0x3300,  0x3357,  #  -    
-    0x3371,  0x3376,  #  -    
-    0x337b,  0x3394,  #  -    
-    0x3399,  0x339e,  #  -    
-    0x33a9,  0x33ad,  #  -    
-    0x33b0,  0x33c1,  #  -    
-    0x33c3,  0x33c5,  #  -    
-    0x33c7,  0x33d7,  #  -    
-    0x33d9,  0x33dd,  #  -    
-    0x4e00,  0x9fff,  #  -    
-    0xac00,  0xd7a3,  #  -    
-    0xf900,  0xfb06,  #  -    
-    0xfb13,  0xfb17,  #  -    
-    0xfb1f,  0xfb28,  #  -    
-    0xfb2a,  0xfb36,  #  -    
-    0xfb38,  0xfb3c,  #  -    
-    0xfb40,  0xfb41,  #  -    
-    0xfb43,  0xfb44,  #  -    
-    0xfb46,  0xfbb1,  #  -    
-    0xfbd3,  0xfd3d,  #  -    
-    0xfd50,  0xfd8f,  #  -    
-    0xfd92,  0xfdc7,  #  -    
-    0xfdf0,  0xfdf9,  #  -    
-    0xfe70,  0xfe72,  #  -    
-    0xfe76,  0xfefc,  #  -    
-    0xff66,  0xff6f,  #  -    
-    0xff71,  0xff9d,  #  -    
-    0xffa0,  0xffbe,  #  -    
-    0xffc2,  0xffc7,  #  -    
-    0xffca,  0xffcf,  #  -    
-    0xffd2,  0xffd7,  #  -    
-    0xffda,  0xffdc]  #  -    
+    0x00d8,  0x00f6,  #  -
+    0x00f8,  0x01f5,  #  -
+    0x0250,  0x02a8,  #  -
+    0x038e,  0x03a1,  #  -
+    0x03a3,  0x03ce,  #  -
+    0x03d0,  0x03d6,  #  -
+    0x03e2,  0x03f3,  #  -
+    0x0490,  0x04c4,  #  -
+    0x0561,  0x0587,  #  -
+    0x05d0,  0x05ea,  #  -
+    0x05f0,  0x05f2,  #  -
+    0x0621,  0x063a,  #  -
+    0x0640,  0x064a,  #  -
+    0x0671,  0x06b7,  #  -
+    0x06ba,  0x06be,  #  -
+    0x06c0,  0x06ce,  #  -
+    0x06d0,  0x06d3,  #  -
+    0x0905,  0x0939,  #  -
+    0x0958,  0x0961,  #  -
+    0x0985,  0x098c,  #  -
+    0x098f,  0x0990,  #  -
+    0x0993,  0x09a8,  #  -
+    0x09aa,  0x09b0,  #  -
+    0x09b6,  0x09b9,  #  -
+    0x09dc,  0x09dd,  #  -
+    0x09df,  0x09e1,  #  -
+    0x09f0,  0x09f1,  #  -
+    0x0a05,  0x0a0a,  #  -
+    0x0a0f,  0x0a10,  #  -
+    0x0a13,  0x0a28,  #  -
+    0x0a2a,  0x0a30,  #  -
+    0x0a32,  0x0a33,  #  -
+    0x0a35,  0x0a36,  #  -
+    0x0a38,  0x0a39,  #  -
+    0x0a59,  0x0a5c,  #  -
+    0x0a85,  0x0a8b,  #  -
+    0x0a8f,  0x0a91,  #  -
+    0x0a93,  0x0aa8,  #  -
+    0x0aaa,  0x0ab0,  #  -
+    0x0ab2,  0x0ab3,  #  -
+    0x0ab5,  0x0ab9,  #  -
+    0x0b05,  0x0b0c,  #  -
+    0x0b0f,  0x0b10,  #  -
+    0x0b13,  0x0b28,  #  -
+    0x0b2a,  0x0b30,  #  -
+    0x0b32,  0x0b33,  #  -
+    0x0b36,  0x0b39,  #  -
+    0x0b5c,  0x0b5d,  #  -
+    0x0b5f,  0x0b61,  #  -
+    0x0b85,  0x0b8a,  #  -
+    0x0b8e,  0x0b90,  #  -
+    0x0b92,  0x0b95,  #  -
+    0x0b99,  0x0b9a,  #  -
+    0x0b9e,  0x0b9f,  #  -
+    0x0ba3,  0x0ba4,  #  -
+    0x0ba8,  0x0baa,  #  -
+    0x0bae,  0x0bb5,  #  -
+    0x0bb7,  0x0bb9,  #  -
+    0x0c05,  0x0c0c,  #  -
+    0x0c0e,  0x0c10,  #  -
+    0x0c12,  0x0c28,  #  -
+    0x0c2a,  0x0c33,  #  -
+    0x0c35,  0x0c39,  #  -
+    0x0c60,  0x0c61,  #  -
+    0x0c85,  0x0c8c,  #  -
+    0x0c8e,  0x0c90,  #  -
+    0x0c92,  0x0ca8,  #  -
+    0x0caa,  0x0cb3,  #  -
+    0x0cb5,  0x0cb9,  #  -
+    0x0ce0,  0x0ce1,  #  -
+    0x0d05,  0x0d0c,  #  -
+    0x0d0e,  0x0d10,  #  -
+    0x0d12,  0x0d28,  #  -
+    0x0d2a,  0x0d39,  #  -
+    0x0d60,  0x0d61,  #  -
+    0x0e01,  0x0e30,  #  -
+    0x0e32,  0x0e33,  #  -
+    0x0e40,  0x0e46,  #  -
+    0x0e5a,  0x0e5b,  #  -
+    0x0e81,  0x0e82,  #  -
+    0x0e87,  0x0e88,  #  -
+    0x0e94,  0x0e97,  #  -
+    0x0e99,  0x0e9f,  #  -
+    0x0ea1,  0x0ea3,  #  -
+    0x0eaa,  0x0eab,  #  -
+    0x0ead,  0x0eae,  #  -
+    0x0eb2,  0x0eb3,  #  -
+    0x0ec0,  0x0ec4,  #  -
+    0x0edc,  0x0edd,  #  -
+    0x0f18,  0x0f19,  #  -
+    0x0f40,  0x0f47,  #  -
+    0x0f49,  0x0f69,  #  -
+    0x10d0,  0x10f6,  #  -
+    0x1100,  0x1159,  #  -
+    0x115f,  0x11a2,  #  -
+    0x11a8,  0x11f9,  #  -
+    0x1e00,  0x1e9b,  #  -
+    0x1f50,  0x1f57,  #  -
+    0x1f80,  0x1fb4,  #  -
+    0x1fb6,  0x1fbc,  #  -
+    0x1fc2,  0x1fc4,  #  -
+    0x1fc6,  0x1fcc,  #  -
+    0x1fd0,  0x1fd3,  #  -
+    0x1fd6,  0x1fdb,  #  -
+    0x1fe0,  0x1fec,  #  -
+    0x1ff2,  0x1ff4,  #  -
+    0x1ff6,  0x1ffc,  #  -
+    0x210a,  0x2113,  #  -
+    0x2115,  0x211d,  #  -
+    0x2120,  0x2122,  #  -
+    0x212a,  0x2131,  #  -
+    0x2133,  0x2138,  #  -
+    0x3041,  0x3094,  #  -
+    0x30a1,  0x30fa,  #  -
+    0x3105,  0x312c,  #  -
+    0x3131,  0x318e,  #  -
+    0x3192,  0x319f,  #  -
+    0x3260,  0x327b,  #  -
+    0x328a,  0x32b0,  #  -
+    0x32d0,  0x32fe,  #  -
+    0x3300,  0x3357,  #  -
+    0x3371,  0x3376,  #  -
+    0x337b,  0x3394,  #  -
+    0x3399,  0x339e,  #  -
+    0x33a9,  0x33ad,  #  -
+    0x33b0,  0x33c1,  #  -
+    0x33c3,  0x33c5,  #  -
+    0x33c7,  0x33d7,  #  -
+    0x33d9,  0x33dd,  #  -
+    0x4e00,  0x9fff,  #  -
+    0xac00,  0xd7a3,  #  -
+    0xf900,  0xfb06,  #  -
+    0xfb13,  0xfb17,  #  -
+    0xfb1f,  0xfb28,  #  -
+    0xfb2a,  0xfb36,  #  -
+    0xfb38,  0xfb3c,  #  -
+    0xfb40,  0xfb41,  #  -
+    0xfb43,  0xfb44,  #  -
+    0xfb46,  0xfbb1,  #  -
+    0xfbd3,  0xfd3d,  #  -
+    0xfd50,  0xfd8f,  #  -
+    0xfd92,  0xfdc7,  #  -
+    0xfdf0,  0xfdf9,  #  -
+    0xfe70,  0xfe72,  #  -
+    0xfe76,  0xfefc,  #  -
+    0xff66,  0xff6f,  #  -
+    0xff71,  0xff9d,  #  -
+    0xffa0,  0xffbe,  #  -
+    0xffc2,  0xffc7,  #  -
+    0xffca,  0xffcf,  #  -
+    0xffd2,  0xffd7,  #  -
+    0xffda,  0xffdc]  #  -
 
   alphaSinglets = [
-    0x00aa,  #    
-    0x00b5,  #    
-    0x00ba,  #    
-    0x03da,  #    
-    0x03dc,  #    
-    0x03de,  #    
-    0x03e0,  #    
-    0x06d5,  #    
-    0x09b2,  #    
-    0x0a5e,  #    
-    0x0a8d,  #    
-    0x0ae0,  #    
-    0x0b9c,  #    
-    0x0cde,  #    
-    0x0e4f,  #    
-    0x0e84,  #    
-    0x0e8a,  #    
-    0x0e8d,  #    
-    0x0ea5,  #    
-    0x0ea7,  #    
-    0x0eb0,  #    
-    0x0ebd,  #    
-    0x1fbe,  #    
-    0x207f,  #    
-    0x20a8,  #    
-    0x2102,  #    
-    0x2107,  #    
-    0x2124,  #    
-    0x2126,  #    
-    0x2128,  #    
-    0xfb3e,  #    
-    0xfe74]  #    
+    0x00aa,  #
+    0x00b5,  #
+    0x00ba,  #
+    0x03da,  #
+    0x03dc,  #
+    0x03de,  #
+    0x03e0,  #
+    0x06d5,  #
+    0x09b2,  #
+    0x0a5e,  #
+    0x0a8d,  #
+    0x0ae0,  #
+    0x0b9c,  #
+    0x0cde,  #
+    0x0e4f,  #
+    0x0e84,  #
+    0x0e8a,  #
+    0x0e8d,  #
+    0x0ea5,  #
+    0x0ea7,  #
+    0x0eb0,  #
+    0x0ebd,  #
+    0x1fbe,  #
+    0x207f,  #
+    0x20a8,  #
+    0x2102,  #
+    0x2107,  #
+    0x2124,  #
+    0x2126,  #
+    0x2128,  #
+    0xfb3e,  #
+    0xfe74]  #
 
   spaceRanges = [
-    0x0009,  0x000a,  # tab and newline   
-    0x0020,  0x0020,  # space   
-    0x00a0,  0x00a0,  #    
-    0x2000,  0x200b,  #  -    
-    0x2028,  0x2029,  #  -     0x3000,  0x3000,  #    
-    0xfeff,  0xfeff]  #    
+    0x0009,  0x000a,  # tab and newline
+    0x0020,  0x0020,  # space
+    0x00a0,  0x00a0,  #
+    0x2000,  0x200b,  #  -
+    0x2028,  0x2029,  #  -     0x3000,  0x3000,  #
+    0xfeff,  0xfeff]  #
 
   toupperRanges = [
-    0x0061,  0x007a, 468,  # a-z A-Z   
-    0x00e0,  0x00f6, 468,  # - -   
-    0x00f8,  0x00fe, 468,  # - -   
-    0x0256,  0x0257, 295,  # - -   
-    0x0258,  0x0259, 298,  # - -   
-    0x028a,  0x028b, 283,  # - -   
-    0x03ad,  0x03af, 463,  # - -   
-    0x03b1,  0x03c1, 468,  # - -   
-    0x03c3,  0x03cb, 468,  # - -   
-    0x03cd,  0x03ce, 437,  # - -   
-    0x0430,  0x044f, 468,  # - -   
-    0x0451,  0x045c, 420,  # - -   
-    0x045e,  0x045f, 420,  # - -   
-    0x0561,  0x0586, 452,  # - -   
-    0x1f00,  0x1f07, 508,  # - -   
-    0x1f10,  0x1f15, 508,  # - -   
-    0x1f20,  0x1f27, 508,  # - -   
-    0x1f30,  0x1f37, 508,  # - -   
-    0x1f40,  0x1f45, 508,  # - -   
-    0x1f60,  0x1f67, 508,  # - -   
-    0x1f70,  0x1f71, 574,  # - -   
-    0x1f72,  0x1f75, 586,  # - -   
-    0x1f76,  0x1f77, 600,  # - -   
-    0x1f78,  0x1f79, 628,  # - -   
-    0x1f7a,  0x1f7b, 612,  # - -   
-    0x1f7c,  0x1f7d, 626,  # - -   
-    0x1f80,  0x1f87, 508,  # - -   
-    0x1f90,  0x1f97, 508,  # - -   
-    0x1fa0,  0x1fa7, 508,  # - -   
-    0x1fb0,  0x1fb1, 508,  # - -   
-    0x1fd0,  0x1fd1, 508,  # - -   
-    0x1fe0,  0x1fe1, 508,  # - -   
-    0x2170,  0x217f, 484,  # - -   
-    0x24d0,  0x24e9, 474,  # - -   
-    0xff41,  0xff5a, 468]  # - -   
+    0x0061,  0x007a, 468,  # a-z A-Z
+    0x00e0,  0x00f6, 468,  # - -
+    0x00f8,  0x00fe, 468,  # - -
+    0x0256,  0x0257, 295,  # - -
+    0x0258,  0x0259, 298,  # - -
+    0x028a,  0x028b, 283,  # - -
+    0x03ad,  0x03af, 463,  # - -
+    0x03b1,  0x03c1, 468,  # - -
+    0x03c3,  0x03cb, 468,  # - -
+    0x03cd,  0x03ce, 437,  # - -
+    0x0430,  0x044f, 468,  # - -
+    0x0451,  0x045c, 420,  # - -
+    0x045e,  0x045f, 420,  # - -
+    0x0561,  0x0586, 452,  # - -
+    0x1f00,  0x1f07, 508,  # - -
+    0x1f10,  0x1f15, 508,  # - -
+    0x1f20,  0x1f27, 508,  # - -
+    0x1f30,  0x1f37, 508,  # - -
+    0x1f40,  0x1f45, 508,  # - -
+    0x1f60,  0x1f67, 508,  # - -
+    0x1f70,  0x1f71, 574,  # - -
+    0x1f72,  0x1f75, 586,  # - -
+    0x1f76,  0x1f77, 600,  # - -
+    0x1f78,  0x1f79, 628,  # - -
+    0x1f7a,  0x1f7b, 612,  # - -
+    0x1f7c,  0x1f7d, 626,  # - -
+    0x1f80,  0x1f87, 508,  # - -
+    0x1f90,  0x1f97, 508,  # - -
+    0x1fa0,  0x1fa7, 508,  # - -
+    0x1fb0,  0x1fb1, 508,  # - -
+    0x1fd0,  0x1fd1, 508,  # - -
+    0x1fe0,  0x1fe1, 508,  # - -
+    0x2170,  0x217f, 484,  # - -
+    0x24d0,  0x24e9, 474,  # - -
+    0xff41,  0xff5a, 468]  # - -
 
   toupperSinglets = [
-    0x00ff, 621,  #     
-    0x0101, 499,  #     
-    0x0103, 499,  #     
-    0x0105, 499,  #     
-    0x0107, 499,  #     
-    0x0109, 499,  #     
-    0x010b, 499,  #     
-    0x010d, 499,  #     
-    0x010f, 499,  #     
-    0x0111, 499,  #     
-    0x0113, 499,  #     
-    0x0115, 499,  #     
-    0x0117, 499,  #     
-    0x0119, 499,  #     
-    0x011b, 499,  #     
-    0x011d, 499,  #     
-    0x011f, 499,  #     
-    0x0121, 499,  #     
-    0x0123, 499,  #     
-    0x0125, 499,  #     
-    0x0127, 499,  #     
-    0x0129, 499,  #     
-    0x012b, 499,  #     
-    0x012d, 499,  #     
-    0x012f, 499,  #     
-    0x0131, 268,  #  I   
-    0x0133, 499,  #     
-    0x0135, 499,  #     
-    0x0137, 499,  #     
-    0x013a, 499,  #     
-    0x013c, 499,  #     
-    0x013e, 499,  #     
-    0x0140, 499,  #     
-    0x0142, 499,  #     
-    0x0144, 499,  #     
-    0x0146, 499,  #     
-    0x0148, 499,  #     
-    0x014b, 499,  #     
-    0x014d, 499,  #     
-    0x014f, 499,  #     
-    0x0151, 499,  #     
-    0x0153, 499,  #     
-    0x0155, 499,  #     
-    0x0157, 499,  #     
-    0x0159, 499,  #     
-    0x015b, 499,  #     
-    0x015d, 499,  #     
-    0x015f, 499,  #     
-    0x0161, 499,  #     
-    0x0163, 499,  #     
-    0x0165, 499,  #     
-    0x0167, 499,  #     
-    0x0169, 499,  #     
-    0x016b, 499,  #     
-    0x016d, 499,  #     
-    0x016f, 499,  #     
-    0x0171, 499,  #     
-    0x0173, 499,  #     
-    0x0175, 499,  #     
-    0x0177, 499,  #     
-    0x017a, 499,  #     
-    0x017c, 499,  #     
-    0x017e, 499,  #     
-    0x017f, 200,  #  S   
-    0x0183, 499,  #     
-    0x0185, 499,  #     
-    0x0188, 499,  #     
-    0x018c, 499,  #     
-    0x0192, 499,  #     
-    0x0199, 499,  #     
-    0x01a1, 499,  #     
-    0x01a3, 499,  #     
-    0x01a5, 499,  #     
-    0x01a8, 499,  #     
-    0x01ad, 499,  #     
-    0x01b0, 499,  #     
-    0x01b4, 499,  #     
-    0x01b6, 499,  #     
-    0x01b9, 499,  #     
-    0x01bd, 499,  #     
-    0x01c5, 499,  #     
-    0x01c6, 498,  #     
-    0x01c8, 499,  #     
-    0x01c9, 498,  #     
-    0x01cb, 499,  #     
-    0x01cc, 498,  #     
-    0x01ce, 499,  #     
-    0x01d0, 499,  #     
-    0x01d2, 499,  #     
-    0x01d4, 499,  #     
-    0x01d6, 499,  #     
-    0x01d8, 499,  #     
-    0x01da, 499,  #     
-    0x01dc, 499,  #     
-    0x01df, 499,  #     
-    0x01e1, 499,  #     
-    0x01e3, 499,  #     
-    0x01e5, 499,  #     
-    0x01e7, 499,  #     
-    0x01e9, 499,  #     
-    0x01eb, 499,  #     
-    0x01ed, 499,  #     
-    0x01ef, 499,  #     
-    0x01f2, 499,  #     
-    0x01f3, 498,  #     
-    0x01f5, 499,  #     
-    0x01fb, 499,  #     
-    0x01fd, 499,  #     
-    0x01ff, 499,  #     
-    0x0201, 499,  #     
-    0x0203, 499,  #     
-    0x0205, 499,  #     
-    0x0207, 499,  #     
-    0x0209, 499,  #     
-    0x020b, 499,  #     
-    0x020d, 499,  #     
-    0x020f, 499,  #     
-    0x0211, 499,  #     
-    0x0213, 499,  #     
-    0x0215, 499,  #     
-    0x0217, 499,  #     
-    0x0253, 290,  #     
-    0x0254, 294,  #     
-    0x025b, 297,  #     
-    0x0260, 295,  #     
-    0x0263, 293,  #     
-    0x0268, 291,  #     
-    0x0269, 289,  #     
-    0x026f, 289,  #     
-    0x0272, 287,  #     
-    0x0283, 282,  #     
-    0x0288, 282,  #     
-    0x0292, 281,  #     
-    0x03ac, 462,  #     
-    0x03cc, 436,  #     
-    0x03d0, 438,  #     
-    0x03d1, 443,  #     
-    0x03d5, 453,  #     
-    0x03d6, 446,  #     
-    0x03e3, 499,  #     
-    0x03e5, 499,  #     
-    0x03e7, 499,  #     
-    0x03e9, 499,  #     
-    0x03eb, 499,  #     
-    0x03ed, 499,  #     
-    0x03ef, 499,  #     
-    0x03f0, 414,  #     
-    0x03f1, 420,  #     
-    0x0461, 499,  #     
-    0x0463, 499,  #     
-    0x0465, 499,  #     
-    0x0467, 499,  #     
-    0x0469, 499,  #     
-    0x046b, 499,  #     
-    0x046d, 499,  #     
-    0x046f, 499,  #     
-    0x0471, 499,  #     
-    0x0473, 499,  #     
-    0x0475, 499,  #     
-    0x0477, 499,  #     
-    0x0479, 499,  #     
-    0x047b, 499,  #     
-    0x047d, 499,  #     
-    0x047f, 499,  #     
-    0x0481, 499,  #     
-    0x0491, 499,  #     
-    0x0493, 499,  #     
-    0x0495, 499,  #     
-    0x0497, 499,  #     
-    0x0499, 499,  #     
-    0x049b, 499,  #     
-    0x049d, 499,  #     
-    0x049f, 499,  #     
-    0x04a1, 499,  #     
-    0x04a3, 499,  #     
-    0x04a5, 499,  #     
-    0x04a7, 499,  #     
-    0x04a9, 499,  #     
-    0x04ab, 499,  #     
-    0x04ad, 499,  #     
-    0x04af, 499,  #     
-    0x04b1, 499,  #     
-    0x04b3, 499,  #     
-    0x04b5, 499,  #     
-    0x04b7, 499,  #     
-    0x04b9, 499,  #     
-    0x04bb, 499,  #     
-    0x04bd, 499,  #     
-    0x04bf, 499,  #     
-    0x04c2, 499,  #     
-    0x04c4, 499,  #     
-    0x04c8, 499,  #     
-    0x04cc, 499,  #     
-    0x04d1, 499,  #     
-    0x04d3, 499,  #     
-    0x04d5, 499,  #     
-    0x04d7, 499,  #     
-    0x04d9, 499,  #     
-    0x04db, 499,  #     
-    0x04dd, 499,  #     
-    0x04df, 499,  #     
-    0x04e1, 499,  #     
-    0x04e3, 499,  #     
-    0x04e5, 499,  #     
-    0x04e7, 499,  #     
-    0x04e9, 499,  #     
-    0x04eb, 499,  #     
-    0x04ef, 499,  #     
-    0x04f1, 499,  #     
-    0x04f3, 499,  #     
-    0x04f5, 499,  #     
-    0x04f9, 499,  #     
-    0x1e01, 499,  #     
-    0x1e03, 499,  #     
-    0x1e05, 499,  #     
-    0x1e07, 499,  #     
-    0x1e09, 499,  #     
-    0x1e0b, 499,  #     
-    0x1e0d, 499,  #     
-    0x1e0f, 499,  #     
-    0x1e11, 499,  #     
-    0x1e13, 499,  #     
-    0x1e15, 499,  #     
-    0x1e17, 499,  #     
-    0x1e19, 499,  #     
-    0x1e1b, 499,  #     
-    0x1e1d, 499,  #     
-    0x1e1f, 499,  #     
-    0x1e21, 499,  #     
-    0x1e23, 499,  #     
-    0x1e25, 499,  #     
-    0x1e27, 499,  #     
-    0x1e29, 499,  #     
-    0x1e2b, 499,  #     
-    0x1e2d, 499,  #     
-    0x1e2f, 499,  #     
-    0x1e31, 499,  #     
-    0x1e33, 499,  #     
-    0x1e35, 499,  #     
-    0x1e37, 499,  #     
-    0x1e39, 499,  #     
-    0x1e3b, 499,  #     
-    0x1e3d, 499,  #     
-    0x1e3f, 499,  #     
-    0x1e41, 499,  #     
-    0x1e43, 499,  #     
-    0x1e45, 499,  #     
-    0x1e47, 499,  #     
-    0x1e49, 499,  #     
-    0x1e4b, 499,  #     
-    0x1e4d, 499,  #     
-    0x1e4f, 499,  #     
-    0x1e51, 499,  #     
-    0x1e53, 499,  #     
-    0x1e55, 499,  #     
-    0x1e57, 499,  #     
-    0x1e59, 499,  #     
-    0x1e5b, 499,  #     
-    0x1e5d, 499,  #     
-    0x1e5f, 499,  #     
-    0x1e61, 499,  #     
-    0x1e63, 499,  #     
-    0x1e65, 499,  #     
-    0x1e67, 499,  #     
-    0x1e69, 499,  #     
-    0x1e6b, 499,  #     
-    0x1e6d, 499,  #     
-    0x1e6f, 499,  #     
-    0x1e71, 499,  #     
-    0x1e73, 499,  #     
-    0x1e75, 499,  #     
-    0x1e77, 499,  #     
-    0x1e79, 499,  #     
-    0x1e7b, 499,  #     
-    0x1e7d, 499,  #     
-    0x1e7f, 499,  #     
-    0x1e81, 499,  #     
-    0x1e83, 499,  #     
-    0x1e85, 499,  #     
-    0x1e87, 499,  #     
-    0x1e89, 499,  #     
-    0x1e8b, 499,  #     
-    0x1e8d, 499,  #     
-    0x1e8f, 499,  #     
-    0x1e91, 499,  #     
-    0x1e93, 499,  #     
-    0x1e95, 499,  #     
-    0x1ea1, 499,  #     
-    0x1ea3, 499,  #     
-    0x1ea5, 499,  #     
-    0x1ea7, 499,  #     
-    0x1ea9, 499,  #     
-    0x1eab, 499,  #     
-    0x1ead, 499,  #     
-    0x1eaf, 499,  #     
-    0x1eb1, 499,  #     
-    0x1eb3, 499,  #     
-    0x1eb5, 499,  #     
-    0x1eb7, 499,  #     
-    0x1eb9, 499,  #     
-    0x1ebb, 499,  #     
-    0x1ebd, 499,  #     
-    0x1ebf, 499,  #     
-    0x1ec1, 499,  #     
-    0x1ec3, 499,  #     
-    0x1ec5, 499,  #     
-    0x1ec7, 499,  #     
-    0x1ec9, 499,  #     
-    0x1ecb, 499,  #     
-    0x1ecd, 499,  #     
-    0x1ecf, 499,  #     
-    0x1ed1, 499,  #     
-    0x1ed3, 499,  #     
-    0x1ed5, 499,  #     
-    0x1ed7, 499,  #     
-    0x1ed9, 499,  #     
-    0x1edb, 499,  #     
-    0x1edd, 499,  #     
-    0x1edf, 499,  #     
-    0x1ee1, 499,  #     
-    0x1ee3, 499,  #     
-    0x1ee5, 499,  #     
-    0x1ee7, 499,  #     
-    0x1ee9, 499,  #     
-    0x1eeb, 499,  #     
-    0x1eed, 499,  #     
-    0x1eef, 499,  #     
-    0x1ef1, 499,  #     
-    0x1ef3, 499,  #     
-    0x1ef5, 499,  #     
-    0x1ef7, 499,  #     
-    0x1ef9, 499,  #     
-    0x1f51, 508,  #     
-    0x1f53, 508,  #     
-    0x1f55, 508,  #     
-    0x1f57, 508,  #     
-    0x1fb3, 509,  #     
-    0x1fc3, 509,  #     
-    0x1fe5, 507,  #     
-    0x1ff3, 509]  #     
+    0x00ff, 621,  #
+    0x0101, 499,  #
+    0x0103, 499,  #
+    0x0105, 499,  #
+    0x0107, 499,  #
+    0x0109, 499,  #
+    0x010b, 499,  #
+    0x010d, 499,  #
+    0x010f, 499,  #
+    0x0111, 499,  #
+    0x0113, 499,  #
+    0x0115, 499,  #
+    0x0117, 499,  #
+    0x0119, 499,  #
+    0x011b, 499,  #
+    0x011d, 499,  #
+    0x011f, 499,  #
+    0x0121, 499,  #
+    0x0123, 499,  #
+    0x0125, 499,  #
+    0x0127, 499,  #
+    0x0129, 499,  #
+    0x012b, 499,  #
+    0x012d, 499,  #
+    0x012f, 499,  #
+    0x0131, 268,  #  I
+    0x0133, 499,  #
+    0x0135, 499,  #
+    0x0137, 499,  #
+    0x013a, 499,  #
+    0x013c, 499,  #
+    0x013e, 499,  #
+    0x0140, 499,  #
+    0x0142, 499,  #
+    0x0144, 499,  #
+    0x0146, 499,  #
+    0x0148, 499,  #
+    0x014b, 499,  #
+    0x014d, 499,  #
+    0x014f, 499,  #
+    0x0151, 499,  #
+    0x0153, 499,  #
+    0x0155, 499,  #
+    0x0157, 499,  #
+    0x0159, 499,  #
+    0x015b, 499,  #
+    0x015d, 499,  #
+    0x015f, 499,  #
+    0x0161, 499,  #
+    0x0163, 499,  #
+    0x0165, 499,  #
+    0x0167, 499,  #
+    0x0169, 499,  #
+    0x016b, 499,  #
+    0x016d, 499,  #
+    0x016f, 499,  #
+    0x0171, 499,  #
+    0x0173, 499,  #
+    0x0175, 499,  #
+    0x0177, 499,  #
+    0x017a, 499,  #
+    0x017c, 499,  #
+    0x017e, 499,  #
+    0x017f, 200,  #  S
+    0x0183, 499,  #
+    0x0185, 499,  #
+    0x0188, 499,  #
+    0x018c, 499,  #
+    0x0192, 499,  #
+    0x0199, 499,  #
+    0x01a1, 499,  #
+    0x01a3, 499,  #
+    0x01a5, 499,  #
+    0x01a8, 499,  #
+    0x01ad, 499,  #
+    0x01b0, 499,  #
+    0x01b4, 499,  #
+    0x01b6, 499,  #
+    0x01b9, 499,  #
+    0x01bd, 499,  #
+    0x01c5, 499,  #
+    0x01c6, 498,  #
+    0x01c8, 499,  #
+    0x01c9, 498,  #
+    0x01cb, 499,  #
+    0x01cc, 498,  #
+    0x01ce, 499,  #
+    0x01d0, 499,  #
+    0x01d2, 499,  #
+    0x01d4, 499,  #
+    0x01d6, 499,  #
+    0x01d8, 499,  #
+    0x01da, 499,  #
+    0x01dc, 499,  #
+    0x01df, 499,  #
+    0x01e1, 499,  #
+    0x01e3, 499,  #
+    0x01e5, 499,  #
+    0x01e7, 499,  #
+    0x01e9, 499,  #
+    0x01eb, 499,  #
+    0x01ed, 499,  #
+    0x01ef, 499,  #
+    0x01f2, 499,  #
+    0x01f3, 498,  #
+    0x01f5, 499,  #
+    0x01fb, 499,  #
+    0x01fd, 499,  #
+    0x01ff, 499,  #
+    0x0201, 499,  #
+    0x0203, 499,  #
+    0x0205, 499,  #
+    0x0207, 499,  #
+    0x0209, 499,  #
+    0x020b, 499,  #
+    0x020d, 499,  #
+    0x020f, 499,  #
+    0x0211, 499,  #
+    0x0213, 499,  #
+    0x0215, 499,  #
+    0x0217, 499,  #
+    0x0253, 290,  #
+    0x0254, 294,  #
+    0x025b, 297,  #
+    0x0260, 295,  #
+    0x0263, 293,  #
+    0x0268, 291,  #
+    0x0269, 289,  #
+    0x026f, 289,  #
+    0x0272, 287,  #
+    0x0283, 282,  #
+    0x0288, 282,  #
+    0x0292, 281,  #
+    0x03ac, 462,  #
+    0x03cc, 436,  #
+    0x03d0, 438,  #
+    0x03d1, 443,  #
+    0x03d5, 453,  #
+    0x03d6, 446,  #
+    0x03e3, 499,  #
+    0x03e5, 499,  #
+    0x03e7, 499,  #
+    0x03e9, 499,  #
+    0x03eb, 499,  #
+    0x03ed, 499,  #
+    0x03ef, 499,  #
+    0x03f0, 414,  #
+    0x03f1, 420,  #
+    0x0461, 499,  #
+    0x0463, 499,  #
+    0x0465, 499,  #
+    0x0467, 499,  #
+    0x0469, 499,  #
+    0x046b, 499,  #
+    0x046d, 499,  #
+    0x046f, 499,  #
+    0x0471, 499,  #
+    0x0473, 499,  #
+    0x0475, 499,  #
+    0x0477, 499,  #
+    0x0479, 499,  #
+    0x047b, 499,  #
+    0x047d, 499,  #
+    0x047f, 499,  #
+    0x0481, 499,  #
+    0x0491, 499,  #
+    0x0493, 499,  #
+    0x0495, 499,  #
+    0x0497, 499,  #
+    0x0499, 499,  #
+    0x049b, 499,  #
+    0x049d, 499,  #
+    0x049f, 499,  #
+    0x04a1, 499,  #
+    0x04a3, 499,  #
+    0x04a5, 499,  #
+    0x04a7, 499,  #
+    0x04a9, 499,  #
+    0x04ab, 499,  #
+    0x04ad, 499,  #
+    0x04af, 499,  #
+    0x04b1, 499,  #
+    0x04b3, 499,  #
+    0x04b5, 499,  #
+    0x04b7, 499,  #
+    0x04b9, 499,  #
+    0x04bb, 499,  #
+    0x04bd, 499,  #
+    0x04bf, 499,  #
+    0x04c2, 499,  #
+    0x04c4, 499,  #
+    0x04c8, 499,  #
+    0x04cc, 499,  #
+    0x04d1, 499,  #
+    0x04d3, 499,  #
+    0x04d5, 499,  #
+    0x04d7, 499,  #
+    0x04d9, 499,  #
+    0x04db, 499,  #
+    0x04dd, 499,  #
+    0x04df, 499,  #
+    0x04e1, 499,  #
+    0x04e3, 499,  #
+    0x04e5, 499,  #
+    0x04e7, 499,  #
+    0x04e9, 499,  #
+    0x04eb, 499,  #
+    0x04ef, 499,  #
+    0x04f1, 499,  #
+    0x04f3, 499,  #
+    0x04f5, 499,  #
+    0x04f9, 499,  #
+    0x1e01, 499,  #
+    0x1e03, 499,  #
+    0x1e05, 499,  #
+    0x1e07, 499,  #
+    0x1e09, 499,  #
+    0x1e0b, 499,  #
+    0x1e0d, 499,  #
+    0x1e0f, 499,  #
+    0x1e11, 499,  #
+    0x1e13, 499,  #
+    0x1e15, 499,  #
+    0x1e17, 499,  #
+    0x1e19, 499,  #
+    0x1e1b, 499,  #
+    0x1e1d, 499,  #
+    0x1e1f, 499,  #
+    0x1e21, 499,  #
+    0x1e23, 499,  #
+    0x1e25, 499,  #
+    0x1e27, 499,  #
+    0x1e29, 499,  #
+    0x1e2b, 499,  #
+    0x1e2d, 499,  #
+    0x1e2f, 499,  #
+    0x1e31, 499,  #
+    0x1e33, 499,  #
+    0x1e35, 499,  #
+    0x1e37, 499,  #
+    0x1e39, 499,  #
+    0x1e3b, 499,  #
+    0x1e3d, 499,  #
+    0x1e3f, 499,  #
+    0x1e41, 499,  #
+    0x1e43, 499,  #
+    0x1e45, 499,  #
+    0x1e47, 499,  #
+    0x1e49, 499,  #
+    0x1e4b, 499,  #
+    0x1e4d, 499,  #
+    0x1e4f, 499,  #
+    0x1e51, 499,  #
+    0x1e53, 499,  #
+    0x1e55, 499,  #
+    0x1e57, 499,  #
+    0x1e59, 499,  #
+    0x1e5b, 499,  #
+    0x1e5d, 499,  #
+    0x1e5f, 499,  #
+    0x1e61, 499,  #
+    0x1e63, 499,  #
+    0x1e65, 499,  #
+    0x1e67, 499,  #
+    0x1e69, 499,  #
+    0x1e6b, 499,  #
+    0x1e6d, 499,  #
+    0x1e6f, 499,  #
+    0x1e71, 499,  #
+    0x1e73, 499,  #
+    0x1e75, 499,  #
+    0x1e77, 499,  #
+    0x1e79, 499,  #
+    0x1e7b, 499,  #
+    0x1e7d, 499,  #
+    0x1e7f, 499,  #
+    0x1e81, 499,  #
+    0x1e83, 499,  #
+    0x1e85, 499,  #
+    0x1e87, 499,  #
+    0x1e89, 499,  #
+    0x1e8b, 499,  #
+    0x1e8d, 499,  #
+    0x1e8f, 499,  #
+    0x1e91, 499,  #
+    0x1e93, 499,  #
+    0x1e95, 499,  #
+    0x1ea1, 499,  #
+    0x1ea3, 499,  #
+    0x1ea5, 499,  #
+    0x1ea7, 499,  #
+    0x1ea9, 499,  #
+    0x1eab, 499,  #
+    0x1ead, 499,  #
+    0x1eaf, 499,  #
+    0x1eb1, 499,  #
+    0x1eb3, 499,  #
+    0x1eb5, 499,  #
+    0x1eb7, 499,  #
+    0x1eb9, 499,  #
+    0x1ebb, 499,  #
+    0x1ebd, 499,  #
+    0x1ebf, 499,  #
+    0x1ec1, 499,  #
+    0x1ec3, 499,  #
+    0x1ec5, 499,  #
+    0x1ec7, 499,  #
+    0x1ec9, 499,  #
+    0x1ecb, 499,  #
+    0x1ecd, 499,  #
+    0x1ecf, 499,  #
+    0x1ed1, 499,  #
+    0x1ed3, 499,  #
+    0x1ed5, 499,  #
+    0x1ed7, 499,  #
+    0x1ed9, 499,  #
+    0x1edb, 499,  #
+    0x1edd, 499,  #
+    0x1edf, 499,  #
+    0x1ee1, 499,  #
+    0x1ee3, 499,  #
+    0x1ee5, 499,  #
+    0x1ee7, 499,  #
+    0x1ee9, 499,  #
+    0x1eeb, 499,  #
+    0x1eed, 499,  #
+    0x1eef, 499,  #
+    0x1ef1, 499,  #
+    0x1ef3, 499,  #
+    0x1ef5, 499,  #
+    0x1ef7, 499,  #
+    0x1ef9, 499,  #
+    0x1f51, 508,  #
+    0x1f53, 508,  #
+    0x1f55, 508,  #
+    0x1f57, 508,  #
+    0x1fb3, 509,  #
+    0x1fc3, 509,  #
+    0x1fe5, 507,  #
+    0x1ff3, 509]  #
 
   tolowerRanges = [
     0x0041,  0x005a, 532,  # A-Z a-z
-    0x00c0,  0x00d6, 532,  # - -   
-    0x00d8,  0x00de, 532,  # - -   
-    0x0189,  0x018a, 705,  # - -   
-    0x018e,  0x018f, 702,  # - -   
-    0x01b1,  0x01b2, 717,  # - -   
-    0x0388,  0x038a, 537,  # - -   
-    0x038e,  0x038f, 563,  # - -   
-    0x0391,  0x03a1, 532,  # - -   
-    0x03a3,  0x03ab, 532,  # - -   
-    0x0401,  0x040c, 580,  # - -   
-    0x040e,  0x040f, 580,  # - -   
-    0x0410,  0x042f, 532,  # - -   
-    0x0531,  0x0556, 548,  # - -   
-    0x10a0,  0x10c5, 548,  # - -   
-    0x1f08,  0x1f0f, 492,  # - -   
-    0x1f18,  0x1f1d, 492,  # - -   
-    0x1f28,  0x1f2f, 492,  # - -   
-    0x1f38,  0x1f3f, 492,  # - -   
-    0x1f48,  0x1f4d, 492,  # - -   
-    0x1f68,  0x1f6f, 492,  # - -   
-    0x1f88,  0x1f8f, 492,  # - -   
-    0x1f98,  0x1f9f, 492,  # - -   
-    0x1fa8,  0x1faf, 492,  # - -   
-    0x1fb8,  0x1fb9, 492,  # - -   
-    0x1fba,  0x1fbb, 426,  # - -   
-    0x1fc8,  0x1fcb, 414,  # - -   
-    0x1fd8,  0x1fd9, 492,  # - -   
-    0x1fda,  0x1fdb, 400,  # - -   
-    0x1fe8,  0x1fe9, 492,  # - -   
-    0x1fea,  0x1feb, 388,  # - -   
-    0x1ff8,  0x1ff9, 372,  # - -   
-    0x1ffa,  0x1ffb, 374,  # - -   
-    0x2160,  0x216f, 516,  # - -   
-    0x24b6,  0x24cf, 526,  # - -   
-    0xff21,  0xff3a, 532]  # - -   
+    0x00c0,  0x00d6, 532,  # - -
+    0x00d8,  0x00de, 532,  # - -
+    0x0189,  0x018a, 705,  # - -
+    0x018e,  0x018f, 702,  # - -
+    0x01b1,  0x01b2, 717,  # - -
+    0x0388,  0x038a, 537,  # - -
+    0x038e,  0x038f, 563,  # - -
+    0x0391,  0x03a1, 532,  # - -
+    0x03a3,  0x03ab, 532,  # - -
+    0x0401,  0x040c, 580,  # - -
+    0x040e,  0x040f, 580,  # - -
+    0x0410,  0x042f, 532,  # - -
+    0x0531,  0x0556, 548,  # - -
+    0x10a0,  0x10c5, 548,  # - -
+    0x1f08,  0x1f0f, 492,  # - -
+    0x1f18,  0x1f1d, 492,  # - -
+    0x1f28,  0x1f2f, 492,  # - -
+    0x1f38,  0x1f3f, 492,  # - -
+    0x1f48,  0x1f4d, 492,  # - -
+    0x1f68,  0x1f6f, 492,  # - -
+    0x1f88,  0x1f8f, 492,  # - -
+    0x1f98,  0x1f9f, 492,  # - -
+    0x1fa8,  0x1faf, 492,  # - -
+    0x1fb8,  0x1fb9, 492,  # - -
+    0x1fba,  0x1fbb, 426,  # - -
+    0x1fc8,  0x1fcb, 414,  # - -
+    0x1fd8,  0x1fd9, 492,  # - -
+    0x1fda,  0x1fdb, 400,  # - -
+    0x1fe8,  0x1fe9, 492,  # - -
+    0x1fea,  0x1feb, 388,  # - -
+    0x1ff8,  0x1ff9, 372,  # - -
+    0x1ffa,  0x1ffb, 374,  # - -
+    0x2160,  0x216f, 516,  # - -
+    0x24b6,  0x24cf, 526,  # - -
+    0xff21,  0xff3a, 532]  # - -
 
   tolowerSinglets = [
-    0x0100, 501,  #     
-    0x0102, 501,  #     
-    0x0104, 501,  #     
-    0x0106, 501,  #     
-    0x0108, 501,  #     
-    0x010a, 501,  #     
-    0x010c, 501,  #     
-    0x010e, 501,  #     
-    0x0110, 501,  #     
-    0x0112, 501,  #     
-    0x0114, 501,  #     
-    0x0116, 501,  #     
-    0x0118, 501,  #     
-    0x011a, 501,  #     
-    0x011c, 501,  #     
-    0x011e, 501,  #     
-    0x0120, 501,  #     
-    0x0122, 501,  #     
-    0x0124, 501,  #     
-    0x0126, 501,  #     
-    0x0128, 501,  #     
-    0x012a, 501,  #     
-    0x012c, 501,  #     
-    0x012e, 501,  #     
-    0x0130, 301,  #  i   
-    0x0132, 501,  #     
-    0x0134, 501,  #     
-    0x0136, 501,  #     
-    0x0139, 501,  #     
-    0x013b, 501,  #     
-    0x013d, 501,  #     
-    0x013f, 501,  #     
-    0x0141, 501,  #     
-    0x0143, 501,  #     
-    0x0145, 501,  #     
-    0x0147, 501,  #     
-    0x014a, 501,  #     
-    0x014c, 501,  #     
-    0x014e, 501,  #     
-    0x0150, 501,  #     
-    0x0152, 501,  #     
-    0x0154, 501,  #     
-    0x0156, 501,  #     
-    0x0158, 501,  #     
-    0x015a, 501,  #     
-    0x015c, 501,  #     
-    0x015e, 501,  #     
-    0x0160, 501,  #     
-    0x0162, 501,  #     
-    0x0164, 501,  #     
-    0x0166, 501,  #     
-    0x0168, 501,  #     
-    0x016a, 501,  #     
-    0x016c, 501,  #     
-    0x016e, 501,  #     
-    0x0170, 501,  #     
-    0x0172, 501,  #     
-    0x0174, 501,  #     
-    0x0176, 501,  #     
-    0x0178, 379,  #     
-    0x0179, 501,  #     
-    0x017b, 501,  #     
-    0x017d, 501,  #     
-    0x0181, 710,  #     
-    0x0182, 501,  #     
-    0x0184, 501,  #     
-    0x0186, 706,  #     
-    0x0187, 501,  #     
-    0x018b, 501,  #     
-    0x0190, 703,  #     
-    0x0191, 501,  #     
-    0x0193, 705,  #     
-    0x0194, 707,  #     
-    0x0196, 711,  #     
-    0x0197, 709,  #     
-    0x0198, 501,  #     
-    0x019c, 711,  #     
-    0x019d, 713,  #     
-    0x01a0, 501,  #     
-    0x01a2, 501,  #     
-    0x01a4, 501,  #     
-    0x01a7, 501,  #     
-    0x01a9, 718,  #     
-    0x01ac, 501,  #     
-    0x01ae, 718,  #     
-    0x01af, 501,  #     
-    0x01b3, 501,  #     
-    0x01b5, 501,  #     
-    0x01b7, 719,  #     
-    0x01b8, 501,  #     
-    0x01bc, 501,  #     
-    0x01c4, 502,  #     
-    0x01c5, 501,  #     
-    0x01c7, 502,  #     
-    0x01c8, 501,  #     
-    0x01ca, 502,  #     
-    0x01cb, 501,  #     
-    0x01cd, 501,  #     
-    0x01cf, 501,  #     
-    0x01d1, 501,  #     
-    0x01d3, 501,  #     
-    0x01d5, 501,  #     
-    0x01d7, 501,  #     
-    0x01d9, 501,  #     
-    0x01db, 501,  #     
-    0x01de, 501,  #     
-    0x01e0, 501,  #     
-    0x01e2, 501,  #     
-    0x01e4, 501,  #     
-    0x01e6, 501,  #     
-    0x01e8, 501,  #     
-    0x01ea, 501,  #     
-    0x01ec, 501,  #     
-    0x01ee, 501,  #     
-    0x01f1, 502,  #     
-    0x01f2, 501,  #     
-    0x01f4, 501,  #     
-    0x01fa, 501,  #     
-    0x01fc, 501,  #     
-    0x01fe, 501,  #     
-    0x0200, 501,  #     
-    0x0202, 501,  #     
-    0x0204, 501,  #     
-    0x0206, 501,  #     
-    0x0208, 501,  #     
-    0x020a, 501,  #     
-    0x020c, 501,  #     
-    0x020e, 501,  #     
-    0x0210, 501,  #     
-    0x0212, 501,  #     
-    0x0214, 501,  #     
-    0x0216, 501,  #     
-    0x0386, 538,  #     
-    0x038c, 564,  #     
-    0x03e2, 501,  #     
-    0x03e4, 501,  #     
-    0x03e6, 501,  #     
-    0x03e8, 501,  #     
-    0x03ea, 501,  #     
-    0x03ec, 501,  #     
-    0x03ee, 501,  #     
-    0x0460, 501,  #     
-    0x0462, 501,  #     
-    0x0464, 501,  #     
-    0x0466, 501,  #     
-    0x0468, 501,  #     
-    0x046a, 501,  #     
-    0x046c, 501,  #     
-    0x046e, 501,  #     
-    0x0470, 501,  #     
-    0x0472, 501,  #     
-    0x0474, 501,  #     
-    0x0476, 501,  #     
-    0x0478, 501,  #     
-    0x047a, 501,  #     
-    0x047c, 501,  #     
-    0x047e, 501,  #     
-    0x0480, 501,  #     
-    0x0490, 501,  #     
-    0x0492, 501,  #     
-    0x0494, 501,  #     
-    0x0496, 501,  #     
-    0x0498, 501,  #     
-    0x049a, 501,  #     
-    0x049c, 501,  #     
-    0x049e, 501,  #     
-    0x04a0, 501,  #     
-    0x04a2, 501,  #     
-    0x04a4, 501,  #     
-    0x04a6, 501,  #     
-    0x04a8, 501,  #     
-    0x04aa, 501,  #     
-    0x04ac, 501,  #     
-    0x04ae, 501,  #     
-    0x04b0, 501,  #     
-    0x04b2, 501,  #     
-    0x04b4, 501,  #     
-    0x04b6, 501,  #     
-    0x04b8, 501,  #     
-    0x04ba, 501,  #     
-    0x04bc, 501,  #     
-    0x04be, 501,  #     
-    0x04c1, 501,  #     
-    0x04c3, 501,  #     
-    0x04c7, 501,  #     
-    0x04cb, 501,  #     
-    0x04d0, 501,  #     
-    0x04d2, 501,  #     
-    0x04d4, 501,  #     
-    0x04d6, 501,  #     
-    0x04d8, 501,  #     
-    0x04da, 501,  #     
-    0x04dc, 501,  #     
-    0x04de, 501,  #     
-    0x04e0, 501,  #     
-    0x04e2, 501,  #     
-    0x04e4, 501,  #     
-    0x04e6, 501,  #     
-    0x04e8, 501,  #     
-    0x04ea, 501,  #     
-    0x04ee, 501,  #     
-    0x04f0, 501,  #     
-    0x04f2, 501,  #     
-    0x04f4, 501,  #     
-    0x04f8, 501,  #     
-    0x1e00, 501,  #     
-    0x1e02, 501,  #     
-    0x1e04, 501,  #     
-    0x1e06, 501,  #     
-    0x1e08, 501,  #     
-    0x1e0a, 501,  #     
-    0x1e0c, 501,  #     
-    0x1e0e, 501,  #     
-    0x1e10, 501,  #     
-    0x1e12, 501,  #     
-    0x1e14, 501,  #     
-    0x1e16, 501,  #     
-    0x1e18, 501,  #     
-    0x1e1a, 501,  #     
-    0x1e1c, 501,  #     
-    0x1e1e, 501,  #     
-    0x1e20, 501,  #     
-    0x1e22, 501,  #     
-    0x1e24, 501,  #     
-    0x1e26, 501,  #     
-    0x1e28, 501,  #     
-    0x1e2a, 501,  #     
-    0x1e2c, 501,  #     
-    0x1e2e, 501,  #     
-    0x1e30, 501,  #     
-    0x1e32, 501,  #     
-    0x1e34, 501,  #     
-    0x1e36, 501,  #     
-    0x1e38, 501,  #     
-    0x1e3a, 501,  #     
-    0x1e3c, 501,  #     
-    0x1e3e, 501,  #     
-    0x1e40, 501,  #     
-    0x1e42, 501,  #     
-    0x1e44, 501,  #     
-    0x1e46, 501,  #     
-    0x1e48, 501,  #     
-    0x1e4a, 501,  #     
-    0x1e4c, 501,  #     
-    0x1e4e, 501,  #     
-    0x1e50, 501,  #     
-    0x1e52, 501,  #     
-    0x1e54, 501,  #     
-    0x1e56, 501,  #     
-    0x1e58, 501,  #     
-    0x1e5a, 501,  #     
-    0x1e5c, 501,  #     
-    0x1e5e, 501,  #     
-    0x1e60, 501,  #     
-    0x1e62, 501,  #     
-    0x1e64, 501,  #     
-    0x1e66, 501,  #     
-    0x1e68, 501,  #     
-    0x1e6a, 501,  #     
-    0x1e6c, 501,  #     
-    0x1e6e, 501,  #     
-    0x1e70, 501,  #     
-    0x1e72, 501,  #     
-    0x1e74, 501,  #     
-    0x1e76, 501,  #     
-    0x1e78, 501,  #     
-    0x1e7a, 501,  #     
-    0x1e7c, 501,  #     
-    0x1e7e, 501,  #     
-    0x1e80, 501,  #     
-    0x1e82, 501,  #     
-    0x1e84, 501,  #     
-    0x1e86, 501,  #     
-    0x1e88, 501,  #     
-    0x1e8a, 501,  #     
-    0x1e8c, 501,  #     
-    0x1e8e, 501,  #     
-    0x1e90, 501,  #     
-    0x1e92, 501,  #     
-    0x1e94, 501,  #     
-    0x1ea0, 501,  #     
-    0x1ea2, 501,  #     
-    0x1ea4, 501,  #     
-    0x1ea6, 501,  #     
-    0x1ea8, 501,  #     
-    0x1eaa, 501,  #     
-    0x1eac, 501,  #     
-    0x1eae, 501,  #     
-    0x1eb0, 501,  #     
-    0x1eb2, 501,  #     
-    0x1eb4, 501,  #     
-    0x1eb6, 501,  #     
-    0x1eb8, 501,  #     
-    0x1eba, 501,  #     
-    0x1ebc, 501,  #     
-    0x1ebe, 501,  #     
-    0x1ec0, 501,  #     
-    0x1ec2, 501,  #     
-    0x1ec4, 501,  #     
-    0x1ec6, 501,  #     
-    0x1ec8, 501,  #     
-    0x1eca, 501,  #     
-    0x1ecc, 501,  #     
-    0x1ece, 501,  #     
-    0x1ed0, 501,  #     
-    0x1ed2, 501,  #     
-    0x1ed4, 501,  #     
-    0x1ed6, 501,  #     
-    0x1ed8, 501,  #     
-    0x1eda, 501,  #     
-    0x1edc, 501,  #     
-    0x1ede, 501,  #     
-    0x1ee0, 501,  #     
-    0x1ee2, 501,  #     
-    0x1ee4, 501,  #     
-    0x1ee6, 501,  #     
-    0x1ee8, 501,  #     
-    0x1eea, 501,  #     
-    0x1eec, 501,  #     
-    0x1eee, 501,  #     
-    0x1ef0, 501,  #     
-    0x1ef2, 501,  #     
-    0x1ef4, 501,  #     
-    0x1ef6, 501,  #     
-    0x1ef8, 501,  #     
-    0x1f59, 492,  #     
-    0x1f5b, 492,  #     
-    0x1f5d, 492,  #     
-    0x1f5f, 492,  #     
-    0x1fbc, 491,  #     
-    0x1fcc, 491,  #     
-    0x1fec, 493,  #     
-    0x1ffc, 491]  #     
+    0x0100, 501,  #
+    0x0102, 501,  #
+    0x0104, 501,  #
+    0x0106, 501,  #
+    0x0108, 501,  #
+    0x010a, 501,  #
+    0x010c, 501,  #
+    0x010e, 501,  #
+    0x0110, 501,  #
+    0x0112, 501,  #
+    0x0114, 501,  #
+    0x0116, 501,  #
+    0x0118, 501,  #
+    0x011a, 501,  #
+    0x011c, 501,  #
+    0x011e, 501,  #
+    0x0120, 501,  #
+    0x0122, 501,  #
+    0x0124, 501,  #
+    0x0126, 501,  #
+    0x0128, 501,  #
+    0x012a, 501,  #
+    0x012c, 501,  #
+    0x012e, 501,  #
+    0x0130, 301,  #  i
+    0x0132, 501,  #
+    0x0134, 501,  #
+    0x0136, 501,  #
+    0x0139, 501,  #
+    0x013b, 501,  #
+    0x013d, 501,  #
+    0x013f, 501,  #
+    0x0141, 501,  #
+    0x0143, 501,  #
+    0x0145, 501,  #
+    0x0147, 501,  #
+    0x014a, 501,  #
+    0x014c, 501,  #
+    0x014e, 501,  #
+    0x0150, 501,  #
+    0x0152, 501,  #
+    0x0154, 501,  #
+    0x0156, 501,  #
+    0x0158, 501,  #
+    0x015a, 501,  #
+    0x015c, 501,  #
+    0x015e, 501,  #
+    0x0160, 501,  #
+    0x0162, 501,  #
+    0x0164, 501,  #
+    0x0166, 501,  #
+    0x0168, 501,  #
+    0x016a, 501,  #
+    0x016c, 501,  #
+    0x016e, 501,  #
+    0x0170, 501,  #
+    0x0172, 501,  #
+    0x0174, 501,  #
+    0x0176, 501,  #
+    0x0178, 379,  #
+    0x0179, 501,  #
+    0x017b, 501,  #
+    0x017d, 501,  #
+    0x0181, 710,  #
+    0x0182, 501,  #
+    0x0184, 501,  #
+    0x0186, 706,  #
+    0x0187, 501,  #
+    0x018b, 501,  #
+    0x0190, 703,  #
+    0x0191, 501,  #
+    0x0193, 705,  #
+    0x0194, 707,  #
+    0x0196, 711,  #
+    0x0197, 709,  #
+    0x0198, 501,  #
+    0x019c, 711,  #
+    0x019d, 713,  #
+    0x01a0, 501,  #
+    0x01a2, 501,  #
+    0x01a4, 501,  #
+    0x01a7, 501,  #
+    0x01a9, 718,  #
+    0x01ac, 501,  #
+    0x01ae, 718,  #
+    0x01af, 501,  #
+    0x01b3, 501,  #
+    0x01b5, 501,  #
+    0x01b7, 719,  #
+    0x01b8, 501,  #
+    0x01bc, 501,  #
+    0x01c4, 502,  #
+    0x01c5, 501,  #
+    0x01c7, 502,  #
+    0x01c8, 501,  #
+    0x01ca, 502,  #
+    0x01cb, 501,  #
+    0x01cd, 501,  #
+    0x01cf, 501,  #
+    0x01d1, 501,  #
+    0x01d3, 501,  #
+    0x01d5, 501,  #
+    0x01d7, 501,  #
+    0x01d9, 501,  #
+    0x01db, 501,  #
+    0x01de, 501,  #
+    0x01e0, 501,  #
+    0x01e2, 501,  #
+    0x01e4, 501,  #
+    0x01e6, 501,  #
+    0x01e8, 501,  #
+    0x01ea, 501,  #
+    0x01ec, 501,  #
+    0x01ee, 501,  #
+    0x01f1, 502,  #
+    0x01f2, 501,  #
+    0x01f4, 501,  #
+    0x01fa, 501,  #
+    0x01fc, 501,  #
+    0x01fe, 501,  #
+    0x0200, 501,  #
+    0x0202, 501,  #
+    0x0204, 501,  #
+    0x0206, 501,  #
+    0x0208, 501,  #
+    0x020a, 501,  #
+    0x020c, 501,  #
+    0x020e, 501,  #
+    0x0210, 501,  #
+    0x0212, 501,  #
+    0x0214, 501,  #
+    0x0216, 501,  #
+    0x0386, 538,  #
+    0x038c, 564,  #
+    0x03e2, 501,  #
+    0x03e4, 501,  #
+    0x03e6, 501,  #
+    0x03e8, 501,  #
+    0x03ea, 501,  #
+    0x03ec, 501,  #
+    0x03ee, 501,  #
+    0x0460, 501,  #
+    0x0462, 501,  #
+    0x0464, 501,  #
+    0x0466, 501,  #
+    0x0468, 501,  #
+    0x046a, 501,  #
+    0x046c, 501,  #
+    0x046e, 501,  #
+    0x0470, 501,  #
+    0x0472, 501,  #
+    0x0474, 501,  #
+    0x0476, 501,  #
+    0x0478, 501,  #
+    0x047a, 501,  #
+    0x047c, 501,  #
+    0x047e, 501,  #
+    0x0480, 501,  #
+    0x0490, 501,  #
+    0x0492, 501,  #
+    0x0494, 501,  #
+    0x0496, 501,  #
+    0x0498, 501,  #
+    0x049a, 501,  #
+    0x049c, 501,  #
+    0x049e, 501,  #
+    0x04a0, 501,  #
+    0x04a2, 501,  #
+    0x04a4, 501,  #
+    0x04a6, 501,  #
+    0x04a8, 501,  #
+    0x04aa, 501,  #
+    0x04ac, 501,  #
+    0x04ae, 501,  #
+    0x04b0, 501,  #
+    0x04b2, 501,  #
+    0x04b4, 501,  #
+    0x04b6, 501,  #
+    0x04b8, 501,  #
+    0x04ba, 501,  #
+    0x04bc, 501,  #
+    0x04be, 501,  #
+    0x04c1, 501,  #
+    0x04c3, 501,  #
+    0x04c7, 501,  #
+    0x04cb, 501,  #
+    0x04d0, 501,  #
+    0x04d2, 501,  #
+    0x04d4, 501,  #
+    0x04d6, 501,  #
+    0x04d8, 501,  #
+    0x04da, 501,  #
+    0x04dc, 501,  #
+    0x04de, 501,  #
+    0x04e0, 501,  #
+    0x04e2, 501,  #
+    0x04e4, 501,  #
+    0x04e6, 501,  #
+    0x04e8, 501,  #
+    0x04ea, 501,  #
+    0x04ee, 501,  #
+    0x04f0, 501,  #
+    0x04f2, 501,  #
+    0x04f4, 501,  #
+    0x04f8, 501,  #
+    0x1e00, 501,  #
+    0x1e02, 501,  #
+    0x1e04, 501,  #
+    0x1e06, 501,  #
+    0x1e08, 501,  #
+    0x1e0a, 501,  #
+    0x1e0c, 501,  #
+    0x1e0e, 501,  #
+    0x1e10, 501,  #
+    0x1e12, 501,  #
+    0x1e14, 501,  #
+    0x1e16, 501,  #
+    0x1e18, 501,  #
+    0x1e1a, 501,  #
+    0x1e1c, 501,  #
+    0x1e1e, 501,  #
+    0x1e20, 501,  #
+    0x1e22, 501,  #
+    0x1e24, 501,  #
+    0x1e26, 501,  #
+    0x1e28, 501,  #
+    0x1e2a, 501,  #
+    0x1e2c, 501,  #
+    0x1e2e, 501,  #
+    0x1e30, 501,  #
+    0x1e32, 501,  #
+    0x1e34, 501,  #
+    0x1e36, 501,  #
+    0x1e38, 501,  #
+    0x1e3a, 501,  #
+    0x1e3c, 501,  #
+    0x1e3e, 501,  #
+    0x1e40, 501,  #
+    0x1e42, 501,  #
+    0x1e44, 501,  #
+    0x1e46, 501,  #
+    0x1e48, 501,  #
+    0x1e4a, 501,  #
+    0x1e4c, 501,  #
+    0x1e4e, 501,  #
+    0x1e50, 501,  #
+    0x1e52, 501,  #
+    0x1e54, 501,  #
+    0x1e56, 501,  #
+    0x1e58, 501,  #
+    0x1e5a, 501,  #
+    0x1e5c, 501,  #
+    0x1e5e, 501,  #
+    0x1e60, 501,  #
+    0x1e62, 501,  #
+    0x1e64, 501,  #
+    0x1e66, 501,  #
+    0x1e68, 501,  #
+    0x1e6a, 501,  #
+    0x1e6c, 501,  #
+    0x1e6e, 501,  #
+    0x1e70, 501,  #
+    0x1e72, 501,  #
+    0x1e74, 501,  #
+    0x1e76, 501,  #
+    0x1e78, 501,  #
+    0x1e7a, 501,  #
+    0x1e7c, 501,  #
+    0x1e7e, 501,  #
+    0x1e80, 501,  #
+    0x1e82, 501,  #
+    0x1e84, 501,  #
+    0x1e86, 501,  #
+    0x1e88, 501,  #
+    0x1e8a, 501,  #
+    0x1e8c, 501,  #
+    0x1e8e, 501,  #
+    0x1e90, 501,  #
+    0x1e92, 501,  #
+    0x1e94, 501,  #
+    0x1ea0, 501,  #
+    0x1ea2, 501,  #
+    0x1ea4, 501,  #
+    0x1ea6, 501,  #
+    0x1ea8, 501,  #
+    0x1eaa, 501,  #
+    0x1eac, 501,  #
+    0x1eae, 501,  #
+    0x1eb0, 501,  #
+    0x1eb2, 501,  #
+    0x1eb4, 501,  #
+    0x1eb6, 501,  #
+    0x1eb8, 501,  #
+    0x1eba, 501,  #
+    0x1ebc, 501,  #
+    0x1ebe, 501,  #
+    0x1ec0, 501,  #
+    0x1ec2, 501,  #
+    0x1ec4, 501,  #
+    0x1ec6, 501,  #
+    0x1ec8, 501,  #
+    0x1eca, 501,  #
+    0x1ecc, 501,  #
+    0x1ece, 501,  #
+    0x1ed0, 501,  #
+    0x1ed2, 501,  #
+    0x1ed4, 501,  #
+    0x1ed6, 501,  #
+    0x1ed8, 501,  #
+    0x1eda, 501,  #
+    0x1edc, 501,  #
+    0x1ede, 501,  #
+    0x1ee0, 501,  #
+    0x1ee2, 501,  #
+    0x1ee4, 501,  #
+    0x1ee6, 501,  #
+    0x1ee8, 501,  #
+    0x1eea, 501,  #
+    0x1eec, 501,  #
+    0x1eee, 501,  #
+    0x1ef0, 501,  #
+    0x1ef2, 501,  #
+    0x1ef4, 501,  #
+    0x1ef6, 501,  #
+    0x1ef8, 501,  #
+    0x1f59, 492,  #
+    0x1f5b, 492,  #
+    0x1f5d, 492,  #
+    0x1f5f, 492,  #
+    0x1fbc, 491,  #
+    0x1fcc, 491,  #
+    0x1fec, 493,  #
+    0x1ffc, 491]  #
 
   toTitleSinglets = [
-    0x01c4, 501,  #     
-    0x01c6, 499,  #     
-    0x01c7, 501,  #     
-    0x01c9, 499,  #     
-    0x01ca, 501,  #     
-    0x01cc, 499,  #     
-    0x01f1, 501,  #     
-    0x01f3, 499]  #     
+    0x01c4, 501,  #
+    0x01c6, 499,  #
+    0x01c7, 501,  #
+    0x01c9, 499,  #
+    0x01ca, 501,  #
+    0x01cc, 499,  #
+    0x01f1, 501,  #
+    0x01f3, 499]  #
 
-proc binarySearch(c: RuneImpl, tab: openArray[RuneImpl], len, stride: int): int = 
+proc binarySearch(c: RuneImpl, tab: openArray[RuneImpl], len, stride: int): int =
   var n = len
   var t = 0
-  while n > 1: 
+  while n > 1:
     var m = n div 2
     var p = t + m*stride
     if c >= tab[p]:
@@ -1117,9 +1156,9 @@ proc binarySearch(c: RuneImpl, tab: openArray[RuneImpl], len, stride: int): int
     return t
   return -1
 
-proc toLower*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} = 
+proc toLower*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
   ## Converts `c` into lower case. This works for any Unicode character.
-  ## If possible, prefer `toLower` over `toUpper`. 
+  ## If possible, prefer `toLower` over `toUpper`.
   var c = RuneImpl(c)
   var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3)
   if p >= 0 and c >= tolowerRanges[p] and c <= tolowerRanges[p+1]:
@@ -1129,9 +1168,9 @@ proc toLower*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
     return Rune(c + tolowerSinglets[p+1] - 500)
   return Rune(c)
 
-proc toUpper*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} = 
+proc toUpper*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
   ## Converts `c` into upper case. This works for any Unicode character.
-  ## If possible, prefer `toLower` over `toUpper`. 
+  ## If possible, prefer `toLower` over `toUpper`.
   var c = RuneImpl(c)
   var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3)
   if p >= 0 and c >= toupperRanges[p] and c <= toupperRanges[p+1]:
@@ -1141,16 +1180,16 @@ proc toUpper*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
     return Rune(c + toupperSinglets[p+1] - 500)
   return Rune(c)
 
-proc toTitle*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} = 
+proc toTitle*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
   var c = RuneImpl(c)
   var p = binarySearch(c, toTitleSinglets, len(toTitleSinglets) div 2, 2)
   if p >= 0 and c == toTitleSinglets[p]:
     return Rune(c + toTitleSinglets[p+1] - 500)
   return Rune(c)
 
-proc isLower*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = 
+proc isLower*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
   ## returns true iff `c` is a lower case Unicode character
-  ## If possible, prefer `isLower` over `isUpper`. 
+  ## If possible, prefer `isLower` over `isUpper`.
   var c = RuneImpl(c)
   # Note: toUpperRanges is correct here!
   var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3)
@@ -1160,9 +1199,9 @@ proc isLower*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
   if p >= 0 and c == toupperSinglets[p]:
     return true
 
-proc isUpper*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = 
+proc isUpper*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
   ## returns true iff `c` is a upper case Unicode character
-  ## If possible, prefer `isLower` over `isUpper`. 
+  ## If possible, prefer `isLower` over `isUpper`.
   var c = RuneImpl(c)
   # Note: toLowerRanges is correct here!
   var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3)
@@ -1172,9 +1211,9 @@ proc isUpper*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
   if p >= 0 and c == tolowerSinglets[p]:
     return true
 
-proc isAlpha*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = 
+proc isAlpha*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
   ## returns true iff `c` is an *alpha* Unicode character (i.e. a letter)
-  if isUpper(c) or isLower(c): 
+  if isUpper(c) or isLower(c):
     return true
   var c = RuneImpl(c)
   var p = binarySearch(c, alphaRanges, len(alphaRanges) div 2, 2)
@@ -1183,17 +1222,28 @@ proc isAlpha*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
   p = binarySearch(c, alphaSinglets, len(alphaSinglets), 1)
   if p >= 0 and c == alphaSinglets[p]:
     return true
-  
-proc isTitle*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = 
+
+proc isTitle*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
   return isUpper(c) and isLower(c)
 
-proc isWhiteSpace*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = 
+proc isWhiteSpace*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
   ## returns true iff `c` is a Unicode whitespace character
   var c = RuneImpl(c)
   var p = binarySearch(c, spaceRanges, len(spaceRanges) div 2, 2)
   if p >= 0 and c >= spaceRanges[p] and c <= spaceRanges[p+1]:
     return true
 
+proc isCombining*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
+  ## returns true iff `c` is a Unicode combining character
+  var c = RuneImpl(c)
+
+  # Optimized to return false immediately for ASCII
+  return c >= 0x0300 and (c <= 0x036f or
+    (c >= 0x1ab0 and c <= 0x1aff) or
+    (c >= 0x1dc0 and c <= 0x1dff) or
+    (c >= 0x20d0 and c <= 0x20ff) or
+    (c >= 0xfe20 and c <= 0xfe2f))
+
 iterator runes*(s: string): Rune =
   ## iterates over any unicode character of the string `s`.
   var
@@ -1203,7 +1253,7 @@ iterator runes*(s: string): Rune =
     fastRuneAt(s, i, result, true)
     yield result
 
-proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} = 
+proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} =
   ## compares two UTF8 strings and ignores the case. Returns:
   ##
   ## | 0 iff a == b
@@ -1220,9 +1270,49 @@ proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} =
     if result != 0: return
   result = a.len - b.len
 
+proc reversed*(s: string): string =
+  ## returns the reverse of `s`, interpreting it as unicode characters. Unicode
+  ## combining characters are correctly interpreted as well:
+  ##
+  ## .. code-block:: nim
+  ##
+  ##   assert reversed("Reverse this!") == "!siht esreveR"
+  ##   assert reversed("先秦兩漢") == "漢兩秦先"
+  ##   assert reversed("as⃝df̅") == "f̅ds⃝a"
+  ##   assert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
+  var
+    i = 0
+    lastI = 0
+    newPos = len(s) - 1
+    blockPos = 0
+    r: Rune
+
+  template reverseUntil(pos): stmt =
+    var j = pos - 1
+    while j > blockPos:
+      result[newPos] = s[j]
+      dec j
+      dec newPos
+    blockPos = pos - 1
+
+  result = newString(len(s))
+
+  while i < len(s):
+    lastI = i
+    fastRuneAt(s, i, r, true)
+    if not isCombining(r):
+      reverseUntil(lastI)
+
+  reverseUntil(len(s))
+
 when isMainModule:
   let
     someString = "öÑ"
     someRunes = @[runeAt(someString, 0), runeAt(someString, 2)]
     compared = (someString == $someRunes)
   assert compared == true
+
+  assert reversed("Reverse this!") == "!siht esreveR"
+  assert reversed("先秦兩漢") == "漢兩秦先"
+  assert reversed("as⃝df̅") == "f̅ds⃝a"
+  assert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
diff --git a/lib/pure/unidecode/unidecode.nim b/lib/pure/unidecode/unidecode.nim
index 798eef5d0..a83b9be0f 100644
--- a/lib/pure/unidecode/unidecode.nim
+++ b/lib/pure/unidecode/unidecode.nim
@@ -70,5 +70,5 @@ proc unidecode*(s: string): string =
 
 when isMainModule:
   loadUnidecodeTable("lib/pure/unidecode/unidecode.dat")
-  echo unidecode("Äußerst")
+  assert unidecode("Äußerst") == "Ausserst"
 
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index 21efea3bc..3bf4724b9 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2012 Nim Contributors
+#        (c) Copyright 2015 Nim Contributors
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -9,12 +9,27 @@
 
 ## :Author: Zahary Karadjov
 ##
-## This module implements the standard unit testing facilities such as
-## suites, fixtures and test cases as well as facilities for combinatorial 
-## and randomzied test case generation (not yet available) 
-## and object mocking (not yet available)
+## This module implements boilerplate to make testing easy.
 ##
-## It is loosely based on C++'s boost.test and Haskell's QuickTest
+## Example:
+##
+## .. code:: nim
+##
+##   suite "description for this stuff":
+##     test "essential truths":
+##       # give up and stop if this fails
+##       require(true)
+##
+##     test "slightly less obvious stuff":
+##       # print a nasty message and move on, skipping
+##       # the remainder of this block
+##       check(1 != 1)
+##       check("asd"[2] == 'd')
+##
+##     test "out of bounds error is thrown on bad access":
+##       let v = @[1, 2, 3]  # you can do initialization here
+##       expect(IndexError):
+##         discard v[4]
 
 import
   macros
@@ -24,6 +39,7 @@ when declared(stdout):
 
 when not defined(ECMAScript):
   import terminal
+  system.addQuitProc(resetAttributes)
 
 type
   TestStatus* = enum OK, FAILED
@@ -31,7 +47,7 @@ type
 
 {.deprecated: [TTestStatus: TestStatus, TOutputLevel: OutputLevel]}
 
-var 
+var
   abortOnError* {.threadvar.}: bool
   outputLevel* {.threadvar.}: OutputLevel
   colorOutput* {.threadvar.}: bool
@@ -84,6 +100,7 @@ template test*(name: expr, body: stmt): stmt {.immediate, dirty.} =
 
     except:
       checkpoint("Unhandled exception: " & getCurrentExceptionMsg())
+      echo getCurrentException().getStackTrace()
       fail()
 
     finally:
@@ -127,16 +144,25 @@ macro check*(conditions: stmt): stmt {.immediate.} =
     when compiles(string($value)):
       checkpoint(name & " was " & $value)
 
-  proc inspectArgs(exp: PNimrodNode) =
+  proc inspectArgs(exp: NimNode) =
     for i in 1 .. <exp.len:
       if exp[i].kind notin nnkLiterals:
         inc counter
         var arg = newIdentNode(":p" & $counter)
         var argStr = exp[i].toStrLit
+        var paramAst = exp[i]
         if exp[i].kind in nnkCallKinds: inspectArgs(exp[i])
-        argsAsgns.add getAst(asgn(arg, exp[i]))
+        if exp[i].kind == nnkExprEqExpr:
+          # ExprEqExpr
+          #   Ident !"v"
+          #   IntLit 2
+          paramAst = exp[i][1]
+        argsAsgns.add getAst(asgn(arg, paramAst))
         argsPrintOuts.add getAst(print(argStr, arg))
-        exp[i] = arg
+        if exp[i].kind != nnkExprEqExpr:
+          exp[i] = arg
+        else:
+          exp[i][1] = arg
 
   case checked.kind
   of nnkCallKinds:
@@ -176,7 +202,7 @@ template require*(conditions: stmt): stmt {.immediate, dirty.} =
 macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
   let exp = callsite()
   template expectBody(errorTypes, lineInfoLit: expr,
-                      body: stmt): PNimrodNode {.dirty.} =
+                      body: stmt): NimNode {.dirty.} =
     try:
       body
       checkpoint(lineInfoLit & ": Expect Failed, no exception was thrown.")
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index 368802dc2..1890a9bf4 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -16,9 +16,11 @@ type
   Uri* = object
     scheme*, username*, password*: string 
     hostname*, port*, path*, query*, anchor*: string
+    opaque*: bool
 
 {.deprecated: [TUrl: Url, TUri: Uri].}
 
+{.push warning[deprecated]: off.}
 proc `$`*(url: Url): string {.deprecated.} =
   ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   return string(url)
@@ -43,6 +45,7 @@ proc add*(url: var Url, a: Url) {.deprecated.} =
   ##
   ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   url = url / a
+{.pop.}
 
 proc parseAuthority(authority: string, result: var Uri) =
   var i = 0
@@ -50,10 +53,10 @@ proc parseAuthority(authority: string, result: var Uri) =
   while true:
     case authority[i]
     of '@':
-      result.password = result.port
-      result.port = ""
-      result.username = result.hostname
-      result.hostname = ""
+      swap result.password, result.port
+      result.port.setLen(0)
+      swap result.username, result.hostname
+      result.hostname.setLen(0)
       inPort = false
     of ':':
       inPort = true
@@ -72,7 +75,7 @@ proc parsePath(uri: string, i: var int, result: var Uri) =
   # The 'mailto' scheme's PATH actually contains the hostname/username
   if result.scheme.toLower == "mailto":
     parseAuthority(result.path, result)
-    result.path = ""
+    result.path.setLen(0)
 
   if uri[i] == '?':
     i.inc # Skip '?'
@@ -82,13 +85,21 @@ proc parsePath(uri: string, i: var int, result: var Uri) =
     i.inc # Skip '#'
     i.inc parseUntil(uri, result.anchor, {}, i)
 
-proc initUri(): Uri =
+proc initUri*(): Uri =
+  ## Initializes a URI.
   result = Uri(scheme: "", username: "", password: "", hostname: "", port: "",
                 path: "", query: "", anchor: "")
 
-proc parseUri*(uri: string): Uri =
-  ## Parses a URI.
-  result = initUri()
+proc resetUri(uri: var Uri) =
+  for f in uri.fields:
+    when f is string:
+      f.setLen(0)
+    else:
+      f = false
+
+proc parseUri*(uri: string, result: var Uri) =
+  ## Parses a URI. The `result` variable will be cleared before.
+  resetUri(result)
 
   var i = 0
 
@@ -102,7 +113,7 @@ proc parseUri*(uri: string): Uri =
   if uri[i] != ':':
     # Assume this is a reference URI (relative URI)
     i = 0
-    result.scheme = ""
+    result.scheme.setLen(0)
     parsePath(uri, i, result)
     return
   i.inc # Skip ':'
@@ -115,10 +126,17 @@ proc parseUri*(uri: string): Uri =
     if authority == "":
       raise newException(ValueError, "Expected authority got nothing.")
     parseAuthority(authority, result)
+  else:
+    result.opaque = true
 
   # Path
   parsePath(uri, i, result)
 
+proc parseUri*(uri: string): Uri =
+  ## Parses a URI and returns it.
+  result = initUri()
+  parseUri(uri, result)
+
 proc removeDotSegments(path: string): string =
   var collection: seq[string] = @[]
   let endsWithSlash = path[path.len-1] == '/'
@@ -179,10 +197,10 @@ proc combine*(base: Uri, reference: Uri): Uri =
   ##   assert foo.path == "/baz"
   ##
   ##   let bar = combine(parseUri("http://example.com/foo/bar"), parseUri("baz"))
-  ##   assert foo.path == "/foo/baz"
+  ##   assert bar.path == "/foo/baz"
   ##
   ##   let bar = combine(parseUri("http://example.com/foo/bar/"), parseUri("baz"))
-  ##   assert foo.path == "/foo/bar/baz"
+  ##   assert bar.path == "/foo/bar/baz"
   
   template setAuthority(dest, src: expr): stmt =
     dest.hostname = src.hostname
@@ -236,10 +254,10 @@ proc `/`*(x: Uri, path: string): Uri =
   ##   assert foo.path == "/foo/bar/baz"
   ##
   ##   let bar = parseUri("http://example.com/foo/bar") / parseUri("baz")
-  ##   assert foo.path == "/foo/bar/baz"
+  ##   assert bar.path == "/foo/bar/baz"
   ##
   ##   let bar = parseUri("http://example.com/foo/bar/") / parseUri("baz")
-  ##   assert foo.path == "/foo/bar/baz"
+  ##   assert bar.path == "/foo/bar/baz"
   result = x
   if result.path[result.path.len-1] == '/':
     if path[0] == '/':
@@ -256,7 +274,10 @@ proc `$`*(u: Uri): string =
   result = ""
   if u.scheme.len > 0:
     result.add(u.scheme)
-    result.add("://")
+    if u.opaque:
+      result.add(":")
+    else:
+      result.add("://")
   if u.username.len > 0:
     result.add(u.username)
     if u.password.len > 0:
@@ -268,22 +289,38 @@ proc `$`*(u: Uri): string =
     result.add(":")
     result.add(u.port)
   if u.path.len > 0:
-    if u.path[0] != '/': result.add("/")
     result.add(u.path)
-  result.add(u.query)
-  result.add(u.anchor)
+  if u.query.len > 0:
+    result.add("?")
+    result.add(u.query)
+  if u.anchor.len > 0:
+    result.add("#")
+    result.add(u.anchor)
 
 when isMainModule:
   block:
-    let test = parseUri("http://localhost:8080/test")
+    let str = "http://localhost"
+    let test = parseUri(str)
+    doAssert test.path == ""
+
+  block:
+    let str = "http://localhost/"
+    let test = parseUri(str)
+    doAssert test.path == "/"
+
+  block:
+    let str = "http://localhost:8080/test"
+    let test = parseUri(str)
     doAssert test.scheme == "http"
     doAssert test.port == "8080"
     doAssert test.path == "/test"
     doAssert test.hostname == "localhost"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("foo://username:password@example.com:8042/over/there" &
-                        "/index.dtb?type=animal&name=narwhal#nose")
+    let str = "foo://username:password@example.com:8042/over/there" &
+              "/index.dtb?type=animal&name=narwhal#nose"
+    let test = parseUri(str)
     doAssert test.scheme == "foo"
     doAssert test.username == "username"
     doAssert test.password == "password"
@@ -292,34 +329,45 @@ when isMainModule:
     doAssert test.path == "/over/there/index.dtb"
     doAssert test.query == "type=animal&name=narwhal"
     doAssert test.anchor == "nose"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("urn:example:animal:ferret:nose")
+    let str = "urn:example:animal:ferret:nose"
+    let test = parseUri(str)
     doAssert test.scheme == "urn"
     doAssert test.path == "example:animal:ferret:nose"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("mailto:username@example.com?subject=Topic")
+    let str = "mailto:username@example.com?subject=Topic"
+    let test = parseUri(str)
     doAssert test.scheme == "mailto"
     doAssert test.username == "username"
     doAssert test.hostname == "example.com"
     doAssert test.query == "subject=Topic"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar")
+    let str = "magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
+    let test = parseUri(str)
     doAssert test.scheme == "magnet"
     doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("/test/foo/bar?q=2#asdf")
+    let str = "/test/foo/bar?q=2#asdf"
+    let test = parseUri(str)
     doAssert test.scheme == ""
     doAssert test.path == "/test/foo/bar"
     doAssert test.query == "q=2"
     doAssert test.anchor == "asdf"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("test/no/slash")
+    let str = "test/no/slash"
+    let test = parseUri(str)
     doAssert test.path == "test/no/slash"
+    doAssert($test == str)
 
   # Remove dot segments tests
   block:
@@ -371,5 +419,3 @@ when isMainModule:
   block:
     let test = parseUri("http://example.com/foo/") / "/bar/asd"
     doAssert test.path == "/foo/bar/asd"
-
-  
diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim
index 660932d92..6cf837f25 100644
--- a/lib/pure/xmldom.nim
+++ b/lib/pure/xmldom.nim
@@ -365,23 +365,21 @@ discard """proc getElementById*(doc: PDocument, elementId: string): PElement =
 proc getElementsByTagName*(doc: PDocument, tagName: string): seq[PNode] =
   ## Returns a NodeList of all the Elements with a given tag name in
   ## the order in which they are encountered in a preorder traversal of the Document tree.
-  var result: seq[PNode] = @[]
+  result = @[]
   if doc.fDocumentElement.fNodeName == tagName or tagName == "*":
     result.add(doc.fDocumentElement)
 
   result.add(doc.fDocumentElement.findNodes(tagName))
-  return result
 
 proc getElementsByTagNameNS*(doc: PDocument, namespaceURI: string, localName: string): seq[PNode] =
   ## Returns a NodeList of all the Elements with a given localName and namespaceURI
   ## in the order in which they are encountered in a preorder traversal of the Document tree.
-  var result: seq[PNode] = @[]
+  result = @[]
   if doc.fDocumentElement.fLocalName == localName or localName == "*":
     if doc.fDocumentElement.fNamespaceURI == namespaceURI or namespaceURI == "*":
       result.add(doc.fDocumentElement)
 
   result.add(doc.fDocumentElement.findNodesNS(namespaceURI, localName))
-  return result
 
 proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
   ## Imports a node from another document to this document
@@ -642,7 +640,7 @@ proc isEmpty(s: string): bool =
   return true
 
 proc normalize*(n: PNode) =
-  ## Merges all seperated TextNodes together, and removes any empty TextNodes
+  ## Merges all separated TextNodes together, and removes any empty TextNodes
   var curTextNode: PNode = nil
   var i: int = 0
 
@@ -677,7 +675,7 @@ proc removeChild*(n: PNode, oldChild: PNode): PNode =
       if n.childNodes[i] == oldChild:
         result = n.childNodes[i]
         n.childNodes.delete(i)
-        return result
+        return
 
   raise newException(ENotFoundErr, "Node not found")
 
@@ -693,7 +691,7 @@ proc replaceChild*(n: PNode, newChild: PNode, oldChild: PNode): PNode =
       if n.childNodes[i] == oldChild:
         result = n.childNodes[i]
         n.childNodes[i] = newChild
-        return result
+        return
 
   raise newException(ENotFoundErr, "Node not found")
 
@@ -740,7 +738,7 @@ proc removeNamedItem*(nList: var seq[PNode], name: string): PNode =
     if nList[i].fNodeName == name:
       result = nList[i]
       nList.delete(i)
-      return result
+      return
 
   raise newException(ENotFoundErr, "Node not found")
 
@@ -750,7 +748,7 @@ proc removeNamedItemNS*(nList: var seq[PNode], namespaceURI: string, localName:
     if nList[i].fLocalName == localName and nList[i].fNamespaceURI == namespaceURI:
       result = nList[i]
       nList.delete(i)
-      return result
+      return
 
   raise newException(ENotFoundErr, "Node not found")
 
@@ -965,7 +963,7 @@ proc removeAttributeNode*(el: PElement, oldAttr: PAttr): PAttr =
       if el.attributes[i] == oldAttr:
         result = el.attributes[i]
         el.attributes.delete(i)
-        return result
+        return
 
   raise newException(ENotFoundErr, "oldAttr is not a member of el's Attributes")
 
@@ -1083,7 +1081,7 @@ proc addEscaped(s: string): string =
     else: result.add(c)
 
 proc nodeToXml(n: PNode, indent: int = 0): string =
-  result = repeatChar(indent, ' ') & "<" & n.nodeName
+  result = spaces(indent) & "<" & n.nodeName
   if not isNil(n.attributes):
     for i in items(n.attributes):
       result.add(" " & i.name & "=\"" & addEscaped(i.value) & "\"")
@@ -1098,23 +1096,23 @@ proc nodeToXml(n: PNode, indent: int = 0): string =
       of ElementNode:
         result.add(nodeToXml(i, indent + 2))
       of TextNode:
-        result.add(repeatChar(indent * 2, ' '))
+        result.add(spaces(indent * 2))
         result.add(addEscaped(i.nodeValue))
       of CDataSectionNode:
-        result.add(repeatChar(indent * 2, ' '))
+        result.add(spaces(indent * 2))
         result.add("<![CDATA[" & i.nodeValue & "]]>")
       of ProcessingInstructionNode:
-        result.add(repeatChar(indent * 2, ' '))
+        result.add(spaces(indent * 2))
         result.add("<?" & PProcessingInstruction(i).target & " " &
                           PProcessingInstruction(i).data & " ?>")
       of CommentNode:
-        result.add(repeatChar(indent * 2, ' '))
+        result.add(spaces(indent * 2))
         result.add("<!-- " & i.nodeValue & " -->")
       else:
         continue
       result.add("\n")
     # Add the ending tag - </tag>
-    result.add(repeatChar(indent, ' ') & "</" & n.nodeName & ">")
+    result.add(spaces(indent) & "</" & n.nodeName & ">")
 
 proc `$`*(doc: PDocument): string =
   ## Converts a PDocument object into a string representation of it's XML
diff --git a/lib/pure/xmldomparser.nim b/lib/pure/xmldomparser.nim
index 7f34d72a8..050362435 100644
--- a/lib/pure/xmldomparser.nim
+++ b/lib/pure/xmldomparser.nim
@@ -155,7 +155,7 @@ proc loadXMLFile*(path: string): PDocument =
   return loadXMLStream(s)
 
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   var xml = loadXMLFile("nim/xmldom/test.xml")
   #echo(xml.getElementsByTagName("m:test2")[0].namespaceURI)
   #echo(xml.getElementsByTagName("bla:test")[0].namespaceURI)
diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim
index 8591e894c..840cae734 100644
--- a/lib/pure/xmlparser.nim
+++ b/lib/pure/xmlparser.nim
@@ -103,7 +103,7 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode =
 proc parseXml*(s: Stream, filename: string, 
                errors: var seq[string]): XmlNode = 
   ## parses the XML from stream `s` and returns a ``PXmlNode``. Every
-  ## occured parsing error is added to the `errors` sequence.
+  ## occurred parsing error is added to the `errors` sequence.
   var x: XmlParser
   open(x, s, filename, {reportComments})
   while true:
@@ -129,7 +129,7 @@ proc parseXml*(s: Stream): XmlNode =
 
 proc loadXml*(path: string, errors: var seq[string]): XmlNode =
   ## Loads and parses XML from file specified by ``path``, and returns 
-  ## a ``PXmlNode``. Every occured parsing error is added to the `errors`
+  ## a ``PXmlNode``. Every occurred parsing error is added to the `errors`
   ## sequence.
   var s = newFileStream(path, fmRead)
   if s == nil: raise newException(IOError, "Unable to read file: " & path)
@@ -143,7 +143,7 @@ proc loadXml*(path: string): XmlNode =
   result = loadXml(path, errors)
   if errors.len > 0: raiseInvalidXml(errors)
 
-when isMainModule:
+when not defined(testing) and isMainModule:
   import os
 
   var errors: seq[string] = @[]  
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index b84da9586..7526a989a 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -12,20 +12,20 @@
 import macros, strtabs
 
 type
-  XmlNode* = ref XmlNodeObj ## an XML tree consists of ``PXmlNode``'s. 
-  
+  XmlNode* = ref XmlNodeObj ## an XML tree consists of ``PXmlNode``'s.
+
   XmlNodeKind* = enum  ## different kinds of ``PXmlNode``'s
     xnText,             ## a text element
     xnElement,          ## an element with 0 or more children
     xnCData,            ## a CDATA node
     xnEntity,           ## an entity (like ``&thing;``)
     xnComment           ## an XML comment
-  
+
   XmlAttributes* = StringTableRef ## an alias for a string to string mapping
-  
-  XmlNodeObj {.acyclic.} = object 
+
+  XmlNodeObj {.acyclic.} = object
     case k: XmlNodeKind # private, use the kind() proc to read this field.
-    of xnText, xnComment, xnCData, xnEntity: 
+    of xnText, xnComment, xnCData, xnEntity:
       fText: string
     of xnElement:
       fTag: string
@@ -41,34 +41,34 @@ proc newXmlNode(kind: XmlNodeKind): XmlNode =
   new(result)
   result.k = kind
 
-proc newElement*(tag: string): XmlNode = 
+proc newElement*(tag: string): XmlNode =
   ## creates a new ``PXmlNode`` of kind ``xnText`` with the given `tag`.
   result = newXmlNode(xnElement)
   result.fTag = tag
   result.s = @[]
   # init attributes lazily to safe memory
 
-proc newText*(text: string): XmlNode = 
+proc newText*(text: string): XmlNode =
   ## creates a new ``PXmlNode`` of kind ``xnText`` with the text `text`.
   result = newXmlNode(xnText)
   result.fText = text
 
-proc newComment*(comment: string): XmlNode = 
+proc newComment*(comment: string): XmlNode =
   ## creates a new ``PXmlNode`` of kind ``xnComment`` with the text `comment`.
   result = newXmlNode(xnComment)
   result.fText = comment
 
-proc newCData*(cdata: string): XmlNode = 
+proc newCData*(cdata: string): XmlNode =
   ## creates a new ``PXmlNode`` of kind ``xnComment`` with the text `cdata`.
   result = newXmlNode(xnCData)
   result.fText = cdata
 
-proc newEntity*(entity: string): XmlNode = 
+proc newEntity*(entity: string): XmlNode =
   ## creates a new ``PXmlNode`` of kind ``xnEntity`` with the text `entity`.
   result = newXmlNode(xnCData)
   result.fText = entity
 
-proc text*(n: XmlNode): string {.inline.} = 
+proc text*(n: XmlNode): string {.inline.} =
   ## gets the associated text with the node `n`. `n` can be a CDATA, Text,
   ## comment, or entity node.
   assert n.k in {xnText, xnComment, xnCData, xnEntity}
@@ -93,16 +93,16 @@ proc innerText*(n: XmlNode): string =
   for i in 0 .. n.s.len-1:
     if n.s[i].k in {xnText, xnEntity}: result.add(n.s[i].fText)
 
-proc tag*(n: XmlNode): string {.inline.} = 
+proc tag*(n: XmlNode): string {.inline.} =
   ## gets the tag name of `n`. `n` has to be an ``xnElement`` node.
   assert n.k == xnElement
   result = n.fTag
-    
-proc add*(father, son: XmlNode) {.inline.} = 
+
+proc add*(father, son: XmlNode) {.inline.} =
   ## adds the child `son` to `father`.
   add(father.s, son)
-  
-proc len*(n: XmlNode): int {.inline.} = 
+
+proc len*(n: XmlNode): int {.inline.} =
   ## returns the number `n`'s children.
   if n.k == xnElement: result = len(n.s)
 
@@ -110,28 +110,38 @@ proc kind*(n: XmlNode): XmlNodeKind {.inline.} =
   ## returns `n`'s kind.
   result = n.k
 
-proc `[]`* (n: XmlNode, i: int): XmlNode {.inline.} = 
+proc `[]`* (n: XmlNode, i: int): XmlNode {.inline.} =
   ## returns the `i`'th child of `n`.
   assert n.k == xnElement
   result = n.s[i]
 
-iterator items*(n: XmlNode): XmlNode {.inline.} = 
+proc mget* (n: var XmlNode, i: int): var XmlNode {.inline.} =
+  ## returns the `i`'th child of `n` so that it can be modified
+  assert n.k == xnElement
+  result = n.s[i]
+
+iterator items*(n: XmlNode): XmlNode {.inline.} =
   ## iterates over any child of `n`.
   assert n.k == xnElement
   for i in 0 .. n.len-1: yield n[i]
 
-proc attrs*(n: XmlNode): XmlAttributes {.inline.} = 
+iterator mitems*(n: var XmlNode): var XmlNode {.inline.} =
+  ## iterates over any child of `n`.
+  assert n.k == xnElement
+  for i in 0 .. n.len-1: yield mget(n, i)
+
+proc attrs*(n: XmlNode): XmlAttributes {.inline.} =
   ## gets the attributes belonging to `n`.
   ## Returns `nil` if attributes have not been initialised for this node.
   assert n.k == xnElement
   result = n.fAttr
-  
-proc `attrs=`*(n: XmlNode, attr: XmlAttributes) {.inline.} = 
+
+proc `attrs=`*(n: XmlNode, attr: XmlAttributes) {.inline.} =
   ## sets the attributes belonging to `n`.
   assert n.k == xnElement
   n.fAttr = attr
 
-proc attrsLen*(n: XmlNode): int {.inline.} = 
+proc attrsLen*(n: XmlNode): int {.inline.} =
   ## returns the number of `n`'s attributes.
   assert n.k == xnElement
   if not isNil(n.fAttr): result = len(n.fAttr)
@@ -141,12 +151,12 @@ proc clientData*(n: XmlNode): int {.inline.} =
   ## parser and generator.
   result = n.fClientData
 
-proc `clientData=`*(n: XmlNode, data: int) {.inline.} = 
+proc `clientData=`*(n: XmlNode, data: int) {.inline.} =
   ## sets the client data of `n`. The client data field is used by the HTML
   ## parser and generator.
   n.fClientData = data
 
-proc addEscaped*(result: var string, s: string) = 
+proc addEscaped*(result: var string, s: string) =
   ## same as ``result.add(escape(s))``, but more efficient.
   for c in items(s):
     case c
@@ -158,8 +168,8 @@ proc addEscaped*(result: var string, s: string) =
     of '/': result.add("&#x2F;")
     else: result.add(c)
 
-proc escape*(s: string): string = 
-  ## escapes `s` for inclusion into an XML document. 
+proc escape*(s: string): string =
+  ## escapes `s` for inclusion into an XML document.
   ## Escapes these characters:
   ##
   ## ------------    -------------------
@@ -174,26 +184,26 @@ proc escape*(s: string): string =
   ## ------------    -------------------
   result = newStringOfCap(s.len)
   addEscaped(result, s)
-  
-proc addIndent(result: var string, indent: int) = 
+
+proc addIndent(result: var string, indent: int) =
   result.add("\n")
   for i in 1..indent: result.add(' ')
-  
+
 proc noWhitespace(n: XmlNode): bool =
   #for i in 1..n.len-1:
   #  if n[i].kind != n[0].kind: return true
   for i in 0..n.len-1:
     if n[i].kind in {xnText, xnEntity}: return true
-  
-proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) = 
+
+proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
   ## adds the textual representation of `n` to `result`.
   if n == nil: return
   case n.k
   of xnElement:
     result.add('<')
     result.add(n.fTag)
-    if not isNil(n.fAttr): 
-      for key, val in pairs(n.fAttr): 
+    if not isNil(n.fAttr):
+      for key, val in pairs(n.fAttr):
         result.add(' ')
         result.add(key)
         result.add("=\"")
@@ -207,7 +217,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
           # because this would be wrong. For example: ``a<b>b</b>`` is
           # different from ``a <b>b</b>``.
           for i in 0..n.len-1: result.add(n[i], indent+indWidth, indWidth)
-        else: 
+        else:
           for i in 0..n.len-1:
             result.addIndent(indent+indWidth)
             result.add(n[i], indent+indWidth, indWidth)
@@ -217,7 +227,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
       result.add("</")
       result.add(n.fTag)
       result.add(">")
-    else: 
+    else:
       result.add(" />")
   of xnText:
     result.addEscaped(n.fText)
@@ -235,7 +245,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
     result.add(';')
 
 const
-  xmlHeader* = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" 
+  xmlHeader* = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
     ## header to use for complete XML output
 
 proc `$`*(n: XmlNode): string =
@@ -245,21 +255,21 @@ proc `$`*(n: XmlNode): string =
   result.add(n)
 
 proc newXmlTree*(tag: string, children: openArray[XmlNode],
-                 attributes: XmlAttributes = nil): XmlNode = 
+                 attributes: XmlAttributes = nil): XmlNode =
   ## creates a new XML tree with `tag`, `children` and `attributes`
   result = newXmlNode(xnElement)
   result.fTag = tag
   newSeq(result.s, children.len)
   for i in 0..children.len-1: result.s[i] = children[i]
   result.fAttr = attributes
-  
-proc xmlConstructor(e: PNimrodNode): PNimrodNode {.compileTime.} =
+
+proc xmlConstructor(e: NimNode): NimNode {.compileTime.} =
   expectLen(e, 2)
   var a = e[1]
   if a.kind == nnkCall:
     result = newCall("newXmlTree", toStrLit(a[0]))
     var attrs = newNimNode(nnkBracket, a)
-    var newStringTabCall = newCall("newStringTable", attrs, 
+    var newStringTabCall = newCall("newStringTable", attrs,
                                    newIdentNode("modeCaseSensitive"))
     var elements = newNimNode(nnkBracket, a)
     for i in 1..a.len-1:
@@ -270,21 +280,21 @@ proc xmlConstructor(e: PNimrodNode): PNimrodNode {.compileTime.} =
       else:
         elements.add(a[i])
     result.add(elements)
-    if attrs.len > 1: 
+    if attrs.len > 1:
       #echo repr(newStringTabCall)
       result.add(newStringTabCall)
   else:
     result = newCall("newXmlTree", toStrLit(a))
 
-macro `<>`*(x: expr): expr {.immediate.} = 
+macro `<>`*(x: expr): expr {.immediate.} =
   ## Constructor macro for XML. Example usage:
   ##
   ## .. code-block:: nim
-  ##   <>a(href="http://nim-code.org", newText("Nim rules."))
+  ##   <>a(href="http://nim-lang.org", newText("Nim rules."))
   ##
   ## Produces an XML tree for::
   ##
-  ##  <a href="http://nim-code.org">Nim rules.</a>
+  ##  <a href="http://nim-lang.org">Nim rules.</a>
   ##
   let x = callsite()
   result = xmlConstructor(x)
@@ -343,5 +353,6 @@ proc findAll*(n: XmlNode, tag: string): seq[XmlNode] =
   findAll(n, tag, result)
 
 when isMainModule:
-  assert """<a href="http://nim-code.org">Nim rules.</a>""" ==
-    $(<>a(href="http://nim-code.org", newText("Nim rules.")))
+  let link = "http://nim-lang.org"
+  assert """<a href="""" & escape(link) & """">Nim rules.</a>""" ==
+    $(<>a(href="http://nim-lang.org", newText("Nim rules.")))
diff --git a/lib/system.nim b/lib/system.nim
index ca85bf1ad..33eee42f0 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -73,9 +73,13 @@ type
   expr* {.magic: Expr.} ## meta type to denote an expression (for templates)
   stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
   typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
-  void* {.magic: "VoidType".}   ## meta type to denote the absense of any type
+  void* {.magic: "VoidType".}   ## meta type to denote the absence of any type
   auto* = expr
   any* = distinct auto
+  untyped* {.magic: Expr.} ## meta type to denote an expression that
+                           ## is not resolved (for templates)
+  typed* {.magic: Stmt.}   ## meta type to denote an expression that
+                           ## is resolved (for templates)
 
   SomeSignedInt* = int|int8|int16|int32|int64
     ## type class matching all signed integer types
@@ -89,7 +93,7 @@ type
   SomeOrdinal* = int|int8|int16|int32|int64|bool|enum|uint8|uint16|uint32
     ## type class matching all ordinal types; however this includes enums with
     ## holes.
-  
+
   SomeReal* = float|float32|float64
     ## type class matching all floating point number types
 
@@ -124,7 +128,7 @@ proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
   ## feature or not:
   ##
   ## .. code-block:: Nim
-  ##   when not defined(strutils.toUpper):
+  ##   when not declared(strutils.toUpper):
   ##     # provide our own toUpper proc here, because strutils is
   ##     # missing it.
 
@@ -140,6 +144,16 @@ proc declaredInScope*(x: expr): bool {.
   ## Special compile-time procedure that checks whether `x` is
   ## declared in the current scope. `x` has to be an identifier.
 
+proc `addr`*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} =
+  ## Builtin 'addr' operator for taking the address of a memory location.
+  ## Cannot be overloaded.
+  discard
+
+proc `type`*(x: expr): typeDesc {.magic: "TypeOf", noSideEffect.} =
+  ## Builtin 'type' operator for accessing the type of an expression.
+  ## Cannot be overloaded.
+  discard
+
 proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
   ## Boolean not; returns true iff ``x == false``.
 
@@ -163,12 +177,6 @@ proc new*(T: typedesc): ref T =
   ## reference to it as result value
   new(result)
 
-proc unsafeNew*[T](a: var ref T, size: int) {.magic: "New", noSideEffect.}
-  ## creates a new object of type ``T`` and returns a safe (traced)
-  ## reference to it in ``a``. This is **unsafe** as it allocates an object
-  ## of the passed ``size``. This should only be used for optimization
-  ## purposes when you know what you're doing!
-
 proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.}
   ## leaked implementation detail. Do not use.
 
@@ -181,7 +189,7 @@ proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {.
   ## freeing the object. Note: The `finalizer` refers to the type `T`, not to
   ## the object! This means that for each object of type `T` the finalizer
   ## will be called!
-  
+
 proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.}
   ## resets an object `obj` to its initial (binary zero) value. This needs to
   ## be called before any possible `object branch transition`:idx:.
@@ -212,13 +220,13 @@ type
   set*{.magic: "Set".}[T]  ## Generic type to construct bit sets.
 
 type
-  Slice* {.final, pure.}[T] = object ## builtin slice type
-    a*, b*: T                        ## the bounds
+  Slice*[T] = object ## builtin slice type
+    a*, b*: T        ## the bounds
 
 when defined(nimalias):
   {.deprecated: [TSlice: Slice].}
 
-proc `..`*[T](a, b: T): Slice[T] {.noSideEffect, inline.} =
+proc `..`*[T](a, b: T): Slice[T] {.noSideEffect, inline, magic: "DotDot".} =
   ## `slice`:idx: operator that constructs an interval ``[a, b]``, both `a`
   ## and `b` are inclusive. Slices can also be used in the set constructor
   ## and in ordinal case statements, but then they are special-cased by the
@@ -226,7 +234,7 @@ proc `..`*[T](a, b: T): Slice[T] {.noSideEffect, inline.} =
   result.a = a
   result.b = b
 
-proc `..`*[T](b: T): Slice[T] {.noSideEffect, inline.} =
+proc `..`*[T](b: T): Slice[T] {.noSideEffect, inline, magic: "DotDot".} =
   ## `slice`:idx: operator that constructs an interval ``[default(T), b]``
   result.b = b
 
@@ -291,12 +299,14 @@ include "system/inclrtl"
 const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \
   ## "fake variables" like 'var EBADF {.importc.}: cint'.
 
+const ArrayDummySize = when defined(cpu16): 10_000 else: 100_000_000
+
 when not defined(JS):
   type
     TGenericSeq {.compilerproc, pure, inheritable.} = object
       len, reserved: int
     PGenericSeq {.exportc.} = ptr TGenericSeq
-    UncheckedCharArray {.unchecked.} = array[0..100_000_000, char]
+    UncheckedCharArray {.unchecked.} = array[0..ArrayDummySize, char]
     # len and space without counting the terminating zero:
     NimStringDesc {.compilerproc, final.} = object of TGenericSeq
       data: UncheckedCharArray
@@ -341,12 +351,12 @@ type
     ##
     ## Each exception has to inherit from `Exception`. See the full `exception
     ## hierarchy`_.
-    parent: ref Exception     ## parent exception (can be used as a stack)
-    name: cstring             ## The exception's name is its Nim identifier.
-                              ## This field is filled automatically in the
-                              ## ``raise`` statement.
+    parent*: ref Exception ## parent exception (can be used as a stack)
+    name: cstring ## The exception's name is its Nim identifier.
+                  ## This field is filled automatically in the
+                  ## ``raise`` statement.
     msg* {.exportc: "message".}: string ## the exception's message. Not
-                                        ## providing an exception message 
+                                        ## providing an exception message
                                         ## is bad style.
     trace: string
 
@@ -355,7 +365,7 @@ type
     ##
     ## See the full `exception hierarchy`_.
   IOError* = object of SystemError ## \
-    ## Raised if an IO error occured.
+    ## Raised if an IO error occurred.
     ##
     ## See the full `exception hierarchy`_.
   OSError* = object of SystemError ## \
@@ -368,11 +378,11 @@ type
     ##
     ## See the full `exception hierarchy`_.
   ResourceExhaustedError* = object of SystemError ## \
-    ## Raised if a resource request could not be fullfilled.
+    ## Raised if a resource request could not be fulfilled.
     ##
     ## See the full `exception hierarchy`_.
   ArithmeticError* = object of Exception ## \
-    ## Raised if any kind of arithmetic error occured.
+    ## Raised if any kind of arithmetic error occurred.
     ##
     ## See the full `exception hierarchy`_.
   DivByZeroError* = object of ArithmeticError ## \
@@ -481,7 +491,7 @@ type
 
   E_Base: Exception, ESystem: SystemError, EIO: IOError,
   EOS: OSError, EInvalidLibrary: LibraryError,
-  EResourceExhausted: ResourceExhaustedError, 
+  EResourceExhausted: ResourceExhaustedError,
   EArithmetic: ArithmeticError, EDivByZero: DivByZeroError,
   EOverflow: OverflowError, EAccessViolation: AccessViolationError,
   EAssertionFailed: AssertionError, EInvalidValue: ValueError,
@@ -492,7 +502,7 @@ type
   EInvalidObjectAssignment: ObjectAssignmentError,
   EInvalidObjectConversion: ObjectConversionError,
   EDeadThread: DeadThreadError,
-  EFloatInexact: FloatInexactError, 
+  EFloatInexact: FloatInexactError,
   EFloatUnderflow: FloatUnderflowError,
   EFloatingPoint: FloatingPointError,
   EFloatInvalidOp: FloatInvalidOpError,
@@ -501,7 +511,13 @@ type
   ESynch: Exception
 ].}
 
-proc sizeof*[T](x: T): Natural {.magic: "SizeOf", noSideEffect.}
+proc unsafeNew*[T](a: var ref T, size: Natural) {.magic: "New", noSideEffect.}
+  ## creates a new object of type ``T`` and returns a safe (traced)
+  ## reference to it in ``a``. This is **unsafe** as it allocates an object
+  ## of the passed ``size``. This should only be used for optimization
+  ## purposes when you know what you're doing!
+
+proc sizeof*[T](x: T): int {.magic: "SizeOf", noSideEffect.}
   ## returns the size of ``x`` in bytes. Since this is a low-level proc,
   ## its usage is discouraged - using ``new`` for the most cases suffices
   ## that one never needs to know ``x``'s size. As a special semantic rule,
@@ -509,11 +525,11 @@ proc sizeof*[T](x: T): Natural {.magic: "SizeOf", noSideEffect.}
 
 proc `<`*[T](x: Ordinal[T]): T {.magic: "UnaryLt", noSideEffect.}
   ## unary ``<`` that can be used for nice looking excluding ranges:
-  ## 
+  ##
   ## .. code-block:: nim
   ##   for i in 0 .. <10: echo i
   ##
-  ## Semantically this is the same as ``pred``. 
+  ## Semantically this is the same as ``pred``.
 
 proc succ*[T](x: Ordinal[T], y = 1): T {.magic: "Succ", noSideEffect.}
   ## returns the ``y``-th successor of the value ``x``. ``T`` has to be
@@ -534,8 +550,8 @@ proc dec*[T: Ordinal|uint|uint64](x: var T, y = 1) {.magic: "Dec", noSideEffect.
   ## decrements the ordinal ``x`` by ``y``. If such a value does not
   ## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
   ## short notation for: ``x = pred(x, y)``.
-  
-proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq", noSideEffect.}
+
+proc newSeq*[T](s: var seq[T], len: Natural) {.magic: "NewSeq", noSideEffect.}
   ## creates a new sequence of type ``seq[T]`` with length ``len``.
   ## This is equivalent to ``s = @[]; setlen(s, len)``, but more
   ## efficient since no reallocation is needed.
@@ -553,7 +569,7 @@ proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq", noSideEffect.}
   ##   inputStrings[2] = "would crash"
   ##   #inputStrings[3] = "out of bounds"
 
-proc newSeq*[T](len = 0): seq[T] =
+proc newSeq*[T](len = 0.Natural): seq[T] =
   ## creates a new sequence of type ``seq[T]`` with length ``len``.
   ##
   ## Note that the sequence will be filled with zeroed entries, which can be a
@@ -576,7 +592,7 @@ proc len*(x: cstring): int {.magic: "LengthStr", noSideEffect.}
 proc len*[I, T](x: array[I, T]): int {.magic: "LengthArray", noSideEffect.}
 proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.}
   ## returns the length of an array, an openarray, a sequence or a string.
-  ## This is rougly the same as ``high(T)-low(T)+1``, but its resulting type is
+  ## This is roughly the same as ``high(T)-low(T)+1``, but its resulting type is
   ## always an int.
 
 # set routines:
@@ -634,7 +650,7 @@ when not defined(JS):
 
   proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.}
     ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
-    ## from `x`.    
+    ## from `x`.
   proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect.}
     ## treats `x` as unsigned and converts it to an ``int16`` by taking the last
     ## 16 bits from `x`.
@@ -647,7 +663,7 @@ proc `+` *(x: int): int {.magic: "UnaryPlusI", noSideEffect.}
 proc `+` *(x: int8): int8 {.magic: "UnaryPlusI", noSideEffect.}
 proc `+` *(x: int16): int16 {.magic: "UnaryPlusI", noSideEffect.}
 proc `+` *(x: int32): int32 {.magic: "UnaryPlusI", noSideEffect.}
-proc `+` *(x: int64): int64 {.magic: "UnaryPlusI64", noSideEffect.}
+proc `+` *(x: int64): int64 {.magic: "UnaryPlusI", noSideEffect.}
   ## Unary `+` operator for an integer. Has no effect.
 
 proc `-` *(x: int): int {.magic: "UnaryMinusI", noSideEffect.}
@@ -692,6 +708,7 @@ proc `div` *(x, y: int32): int32 {.magic: "DivI", noSideEffect.}
 proc `div` *(x, y: int64): int64 {.magic: "DivI64", noSideEffect.}
   ## computes the integer division. This is roughly the same as
   ## ``floor(x/y)``.
+  ##
   ## .. code-block:: Nim
   ##   1 div 2 == 0
   ##   2 div 2 == 1
@@ -711,6 +728,7 @@ proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.}
 proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.}
 proc `shr` *(x, y: int64): int64 {.magic: "ShrI64", noSideEffect.}
   ## computes the `shift right` operation of `x` and `y`.
+  ##
   ## .. code-block:: Nim
   ##   0b0001_0000'i8 shr 2 == 0b0100_0000'i8
   ##   0b1000_0000'i8 shr 2 == 0b0000_0000'i8
@@ -798,7 +816,7 @@ proc `%%` *(x, y: int64): int64 {.magic: "ModU", noSideEffect.}
   ## The result is truncated to fit into the result.
   ## This implements modulo arithmetic.
   ## No overflow errors are possible.
-  
+
 proc `<=%` *(x, y: IntMax32): bool {.magic: "LeU", noSideEffect.}
 proc `<=%` *(x, y: int64): bool {.magic: "LeU64", noSideEffect.}
   ## treats `x` and `y` as unsigned and compares them.
@@ -863,7 +881,7 @@ proc contains*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.}
   ## passes its arguments in reverse order.
 
 proc contains*[T](s: Slice[T], value: T): bool {.noSideEffect, inline.} =
-  ## Checks if `value` is withing the range of `s`; returns true iff
+  ## Checks if `value` is within the range of `s`; returns true iff
   ## `value >= s.a and value <= s.b`
   ##
   ## .. code-block:: Nim
@@ -887,7 +905,7 @@ template `notin` * (x, y: expr): expr {.immediate, dirty.} = not contains(y, x)
 
 proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
   ## Checks if T is of the same type as S
-  ## 
+  ##
   ## .. code-block:: Nim
   ##   proc test[T](a: T): int =
   ##     when (T is int):
@@ -922,25 +940,25 @@ proc cmp*(x, y: string): int {.noSideEffect, procvar.}
 proc `@` * [IDX, T](a: array[IDX, T]): seq[T] {.
   magic: "ArrToSeq", nosideeffect.}
   ## turns an array into a sequence. This most often useful for constructing
-  ## sequences with the array constructor: ``@[1, 2, 3]`` has the type 
+  ## sequences with the array constructor: ``@[1, 2, 3]`` has the type
   ## ``seq[int]``, while ``[1, 2, 3]`` has the type ``array[0..2, int]``.
 
-proc setLen*[T](s: var seq[T], newlen: int) {.
+proc setLen*[T](s: var seq[T], newlen: Natural) {.
   magic: "SetLengthSeq", noSideEffect.}
   ## sets the length of `s` to `newlen`.
   ## ``T`` may be any sequence type.
   ## If the current length is greater than the new length,
   ## ``s`` will be truncated. `s` cannot be nil! To initialize a sequence with
-  ## a size, use ``newSeq`` instead. 
+  ## a size, use ``newSeq`` instead.
 
-proc setLen*(s: var string, newlen: int) {.
+proc setLen*(s: var string, newlen: Natural) {.
   magic: "SetLengthStr", noSideEffect.}
   ## sets the length of `s` to `newlen`.
   ## If the current length is greater than the new length,
   ## ``s`` will be truncated. `s` cannot be nil! To initialize a string with
-  ## a size, use ``newString`` instead. 
+  ## a size, use ``newString`` instead.
 
-proc newString*(len: int): string {.
+proc newString*(len: Natural): string {.
   magic: "NewString", importc: "mnewString", noSideEffect.}
   ## returns a new string of length ``len`` but with uninitialized
   ## content. One needs to fill the string character after character
@@ -948,10 +966,10 @@ proc newString*(len: int): string {.
   ## optimization purposes; the same effect can be achieved with the
   ## ``&`` operator or with ``add``.
 
-proc newStringOfCap*(cap: int): string {.
+proc newStringOfCap*(cap: Natural): string {.
   magic: "NewStringOfCap", importc: "rawNewString", noSideEffect.}
   ## returns a new string of length ``0`` but with capacity `cap`.This
-  ## procedure exists only for optimization purposes; the same effect can 
+  ## procedure exists only for optimization purposes; the same effect can
   ## be achieved with the ``&`` operator or with ``add``.
 
 proc `&` * (x: string, y: char): string {.
@@ -980,7 +998,7 @@ proc `&` * (x: char, y: string): string {.
   ##   assert('a' & "bc" == "abc")
 
 # implementation note: These must all have the same magic value "ConStrStr" so
-# that the merge optimization works properly. 
+# that the merge optimization works properly.
 
 proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
   ## Appends `y` to `x` in place
@@ -1037,15 +1055,15 @@ proc compileOption*(option: string): bool {.
   ## can be used to determine an on|off compile-time option. Example:
   ##
   ## .. code-block:: nim
-  ##   when compileOption("floatchecks"): 
+  ##   when compileOption("floatchecks"):
   ##     echo "compiled with floating point NaN and Inf checks"
-  
+
 proc compileOption*(option, arg: string): bool {.
   magic: "CompileOptionArg", noSideEffect.}
   ## can be used to determine an enum compile-time option. Example:
   ##
   ## .. code-block:: nim
-  ##   when compileOption("opt", "size") and compileOption("gc", "boehm"): 
+  ##   when compileOption("opt", "size") and compileOption("gc", "boehm"):
   ##     echo "compiled with optimization for size and uses Boehm's GC"
 
 const
@@ -1054,16 +1072,16 @@ const
   taintMode = compileOption("taintmode")
 
 when taintMode:
-  type TaintedString* = distinct string ## a distinct string type that 
+  type TaintedString* = distinct string ## a distinct string type that
                                         ## is `tainted`:idx:. It is an alias for
                                         ## ``string`` if the taint mode is not
                                         ## turned on. Use the ``-d:taintMode``
                                         ## command line switch to turn the taint
                                         ## mode on.
-  
+
   proc len*(s: TaintedString): int {.borrow.}
 else:
-  type TaintedString* = string          ## a distinct string type that 
+  type TaintedString* = string          ## a distinct string type that
                                         ## is `tainted`:idx:. It is an alias for
                                         ## ``string`` if the taint mode is not
                                         ## turned on. Use the ``-d:taintMode``
@@ -1134,25 +1152,25 @@ proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
 proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".}
   ## use this instead of `=` for a `shallow copy`:idx:. The shallow copy
   ## only changes the semantics for sequences and strings (and types which
-  ## contain those). Be careful with the changed semantics though! There 
+  ## contain those). Be careful with the changed semantics though! There
   ## is a reason why the default assignment does a deep copy of sequences
   ## and strings.
 
-proc del*[T](x: var seq[T], i: int) {.noSideEffect.} = 
+proc del*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
   ## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`.
   ## This is an O(1) operation.
   let xl = x.len
   shallowCopy(x[i], x[xl-1])
   setLen(x, xl-1)
-  
-proc delete*[T](x: var seq[T], i: int) {.noSideEffect.} = 
+
+proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
   ## deletes the item at index `i` by moving ``x[i+1..]`` by one position.
   ## This is an O(n) operation.
   let xl = x.len
-  for j in i..xl-2: shallowCopy(x[j], x[j+1]) 
+  for j in i..xl-2: shallowCopy(x[j], x[j+1])
   setLen(x, xl-1)
-  
-proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} = 
+
+proc insert*[T](x: var seq[T], item: T, i = 0.Natural) {.noSideEffect.} =
   ## inserts `item` into `x` at position `i`.
   let xl = x.len
   setLen(x, xl+1)
@@ -1222,16 +1240,16 @@ type # these work for most platforms:
     ## This is the same as the type ``unsigned char`` in *C*.
   cushort* {.importc: "unsigned short", nodecl.} = uint16
     ## This is the same as the type ``unsigned short`` in *C*.
-  cuint* {.importc: "int", nodecl.} = uint32
+  cuint* {.importc: "unsigned int", nodecl.} = uint32
     ## This is the same as the type ``unsigned int`` in *C*.
   culonglong* {.importc: "unsigned long long", nodecl.} = uint64
     ## This is the same as the type ``unsigned long long`` in *C*.
 
-  cstringArray* {.importc: "char**", nodecl.} = ptr array [0..50_000, cstring]
+  cstringArray* {.importc: "char**", nodecl.} = ptr array [0..ArrayDummySize, cstring]
     ## This is binary compatible to the type ``char**`` in *C*. The array's
     ## high value is large enough to disable bounds checking in practice.
     ## Use `cstringArrayToSeq` to convert it into a ``seq[string]``.
-  
+
   PFloat32* = ptr float32 ## an alias for ``ptr float32``
   PFloat64* = ptr float64 ## an alias for ``ptr float64``
   PInt64* = ptr int64 ## an alias for ``ptr int64``
@@ -1278,7 +1296,7 @@ proc addQuitProc*(QuitProc: proc() {.noconv.}) {.
 proc copy*(s: string, first = 0): string {.
   magic: "CopyStr", importc: "copyStr", noSideEffect, deprecated.}
 proc copy*(s: string, first, last: int): string {.
-  magic: "CopyStrLast", importc: "copyStrLast", noSideEffect, 
+  magic: "CopyStrLast", importc: "copyStrLast", noSideEffect,
   deprecated.}
   ## copies a slice of `s` into a new string and returns this new
   ## string. The bounds `first` and `last` denote the indices of
@@ -1298,19 +1316,19 @@ proc substr*(s: string, first, last: int): string {.
   ## or `limit`:idx: a string's length.
 
 when not defined(nimrodVM):
-  proc zeroMem*(p: pointer, size: int) {.importc, noDecl, benign.}
+  proc zeroMem*(p: pointer, size: Natural) {.importc, noDecl, benign.}
     ## overwrites the contents of the memory at ``p`` with the value 0.
     ## Exactly ``size`` bytes will be overwritten. Like any procedure
     ## dealing with raw memory this is *unsafe*.
 
-  proc copyMem*(dest, source: pointer, size: int) {.
+  proc copyMem*(dest, source: pointer, size: Natural) {.
     importc: "memcpy", header: "<string.h>", benign.}
     ## copies the contents from the memory at ``source`` to the memory
     ## at ``dest``. Exactly ``size`` bytes will be copied. The memory
     ## regions may not overlap. Like any procedure dealing with raw
     ## memory this is *unsafe*.
 
-  proc moveMem*(dest, source: pointer, size: int) {.
+  proc moveMem*(dest, source: pointer, size: Natural) {.
     importc: "memmove", header: "<string.h>", benign.}
     ## copies the contents from the memory at ``source`` to the memory
     ## at ``dest``. Exactly ``size`` bytes will be copied. The memory
@@ -1318,7 +1336,7 @@ when not defined(nimrodVM):
     ## and is thus somewhat more safe than ``copyMem``. Like any procedure
     ## dealing with raw memory this is still *unsafe*, though.
 
-  proc equalMem*(a, b: pointer, size: int): bool {.
+  proc equalMem*(a, b: pointer, size: Natural): bool {.
     importc: "equalMem", noDecl, noSideEffect.}
     ## compares the memory blocks ``a`` and ``b``. ``size`` bytes will
     ## be compared. If the blocks are equal, true is returned, false
@@ -1326,7 +1344,7 @@ when not defined(nimrodVM):
     ## *unsafe*.
 
   when hostOS != "standalone":
-    proc alloc*(size: int): pointer {.noconv, rtl, tags: [], benign.}
+    proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign.}
       ## allocates a new memory block with at least ``size`` bytes. The
       ## block has to be freed with ``realloc(block, 0)`` or
       ## ``dealloc(block)``. The block is not initialized, so reading
@@ -1341,7 +1359,7 @@ when not defined(nimrodVM):
       ## The allocated memory belongs to its allocating thread!
       ## Use `createSharedU` to allocate from a shared heap.
       cast[ptr T](alloc(T.sizeof * size))
-    proc alloc0*(size: int): pointer {.noconv, rtl, tags: [], benign.}
+    proc alloc0*(size: Natural): pointer {.noconv, rtl, tags: [], benign.}
       ## allocates a new memory block with at least ``size`` bytes. The
       ## block has to be freed with ``realloc(block, 0)`` or
       ## ``dealloc(block)``. The block is initialized with all bytes
@@ -1356,8 +1374,8 @@ when not defined(nimrodVM):
       ## The allocated memory belongs to its allocating thread!
       ## Use `createShared` to allocate from a shared heap.
       cast[ptr T](alloc0(T.sizeof * size))
-    proc realloc*(p: pointer, newSize: int): pointer {.noconv, rtl, tags: [], 
-                                                       benign.}
+    proc realloc*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [],
+                                                           benign.}
       ## grows or shrinks a given memory block. If p is **nil** then a new
       ## memory block is returned. In either way the block has at least
       ## ``newSize`` bytes. If ``newSize == 0`` and p is not **nil**
@@ -1379,40 +1397,40 @@ when not defined(nimrodVM):
       ## ``realloc``. This procedure is dangerous! If one forgets to
       ## free the memory a leak occurs; if one tries to access freed
       ## memory (or just freeing it twice!) a core dump may happen
-      ## or other memory may be corrupted. 
+      ## or other memory may be corrupted.
       ## The freed memory must belong to its allocating thread!
       ## Use `deallocShared` to deallocate from a shared heap.
     proc free*[T](p: ptr T) {.inline, benign.} =
       dealloc(p)
-    proc allocShared*(size: int): pointer {.noconv, rtl, benign.}
+    proc allocShared*(size: Natural): pointer {.noconv, rtl, benign.}
       ## allocates a new memory block on the shared heap with at
       ## least ``size`` bytes. The block has to be freed with
       ## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block
-      ## is not initialized, so reading from it before writing to it is 
+      ## is not initialized, so reading from it before writing to it is
       ## undefined behaviour!
-    proc createSharedU*(T: typedesc, size = 1.Positive): ptr T {.inline, 
+    proc createSharedU*(T: typedesc, size = 1.Positive): ptr T {.inline,
                                                                  benign.} =
       ## allocates a new memory block on the shared heap with at
       ## least ``T.sizeof * size`` bytes. The block has to be freed with
       ## ``resizeShared(block, 0)`` or ``freeShared(block)``. The block
-      ## is not initialized, so reading from it before writing to it is 
+      ## is not initialized, so reading from it before writing to it is
       ## undefined behaviour!
       cast[ptr T](allocShared(T.sizeof * size))
-    proc allocShared0*(size: int): pointer {.noconv, rtl, benign.}
-      ## allocates a new memory block on the shared heap with at 
+    proc allocShared0*(size: Natural): pointer {.noconv, rtl, benign.}
+      ## allocates a new memory block on the shared heap with at
       ## least ``size`` bytes. The block has to be freed with
       ## ``reallocShared(block, 0)`` or ``deallocShared(block)``.
       ## The block is initialized with all bytes
       ## containing zero, so it is somewhat safer than ``allocShared``.
     proc createShared*(T: typedesc, size = 1.Positive): ptr T {.inline.} =
-      ## allocates a new memory block on the shared heap with at 
+      ## allocates a new memory block on the shared heap with at
       ## least ``T.sizeof * size`` bytes. The block has to be freed with
       ## ``resizeShared(block, 0)`` or ``freeShared(block)``.
       ## The block is initialized with all bytes
       ## containing zero, so it is somewhat safer than ``createSharedU``.
       cast[ptr T](allocShared0(T.sizeof * size))
-    proc reallocShared*(p: pointer, newSize: int): pointer {.noconv, rtl, 
-                                                             benign.}
+    proc reallocShared*(p: pointer, newSize: Natural): pointer {.noconv, rtl,
+                                                                 benign.}
       ## grows or shrinks a given memory block on the heap. If p is **nil**
       ## then a new memory block is returned. In either way the block has at
       ## least ``newSize`` bytes. If ``newSize == 0`` and p is not **nil**
@@ -1453,7 +1471,8 @@ template `>%` *(x, y: expr): expr {.immediate.} = y <% x
 
 proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
   ## The stringify operator for an integer argument. Returns `x`
-  ## converted to a decimal string.
+  ## converted to a decimal string. ``$`` is Nim's general way of
+  ## spelling `toString`:idx:.
 
 proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
   ## The stringify operator for an integer argument. Returns `x`
@@ -1513,16 +1532,16 @@ const
   NimMajor*: int = 0
     ## is the major number of Nim's version.
 
-  NimMinor*: int = 10
+  NimMinor*: int = 11
     ## is the minor number of Nim's version.
 
-  NimPatch*: int = 2
+  NimPatch*: int = 0
     ## is the patch number of Nim's version.
 
   NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
     ## is the version of Nim as a string.
 
-{.deprecated: [TEndian: Endianness, NimrodVersion: NimVersion, 
+{.deprecated: [TEndian: Endianness, NimrodVersion: NimVersion,
     NimrodMajor: NimMajor, NimrodMinor: NimMinor, NimrodPatch: NimPatch].}
 
 # GC interface:
@@ -1553,30 +1572,51 @@ when not defined(nimrodVM) and hostOS != "standalone":
       ## returns the number of bytes on the shared heap that are owned by the
       ## process. This is only available when threads are enabled.
 
+when sizeof(int) <= 2:
+  type IntLikeForCount = int|int8|int16|char|bool|uint8|enum
+else:
+  type IntLikeForCount = int|int8|int16|int32|char|bool|uint8|uint16|enum
+
 iterator countdown*[T](a, b: T, step = 1): T {.inline.} =
   ## Counts from ordinal value `a` down to `b` with the given
   ## step count. `T` may be any ordinal type, `step` may only
-  ## be positive.
-  var res = a
-  while res >= b:
-    yield res
-    dec(res, step)
+  ## be positive. **Note**: This fails to count to ``low(int)`` if T = int for
+  ## efficiency reasons.
+  when T is IntLikeForCount:
+    var res = int(a)
+    while res >= int(b):
+      yield T(res)
+      dec(res, step)
+  else:
+    var res = a
+    while res >= b:
+      yield res
+      dec(res, step)
+
+template countupImpl(incr: stmt) {.immediate, dirty.} =
+  when T is IntLikeForCount:
+    var res = int(a)
+    while res <= int(b):
+      yield T(res)
+      incr
+  else:
+    var res: T = T(a)
+    while res <= b:
+      yield res
+      incr
 
 iterator countup*[S, T](a: S, b: T, step = 1): T {.inline.} =
   ## Counts from ordinal value `a` up to `b` with the given
   ## step count. `S`, `T` may be any ordinal type, `step` may only
-  ## be positive.
-  var res: T = T(a)
-  while res <= b:
-    yield res
+  ## be positive. **Note**: This fails to count to ``high(int)`` if T = int for
+  ## efficiency reasons.
+  countupImpl:
     inc(res, step)
 
 iterator `..`*[S, T](a: S, b: T): T {.inline.} =
   ## An alias for `countup`.
-  var res: T = T(a)
-  while res <= b:
-    yield res
-    inc res
+  countupImpl:
+    inc(res)
 
 iterator `||`*[S, T](a: S, b: T, annotation=""): T {.
   inline, magic: "OmpParFor", sideEffect.} =
@@ -1598,7 +1638,7 @@ proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.} =
   if x <= y: x else: y
 proc min*(x, y: int32): int32 {.magic: "MinI", noSideEffect.} =
   if x <= y: x else: y
-proc min*(x, y: int64): int64 {.magic: "MinI64", noSideEffect.} =
+proc min*(x, y: int64): int64 {.magic: "MinI", noSideEffect.} =
   ## The minimum value of two integers.
   if x <= y: x else: y
 
@@ -1616,7 +1656,7 @@ proc max*(x, y: int16): int16 {.magic: "MaxI", noSideEffect.} =
   if y <= x: x else: y
 proc max*(x, y: int32): int32 {.magic: "MaxI", noSideEffect.} =
   if y <= x: x else: y
-proc max*(x, y: int64): int64 {.magic: "MaxI64", noSideEffect.} =
+proc max*(x, y: int64): int64 {.magic: "MaxI", noSideEffect.} =
   ## The maximum value of two integers.
   if y <= x: x else: y
 
@@ -1651,6 +1691,13 @@ iterator items*[T](a: openArray[T]): T {.inline.} =
     yield a[i]
     inc(i)
 
+iterator mitems*[T](a: var openArray[T]): var T {.inline.} =
+  ## iterates over each item of `a` so that you can modify the yielded value.
+  var i = 0
+  while i < len(a):
+    yield a[i]
+    inc(i)
+
 iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
   ## iterates over each item of `a`.
   var i = low(IX)
@@ -1660,16 +1707,23 @@ iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
       if i >= high(IX): break
       inc(i)
 
+iterator mitems*[IX, T](a: var array[IX, T]): var T {.inline.} =
+  ## iterates over each item of `a` so that you can modify the yielded value.
+  var i = low(IX)
+  if i <= high(IX):
+    while true:
+      yield a[i]
+      if i >= high(IX): break
+      inc(i)
+
 iterator items*[T](a: set[T]): T {.inline.} =
   ## iterates over each element of `a`. `items` iterates only over the
   ## elements that are really in the set (and not over the ones the set is
   ## able to hold).
-  var i = low(T)
-  if i <= high(T):
-    while true:
-      if i in a: yield i
-      if i >= high(T): break
-      inc(i)
+  var i = low(T).int
+  while i <= high(T).int:
+    if T(i) in a: yield T(i)
+    inc(i)
 
 iterator items*(a: cstring): char {.inline.} =
   ## iterates over each item of `a`.
@@ -1678,11 +1732,24 @@ iterator items*(a: cstring): char {.inline.} =
     yield a[i]
     inc(i)
 
+iterator mitems*(a: var cstring): var char {.inline.} =
+  ## iterates over each item of `a` so that you can modify the yielded value.
+  var i = 0
+  while a[i] != '\0':
+    yield a[i]
+    inc(i)
+
 iterator items*(E: typedesc[enum]): E =
   ## iterates over the values of the enum ``E``.
   for v in low(E)..high(E):
     yield v
 
+iterator items*[T](s: Slice[T]): T =
+  ## iterates over the slice `s`, yielding each value between `s.a` and `s.b`
+  ## (inclusively).
+  for x in s.a..s.b:
+    yield x
+
 iterator pairs*[T](a: openArray[T]): tuple[key: int, val: T] {.inline.} =
   ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
   var i = 0
@@ -1690,6 +1757,14 @@ iterator pairs*[T](a: openArray[T]): tuple[key: int, val: T] {.inline.} =
     yield (i, a[i])
     inc(i)
 
+iterator mpairs*[T](a: var openArray[T]): tuple[key: int, val: var T] {.inline.} =
+  ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
+  ## ``a[index]`` can be modified.
+  var i = 0
+  while i < len(a):
+    yield (i, a[i])
+    inc(i)
+
 iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} =
   ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
   var i = low(IX)
@@ -1699,6 +1774,16 @@ iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} =
       if i >= high(IX): break
       inc(i)
 
+iterator mpairs*[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inline.} =
+  ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
+  ## ``a[index]`` can be modified.
+  var i = low(IX)
+  if i <= high(IX):
+    while true:
+      yield (i, a[i])
+      if i >= high(IX): break
+      inc(i)
+
 iterator pairs*[T](a: seq[T]): tuple[key: int, val: T] {.inline.} =
   ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
   var i = 0
@@ -1706,6 +1791,14 @@ iterator pairs*[T](a: seq[T]): tuple[key: int, val: T] {.inline.} =
     yield (i, a[i])
     inc(i)
 
+iterator mpairs*[T](a: var seq[T]): tuple[key: int, val: var T] {.inline.} =
+  ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
+  ## ``a[index]`` can be modified.
+  var i = 0
+  while i < len(a):
+    yield (i, a[i])
+    inc(i)
+
 iterator pairs*(a: string): tuple[key: int, val: char] {.inline.} =
   ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
   var i = 0
@@ -1713,6 +1806,29 @@ iterator pairs*(a: string): tuple[key: int, val: char] {.inline.} =
     yield (i, a[i])
     inc(i)
 
+iterator mpairs*(a: var string): tuple[key: int, val: var char] {.inline.} =
+  ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
+  ## ``a[index]`` can be modified.
+  var i = 0
+  while i < len(a):
+    yield (i, a[i])
+    inc(i)
+
+iterator pairs*(a: cstring): tuple[key: int, val: char] {.inline.} =
+  ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
+  var i = 0
+  while a[i] != '\0':
+    yield (i, a[i])
+    inc(i)
+
+iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
+  ## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
+  ## ``a[index]`` can be modified.
+  var i = 0
+  while a[i] != '\0':
+    yield (i, a[i])
+    inc(i)
+
 
 proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".}
 proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
@@ -1730,7 +1846,7 @@ proc `==` *[I, T](x, y: array[I, T]): bool =
       return
   result = true
 
-proc `@`*[T](a: openArray[T]): seq[T] = 
+proc `@`*[T](a: openArray[T]): seq[T] =
   ## turns an openarray into a sequence. This is not as efficient as turning
   ## a fixed length array into a sequence as it always copies every element
   ## of `a`.
@@ -1778,7 +1894,7 @@ when not defined(NimrodVM):
   else:
     proc seqToPtr[T](x: seq[T]): pointer {.asmNoStackFrame, nosideeffect.} =
       asm """return `x`"""
-  
+
   proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} =
     ## Generic equals operator for sequences: relies on a equals operator for
     ## the element type `T`.
@@ -1804,7 +1920,7 @@ proc contains*[T](a: openArray[T], item: T): bool {.inline.}=
   ## for ``find(a, item) >= 0``.
   return find(a, item) >= 0
 
-proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} = 
+proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
   ## returns the last item of `s` and decreases ``s.len`` by one. This treats
   ## `s` as a stack and implements the common *pop* operation.
   var L = s.len-1
@@ -1866,7 +1982,7 @@ iterator fields*[T: tuple|object](x: T): RootObj {.
 iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[a,b: expr] {.
   magic: "Fields", noSideEffect.}
   ## iterates over every field of `x` and `y`.
-  ## Warning: This is really transforms the 'for' and unrolls the loop. 
+  ## Warning: This is really transforms the 'for' and unrolls the loop.
   ## The current implementation also has a bug that affects symbol binding
   ## in the loop body.
 iterator fieldPairs*[T: tuple|object](x: T): RootObj {.
@@ -1907,18 +2023,18 @@ iterator fieldPairs*[S: tuple|object, T: tuple|object](x: S, y: T): tuple[
   a, b: expr] {.
   magic: "FieldPairs", noSideEffect.}
   ## iterates over every field of `x` and `y`.
-  ## Warning: This really transforms the 'for' and unrolls the loop. 
+  ## Warning: This really transforms the 'for' and unrolls the loop.
   ## The current implementation also has a bug that affects symbol binding
   ## in the loop body.
 
-proc `==`*[T: tuple|object](x, y: T): bool = 
+proc `==`*[T: tuple|object](x, y: T): bool =
   ## generic ``==`` operator for tuples that is lifted from the components
   ## of `x` and `y`.
   for a, b in fields(x, y):
     if a != b: return false
   return true
 
-proc `<=`*[T: tuple](x, y: T): bool = 
+proc `<=`*[T: tuple](x, y: T): bool =
   ## generic ``<=`` operator for tuples that is lifted from the components
   ## of `x` and `y`. This implementation uses `cmp`.
   for a, b in fields(x, y):
@@ -1927,7 +2043,7 @@ proc `<=`*[T: tuple](x, y: T): bool =
     if c > 0: return false
   return true
 
-proc `<`*[T: tuple](x, y: T): bool = 
+proc `<`*[T: tuple](x, y: T): bool =
   ## generic ``<`` operator for tuples that is lifted from the components
   ## of `x` and `y`. This implementation uses `cmp`.
   for a, b in fields(x, y):
@@ -1936,7 +2052,7 @@ proc `<`*[T: tuple](x, y: T): bool =
     if c > 0: return false
   return false
 
-proc `$`*[T: tuple|object](x: T): string = 
+proc `$`*[T: tuple|object](x: T): string =
   ## generic ``$`` operator for tuples that is lifted from the components
   ## of `x`. Example:
   ##
@@ -1946,13 +2062,13 @@ proc `$`*[T: tuple|object](x: T): string =
   result = "("
   var firstElement = true
   for name, value in fieldPairs(x):
-    if not(firstElement): result.add(", ")
+    if not firstElement: result.add(", ")
     result.add(name)
     result.add(": ")
     result.add($value)
     firstElement = false
   result.add(")")
-  
+
 proc collectionToString[T](x: T, b, e: string): string =
   result = b
   var firstElement = true
@@ -1962,7 +2078,7 @@ proc collectionToString[T](x: T, b, e: string): string =
     firstElement = false
   result.add(e)
 
-proc `$`*[T](x: set[T]): string = 
+proc `$`*[T](x: set[T]): string =
   ## generic ``$`` operator for sets that is lifted from the components
   ## of `x`. Example:
   ##
@@ -1970,7 +2086,7 @@ proc `$`*[T](x: set[T]): string =
   ##   ${23, 45} == "{23, 45}"
   collectionToString(x, "{", "}")
 
-proc `$`*[T](x: seq[T]): string = 
+proc `$`*[T](x: seq[T]): string =
   ## generic ``$`` operator for seqs that is lifted from the components
   ## of `x`. Example:
   ##
@@ -1981,7 +2097,7 @@ proc `$`*[T](x: seq[T]): string =
 when false:
   # causes bootstrapping to fail as we use array of chars and cstring should
   # match better ...
-  proc `$`*[T, IDX](x: array[IDX, T]): string = 
+  proc `$`*[T, IDX](x: array[IDX, T]): string =
     collectionToString(x, "[", "]")
 
 # ----------------- GC interface ---------------------------------------------
@@ -2023,18 +2139,17 @@ when not defined(nimrodVM) and hostOS != "standalone":
   proc GC_getStatistics*(): string {.rtl, benign.}
     ## returns an informative string about the GC's activity. This may be useful
     ## for tweaking.
-    
-  # XXX mark these as 'locks: 0' once 0.10.0 has been released
-  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.}
+
+  proc GC_ref*[T](x: ref T) {.magic: "GCref", benign.}
+  proc GC_ref*[T](x: seq[T]) {.magic: "GCref", benign.}
+  proc GC_ref*(x: string) {.magic: "GCref", benign.}
     ## 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", gcsafe.}
-  proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", gcsafe.}
-  proc GC_unref*(x: string) {.magic: "GCunref", gcsafe.}
+    ## n calls to `GC_unref` are needed to unmark `x`.
+
+  proc GC_unref*[T](x: ref T) {.magic: "GCunref", benign.}
+  proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", benign.}
+  proc GC_unref*(x: string) {.magic: "GCunref", benign.}
     ## see the documentation of `GC_ref`.
 
 template accumulateResult*(iter: expr) =
@@ -2067,19 +2182,19 @@ var
     ## application code should never set this hook! You better know what you
     ## do when setting this. If ``localRaiseHook`` returns false, the exception
     ## is caught and does not propagate further through the call stack.
-    
+
   outOfMemHook*: proc () {.nimcall, tags: [], benign.}
-    ## set this variable to provide a procedure that should be called 
+    ## set this variable to provide a procedure that should be called
     ## in case of an `out of memory`:idx: event. The standard handler
     ## writes an error message and terminates the program. `outOfMemHook` can
     ## be used to raise an exception in case of OOM like so:
-    ## 
+    ##
     ## .. code-block:: nim
     ##
     ##   var gOutOfMem: ref EOutOfMemory
     ##   new(gOutOfMem) # need to be allocated *before* OOM really happened!
     ##   gOutOfMem.msg = "out of memory"
-    ## 
+    ##
     ##   proc handleOOM() =
     ##     raise gOutOfMem
     ##
@@ -2120,7 +2235,8 @@ elif hostOS != "standalone":
       inc(i)
   {.pop.}
 
-proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect], benign.}
+proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
+  benign, sideEffect.}
   ## Writes and flushes the parameters to the standard output.
   ##
   ## Special built-in that takes a variable number of arguments. Each argument
@@ -2135,7 +2251,7 @@ proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect], benign
   ## <manual.html#nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_
   ## instead.
 
-proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect, 
+proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect,
                                            tags: [], raises: [].}
   ## Same as `echo <#echo>`_, but as a special semantic rule, ``debugEcho``
   ## pretends to be free of side effects, so that it can be used for debugging
@@ -2173,14 +2289,9 @@ when not declared(sysFatal):
       e.msg = message & arg
       raise e
 
-when defined(nimlocks):
-  proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", gcsafe, locks: 0.}
-    ## get type information for `x`. Ordinary code should not use this, but
-    ## the `typeinfo` module instead.
-else:
-  proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", gcsafe.}
-    ## get type information for `x`. Ordinary code should not use this, but
-    ## the `typeinfo` module instead.
+proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", benign.}
+  ## get type information for `x`. Ordinary code should not use this, but
+  ## the `typeinfo` module instead.
 
 {.push stackTrace: off.}
 proc abs*(x: int): int {.magic: "AbsI", noSideEffect.} =
@@ -2192,7 +2303,7 @@ proc abs*(x: int16): int16 {.magic: "AbsI", noSideEffect.} =
 proc abs*(x: int32): int32 {.magic: "AbsI", noSideEffect.} =
   if x < 0: -x else: x
 proc abs*(x: int64): int64 {.magic: "AbsI64", noSideEffect.} =
-  ## returns the absolute value of `x`. If `x` is ``low(x)`` (that 
+  ## returns the absolute value of `x`. If `x` is ``low(x)`` (that
   ## is -MININT for its type), an overflow exception is thrown (if overflow
   ## checking is turned on).
   if x < 0: -x else: x
@@ -2248,14 +2359,14 @@ when not defined(JS): #and not defined(NimrodVM):
       # we use binary mode in Windows:
       setmode(fileno(c_stdin), O_BINARY)
       setmode(fileno(c_stdout), O_BINARY)
-    
+
     when defined(endb):
       proc endbStep()
 
   # ----------------- IO Part ------------------------------------------------
   when hostOS != "standalone":
     type
-      CFile {.importc: "FILE", header: "<stdio.h>", 
+      CFile {.importc: "FILE", header: "<stdio.h>",
               final, incompletestruct.} = object
       File* = ptr CFile ## The type representing a file handle.
 
@@ -2305,9 +2416,9 @@ when not defined(JS): #and not defined(NimrodVM):
       ## Creates a ``TFile`` from a `filehandle` with given `mode`.
       ##
       ## Default mode is readonly. Returns true iff the file could be opened.
-      
+
     proc open*(filename: string,
-               mode: FileMode = fmRead, bufSize: int = -1): File = 
+               mode: FileMode = fmRead, bufSize: int = -1): File =
       ## Opens a file named `filename` with given `mode`.
       ##
       ## Default mode is readonly. Raises an ``IO`` exception if the file
@@ -2317,7 +2428,7 @@ when not defined(JS): #and not defined(NimrodVM):
 
     proc reopen*(f: File, filename: string, mode: FileMode = fmRead): bool {.
       tags: [], benign.}
-      ## reopens the file `f` with given `filename` and `mode`. This 
+      ## reopens the file `f` with given `filename` and `mode`. This
       ## is often used to redirect the `stdin`, `stdout` or `stderr`
       ## file variables.
       ##
@@ -2328,7 +2439,7 @@ when not defined(JS): #and not defined(NimrodVM):
 
     proc endOfFile*(f: File): bool {.tags: [], benign.}
       ## Returns true iff `f` is at the end.
-      
+
     proc readChar*(f: File): char {.
       importc: "fgetc", header: "<stdio.h>", tags: [ReadIOEffect].}
       ## Reads a single character from the stream `f`.
@@ -2341,7 +2452,7 @@ when not defined(JS): #and not defined(NimrodVM):
       ##
       ## Raises an IO exception in case of an error. It is an error if the
       ## current file position is not at the beginning of the file.
-    
+
     proc readFile*(filename: string): TaintedString {.tags: [ReadIOEffect], benign.}
       ## Opens a file named `filename` for reading.
       ##
@@ -2370,8 +2481,8 @@ when not defined(JS): #and not defined(NimrodVM):
       ## reads a line of text from the file `f`. May throw an IO exception.
       ## A line of text may be delimited by ``CR``, ``LF`` or
       ## ``CRLF``. The newline character(s) are not part of the returned string.
-    
-    proc readLine*(f: File, line: var TaintedString): bool {.tags: [ReadIOEffect], 
+
+    proc readLine*(f: File, line: var TaintedString): bool {.tags: [ReadIOEffect],
                   benign.}
       ## reads a line of text from the file `f` into `line`. `line` must not be
       ## ``nil``! May throw an IO exception.
@@ -2380,49 +2491,45 @@ when not defined(JS): #and not defined(NimrodVM):
       ## Returns ``false`` if the end of the file has been reached, ``true``
       ## otherwise. If ``false`` is returned `line` contains no new data.
 
-    when not defined(booting):
-      proc writeln*[Ty](f: File, x: varargs[Ty, `$`]) {.inline, 
-                               tags: [WriteIOEffect], gcsafe, locks: 0.}
-        ## writes the values `x` to `f` and then writes "\n".
-        ## May throw an IO exception.
-    else:
-      proc writeln*[Ty](f: File, x: varargs[Ty, `$`]) {.inline, 
-                               tags: [WriteIOEffect].}
+    proc writeln*[Ty](f: File, x: varargs[Ty, `$`]) {.inline,
+                             tags: [WriteIOEffect], benign.}
+      ## writes the values `x` to `f` and then writes "\n".
+      ## May throw an IO exception.
 
     proc getFileSize*(f: File): int64 {.tags: [ReadIOEffect], benign.}
       ## retrieves the file size (in bytes) of `f`.
 
-    proc readBytes*(f: File, a: var openArray[int8], start, len: int): int {.
+    proc readBytes*(f: File, a: var openArray[int8|uint8], start, len: Natural): int {.
       tags: [ReadIOEffect], benign.}
       ## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
       ## the actual number of bytes that have been read which may be less than
       ## `len` (if not as many bytes are remaining), but not greater.
 
-    proc readChars*(f: File, a: var openArray[char], start, len: int): int {.
+    proc readChars*(f: File, a: var openArray[char], start, len: Natural): int {.
       tags: [ReadIOEffect], benign.}
       ## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
       ## the actual number of bytes that have been read which may be less than
       ## `len` (if not as many bytes are remaining), but not greater.
 
-    proc readBuffer*(f: File, buffer: pointer, len: int): int {.
+    proc readBuffer*(f: File, buffer: pointer, len: Natural): int {.
       tags: [ReadIOEffect], benign.}
       ## reads `len` bytes into the buffer pointed to by `buffer`. Returns
       ## the actual number of bytes that have been read which may be less than
       ## `len` (if not as many bytes are remaining), but not greater.
 
-    proc writeBytes*(f: File, a: openArray[int8], start, len: int): int {.
+    proc writeBytes*(f: File, a: openArray[int8|uint8], start, len: Natural): int {.
       tags: [WriteIOEffect], benign.}
       ## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
       ## the number of actual written bytes, which may be less than `len` in case
       ## of an error.
 
-    proc writeChars*(f: File, a: openArray[char], start, len: int): int {.
+    proc writeChars*(f: File, a: openArray[char], start, len: Natural): int {.
       tags: [WriteIOEffect], benign.}
       ## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
       ## the number of actual written bytes, which may be less than `len` in case
       ## of an error.
 
-    proc writeBuffer*(f: File, buffer: pointer, len: int): int {.
+    proc writeBuffer*(f: File, buffer: pointer, len: Natural): int {.
       tags: [WriteIOEffect], benign.}
       ## writes the bytes of buffer pointed to by the parameter `buffer` to the
       ## file `f`. Returns the number of actual written bytes, which may be less
@@ -2444,7 +2551,7 @@ when not defined(JS): #and not defined(NimrodVM):
     when not defined(nimfix):
       {.deprecated: [fileHandle: getFileHandle].}
 
-    proc cstringArrayToSeq*(a: cstringArray, len: int): seq[string] =
+    proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] =
       ## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be
       ## of length ``len``.
       newSeq(result, len)
@@ -2478,11 +2585,11 @@ when not defined(JS): #and not defined(NimrodVM):
       dealloc(a)
 
   when not defined(NimrodVM):
-    proc atomicInc*(memLoc: var int, x: int = 1): int {.inline, 
+    proc atomicInc*(memLoc: var int, x: int = 1): int {.inline,
       discardable, benign.}
       ## atomic increment of `memLoc`. Returns the value after the operation.
-    
-    proc atomicDec*(memLoc: var int, x: int = 1): int {.inline, 
+
+    proc atomicDec*(memLoc: var int, x: int = 1): int {.inline,
       discardable, benign.}
       ## atomic decrement of `memLoc`. Returns the value after the operation.
 
@@ -2496,21 +2603,21 @@ when not defined(JS): #and not defined(NimrodVM):
       context: C_JmpBuf
       hasRaiseAction: bool
       raiseAction: proc (e: ref Exception): bool {.closure.}
-  
+
   when declared(initAllocator):
     initAllocator()
   when hasThreadSupport:
     include "system/syslocks"
-    include "system/threads"
+    when hostOS != "standalone": include "system/threads"
   elif not defined(nogc) and not defined(NimrodVM) and hostOS != "standalone":
     when not defined(useNimRtl) and not defined(createNimRtl): initStackBottom()
     initGC()
 
   when not defined(NimrodVM):
-    proc setControlCHook*(hook: proc () {.noconv.})
+    proc setControlCHook*(hook: proc () {.noconv.} not nil)
       ## allows you to override the behaviour of your application when CTRL+C
       ## is pressed. Only one such hook is supported.
-      
+
     proc writeStackTrace*() {.tags: [WriteIOEffect].}
       ## writes the current stack trace to ``stderr``. This is only works
       ## for debug builds.
@@ -2521,20 +2628,20 @@ when not defined(JS): #and not defined(NimrodVM):
       proc getStackTrace*(e: ref Exception): string
         ## gets the stack trace associated with `e`, which is the stack that
         ## lead to the ``raise`` statement. This only works for debug builds.
-        
+
     {.push stack_trace: off, profiler:off.}
     when hostOS == "standalone":
       include "system/embedded"
     else:
       include "system/excpt"
     include "system/chcks"
-      
+
     # we cannot compile this with stack tracing on
     # as it would recurse endlessly!
     include "system/arithm"
     {.pop.} # stack trace
   {.pop.} # stack trace
-      
+
   when hostOS != "standalone" and not defined(NimrodVM):
     include "system/dyncalls"
   when not defined(NimrodVM):
@@ -2542,7 +2649,7 @@ when not defined(JS): #and not defined(NimrodVM):
 
     const
       GenericSeqSize = (2 * sizeof(int))
-      
+
     proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
       sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase")
       var d: int
@@ -2662,7 +2769,7 @@ when not defined(JS): #and not defined(NimrodVM):
       ##       process(value)
       ##     else:
       ##       echo "Value too big!"
-    
+
     proc unlikely*(val: bool): bool {.importc: "unlikely", nodecl, nosideeffect.}
       ## Hints the optimizer that `val` is likely going to be false.
       ##
@@ -2676,7 +2783,7 @@ when not defined(JS): #and not defined(NimrodVM):
       ##       echo "Value too big!"
       ##     else:
       ##       process(value)
-      
+
     proc rawProc*[T: proc](x: T): pointer {.noSideEffect, inline.} =
       ## retrieves the raw proc pointer of the closure `x`. This is
       ## useful for interfacing closures with C.
@@ -2708,20 +2815,20 @@ elif defined(JS):
   proc GC_enableMarkAndSweep() = discard
   proc GC_disableMarkAndSweep() = discard
   proc GC_getStatistics(): string = return ""
-  
+
   proc getOccupiedMem(): int = return -1
   proc getFreeMem(): int = return -1
   proc getTotalMem(): int = return -1
 
   proc dealloc(p: pointer) = discard
-  proc alloc(size: int): pointer = discard
-  proc alloc0(size: int): pointer = discard
-  proc realloc(p: pointer, newsize: int): pointer = discard
+  proc alloc(size: Natural): pointer = discard
+  proc alloc0(size: Natural): pointer = discard
+  proc realloc(p: pointer, newsize: Natural): pointer = discard
 
-  proc allocShared(size: int): pointer = discard
-  proc allocShared0(size: int): pointer = discard
+  proc allocShared(size: Natural): pointer = discard
+  proc allocShared0(size: Natural): pointer = discard
   proc deallocShared(p: pointer) = discard
-  proc reallocShared(p: pointer, newsize: int): pointer = discard
+  proc reallocShared(p: pointer, newsize: Natural): pointer = discard
 
   when defined(JS):
     include "system/jssys"
@@ -2731,7 +2838,7 @@ elif defined(JS):
       if x == y: return 0
       if x < y: return -1
       return 1
-  
+
   when defined(nimffi):
     include "system/sysio"
 
@@ -2765,32 +2872,31 @@ template spliceImpl(s, a, L, b: expr): stmt {.immediate.} =
     # cut down:
     setLen(s, newLen)
   # fill the hole:
-  for i in 0 .. <b.len: s[i+a] = b[i]  
+  for i in 0 .. <b.len: s[i+a] = b[i]
 
 when hostOS != "standalone":
   proc `[]`*(s: string, x: Slice[int]): string {.inline.} =
-    ## slice operation for strings. Negative indexes are supported.
-    result = s.substr(x.a-|s, x.b-|s)
+    ## slice operation for strings.
+    result = s.substr(x.a, x.b)
 
-  proc `[]=`*(s: var string, x: Slice[int], b: string) = 
-    ## slice assignment for strings. Negative indexes are supported. If
+  proc `[]=`*(s: var string, x: Slice[int], b: string) =
+    ## slice assignment for strings. If
     ## ``b.len`` is not exactly the number of elements that are referred to
     ## by `x`, a `splice`:idx: is performed:
     ##
     ## .. code-block:: nim
     ##   var s = "abcdef"
-    ##   s[1 .. -2] = "xyz"
+    ##   s[1 .. ^2] = "xyz"
     ##   assert s == "axyzf"
-    var a = x.a-|s
-    var L = x.b-|s - a + 1
+    var a = x.a
+    var L = x.b - a + 1
     if L == b.len:
       for i in 0 .. <L: s[i+a] = b[i]
     else:
       spliceImpl(s, a, L, b)
 
 proc `[]`*[Idx, T](a: array[Idx, T], x: Slice[int]): seq[T] =
-  ## slice operation for arrays. Negative indexes are **not** supported
-  ## because the array might have negative bounds.
+  ## slice operation for arrays.
   when low(a) < 0:
     {.error: "Slicing for arrays with negative indices is unsupported.".}
   var L = x.b - x.a + 1
@@ -2798,8 +2904,7 @@ proc `[]`*[Idx, T](a: array[Idx, T], x: Slice[int]): seq[T] =
   for i in 0.. <L: result[i] = a[i + x.a]
 
 proc `[]=`*[Idx, T](a: var array[Idx, T], x: Slice[int], b: openArray[T]) =
-  ## slice assignment for arrays. Negative indexes are **not** supported
-  ## because the array might have negative bounds.
+  ## slice assignment for arrays.
   when low(a) < 0:
     {.error: "Slicing for arrays with negative indices is unsupported.".}
   var L = x.b - x.a + 1
@@ -2809,40 +2914,34 @@ proc `[]=`*[Idx, T](a: var array[Idx, T], x: Slice[int], b: openArray[T]) =
     sysFatal(RangeError, "different lengths for slice assignment")
 
 proc `[]`*[Idx, T](a: array[Idx, T], x: Slice[Idx]): seq[T] =
-  ## slice operation for arrays. Negative indexes are **not** supported
-  ## because the array might have negative bounds.
+  ## slice operation for arrays.
   var L = ord(x.b) - ord(x.a) + 1
   newSeq(result, L)
-  var j = x.a
-  for i in 0.. <L: 
-    result[i] = a[j]
-    inc(j)
+  for i in 0.. <L:
+    result[i] = a[Idx(ord(x.a) + i)]
 
 proc `[]=`*[Idx, T](a: var array[Idx, T], x: Slice[Idx], b: openArray[T]) =
-  ## slice assignment for arrays. Negative indexes are **not** supported
-  ## because the array might have negative bounds.
+  ## slice assignment for arrays.
   var L = ord(x.b) - ord(x.a) + 1
   if L == b.len:
-    var j = x.a
-    for i in 0 .. <L: 
-      a[j] = b[i]
-      inc(j)
+    for i in 0 .. <L:
+      a[Idx(ord(x.a) + i)] = b[i]
   else:
     sysFatal(RangeError, "different lengths for slice assignment")
 
-proc `[]`*[T](s: seq[T], x: Slice[int]): seq[T] = 
-  ## slice operation for sequences. Negative indexes are supported.
-  var a = x.a-|s
-  var L = x.b-|s - a + 1
+proc `[]`*[T](s: seq[T], x: Slice[int]): seq[T] =
+  ## slice operation for sequences.
+  var a = x.a
+  var L = x.b - a + 1
   newSeq(result, L)
   for i in 0.. <L: result[i] = s[i + a]
 
-proc `[]=`*[T](s: var seq[T], x: Slice[int], b: openArray[T]) = 
-  ## slice assignment for sequences. Negative indexes are supported. If
+proc `[]=`*[T](s: var seq[T], x: Slice[int], b: openArray[T]) =
+  ## slice assignment for sequences. If
   ## ``b.len`` is not exactly the number of elements that are referred to
-  ## by `x`, a `splice`:idx: is performed. 
-  var a = x.a-|s
-  var L = x.b-|s - a + 1
+  ## by `x`, a `splice`:idx: is performed.
+  var a = x.a
+  var L = x.b - a + 1
   if L == b.len:
     for i in 0 .. <L: s[i+a] = b[i]
   else:
@@ -2871,7 +2970,7 @@ proc staticExec*(command: string, input = ""): string {.
   ## to the executed program.
   ##
   ## .. code-block:: nim
-  ##     const buildInfo = "Revision " & staticExec("git rev-parse HEAD") & 
+  ##     const buildInfo = "Revision " & staticExec("git rev-parse HEAD") &
   ##                       "\nCompiled on " & staticExec("uname -v")
   ##
   ## `gorge <#gorge>`_ is an alias for ``staticExec``. Note that you can use
@@ -2913,7 +3012,7 @@ proc `&=`* (x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
 proc astToStr*[T](x: T): string {.magic: "AstToStr", noSideEffect.}
   ## converts the AST of `x` into a string representation. This is very useful
   ## for debugging.
-  
+
 proc instantiationInfo*(index = -1, fullPaths = false): tuple[
   filename: string, line: int] {. magic: "InstantiationInfo", noSideEffect.}
   ## provides access to the compiler's instantiation stack line information.
@@ -2941,8 +3040,8 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[
   ##     result = a[pos]
   ##
   ##   when isMainModule:
-  ##     testException(EInvalidIndex, tester(30))
-  ##     testException(EInvalidIndex, tester(1))
+  ##     testException(IndexError, tester(30))
+  ##     testException(IndexError, tester(1))
   ##     # --> Test failure at example.nim:20 with 'tester(1)'
 
 template currentSourcePath*: string = instantiationInfo(-1, true).filename
@@ -2951,13 +3050,12 @@ template currentSourcePath*: string = instantiationInfo(-1, true).filename
 proc raiseAssert*(msg: string) {.noinline.} =
   sysFatal(AssertionError, msg)
 
-when true:
-  proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} =
-    # trick the compiler to not list ``EAssertionFailed`` when called
-    # by ``assert``.
-    type THide = proc (msg: string) {.noinline, raises: [], noSideEffect,
-                                      tags: [].}
-    THide(raiseAssert)(msg)
+proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} =
+  # trick the compiler to not list ``AssertionError`` when called
+  # by ``assert``.
+  type THide = proc (msg: string) {.noinline, raises: [], noSideEffect,
+                                    tags: [].}
+  THide(raiseAssert)(msg)
 
 template assert*(cond: bool, msg = "") =
   ## Raises ``AssertionError`` with `msg` if `cond` is false. Note
@@ -2990,6 +3088,15 @@ iterator items*[T](a: seq[T]): T {.inline.} =
     inc(i)
     assert(len(a) == L, "seq modified while iterating over it")
 
+iterator mitems*[T](a: var seq[T]): var T {.inline.} =
+  ## iterates over each item of `a` so that you can modify the yielded value.
+  var i = 0
+  let L = len(a)
+  while i < L:
+    yield a[i]
+    inc(i)
+    assert(len(a) == L, "seq modified while iterating over it")
+
 iterator items*(a: string): char {.inline.} =
   ## iterates over each item of `a`.
   var i = 0
@@ -2999,35 +3106,38 @@ iterator items*(a: string): char {.inline.} =
     inc(i)
     assert(len(a) == L, "string modified while iterating over it")
 
+iterator mitems*(a: var string): var char {.inline.} =
+  ## iterates over each item of `a` so that you can modify the yielded value.
+  var i = 0
+  let L = len(a)
+  while i < L:
+    yield a[i]
+    inc(i)
+    assert(len(a) == L, "string modified while iterating over it")
+
 when not defined(nimhygiene):
   {.pragma: inject.}
 
 template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} =
   ## Sets an assertion failure handler that will intercept any assert
-  ## statements following `onFailedAssert` in the current lexical scope.
-  ## Can be defined multiple times in a single function.
-  ##  
-  ## .. code-block:: nim
+  ## statements following `onFailedAssert` in the current module scope.
   ##
-  ##   proc example(x: int): TErrorCode =
-  ##     onFailedAssert(msg):
-  ##       log msg
-  ##       return E_FAIL
-  ## 
-  ##     assert(...)
-  ##     
-  ##     onFailedAssert(msg):
-  ##       raise newException(EMyException, msg)
-  ##
-  ##     assert(...)
+  ## .. code-block:: nim
+  ##  # module-wide policy to change the failed assert
+  ##  # exception type in order to include a lineinfo
+  ##  onFailedAssert(msg):
+  ##    var e = new(TMyError)
+  ##    e.msg = msg
+  ##    e.lineinfo = instantiationInfo(-2)
+  ##    raise e
   ##
-  template failedAssertImpl(msgIMPL: string): stmt {.dirty, immediate.} =
+  template failedAssertImpl(msgIMPL: string): stmt {.dirty.} =
     let msg = msgIMPL
     code
 
 proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
   ## marks a sequence `s` as `shallow`:idx:. Subsequent assignments will not
-  ## perform deep copies of `s`. This is only useful for optimization 
+  ## perform deep copies of `s`. This is only useful for optimization
   ## purposes.
   when not defined(JS) and not defined(NimrodVM):
     var s = cast[PGenericSeq](s)
@@ -3035,27 +3145,29 @@ proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
 
 proc shallow*(s: var string) {.noSideEffect, inline.} =
   ## marks a string `s` as `shallow`:idx:. Subsequent assignments will not
-  ## perform deep copies of `s`. This is only useful for optimization 
+  ## perform deep copies of `s`. This is only useful for optimization
   ## purposes.
   when not defined(JS) and not defined(NimrodVM):
     var s = cast[PGenericSeq](s)
     s.reserved = s.reserved or seqShallowFlag
 
 type
-  TNimrodNode {.final.} = object
-  PNimrodNode* {.magic: "PNimrodNode".} = ref TNimrodNode
+  NimNodeObj = object
+
+  NimNode* {.magic: "PNimrodNode".} = ref NimNodeObj
     ## represents a Nim AST node. Macros operate on this type.
+{.deprecated: [PNimrodNode: NimNode].}
 
 when false:
   template eval*(blk: stmt): stmt =
     ## executes a block of code at compile time just as if it was a macro
-    ## optionally, the block can return an AST tree that will replace the 
+    ## optionally, the block can return an AST tree that will replace the
     ## eval expression
     macro payload: stmt {.gensym.} = blk
     payload()
 
 when hostOS != "standalone":
-  proc insert*(x: var string, item: string, i = 0) {.noSideEffect.} = 
+  proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} =
     ## inserts `item` into `x` at position `i`.
     var xl = x.len
     setLen(x, xl+item.len)
@@ -3068,7 +3180,7 @@ when hostOS != "standalone":
       x[j+i] = item[j]
       inc(j)
 
-proc compiles*(x): bool {.magic: "Compiles", noSideEffect.} =
+proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} =
   ## Special compile-time procedure that checks whether `x` can be compiled
   ## without any semantic error.
   ## This can be used to check whether a type supports some operation:
@@ -3095,7 +3207,7 @@ when hostOS != "standalone":
     if x == nil: x = y
     else: x.add(y)
 
-proc locals*(): RootObj {.magic: "Locals", noSideEffect.} =
+proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} =
   ## generates a tuple constructor expression listing all the local variables
   ## in the current scope. This is quite fast as it does not rely
   ## on any debug or runtime information. Note that in constrast to what
@@ -3136,4 +3248,28 @@ proc procCall*(x: expr) {.magic: "ProcCall".} =
   ##   procCall someMethod(a, b)
   discard
 
+proc `^`*(x: int): int {.noSideEffect, magic: "Roof".} =
+  ## builtin `roof`:idx: operator that can be used for convenient array access.
+  ## ``a[^x]`` is rewritten to ``a[a.len-x]``. However currently the ``a``
+  ## expression must not have side effects for this to compile. Note that since
+  ## this is a builtin, it automatically works for all kinds of
+  ## overloaded ``[]`` or ``[]=`` accessors.
+  discard
+
+template `..^`*(a, b: expr): expr =
+  ## a shortcut for '.. ^' to avoid the common gotcha that a space between
+  ## '..' and '^' is required.
+  a .. ^b
+
+template `..<`*(a, b: expr): expr =
+  ## a shortcut for '.. <' to avoid the common gotcha that a space between
+  ## '..' and '<' is required.
+  a .. <b
+
+proc xlen*(x: string): int {.magic: "XLenStr", noSideEffect.} = discard
+proc xlen*[T](x: seq[T]): int {.magic: "XLenSeq", noSideEffect.} =
+  ## returns the length of a sequence or a string without testing for 'nil'.
+  ## This is an optimization that rarely makes sense.
+  discard
+
 {.pop.} #{.push warning[GcMem]: off.}
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index fd3ced832..ad3419808 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -8,7 +8,7 @@
 #
 
 # Low level allocator for Nim. Has been designed to support the GC.
-# TODO: 
+# TODO:
 # - eliminate "used" field
 # - make searching for block O(1)
 {.push profiler:off.}
@@ -21,37 +21,37 @@
 # used with a size of 0:
 const weirdUnmap = not (defined(amd64) or defined(i386)) or defined(windows)
 
-when defined(posix): 
+when defined(posix):
   const
-    PROT_READ  = 1             # page can be read 
-    PROT_WRITE = 2             # page can be written 
-    MAP_PRIVATE = 2'i32        # Changes are private 
-  
+    PROT_READ  = 1             # page can be read
+    PROT_WRITE = 2             # page can be written
+    MAP_PRIVATE = 2'i32        # Changes are private
+
   when defined(macosx) or defined(bsd):
     const MAP_ANONYMOUS = 0x1000
-  elif defined(solaris): 
+  elif defined(solaris):
     const MAP_ANONYMOUS = 0x100
   else:
     var
       MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint
-    
+
   proc mmap(adr: pointer, len: int, prot, flags, fildes: cint,
             off: int): pointer {.header: "<sys/mman.h>".}
 
   proc munmap(adr: pointer, len: int) {.header: "<sys/mman.h>".}
-  
-  proc osAllocPages(size: int): pointer {.inline.} = 
-    result = mmap(nil, size, PROT_READ or PROT_WRITE, 
+
+  proc osAllocPages(size: int): pointer {.inline.} =
+    result = mmap(nil, size, PROT_READ or PROT_WRITE,
                              MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
     if result == nil or result == cast[pointer](-1):
       raiseOutOfMem()
-      
+
   proc osDeallocPages(p: pointer, size: int) {.inline} =
     when reallyOsDealloc: munmap(p, size)
-  
-elif defined(windows): 
+
+elif defined(windows):
   const
-    MEM_RESERVE = 0x2000 
+    MEM_RESERVE = 0x2000
     MEM_COMMIT = 0x1000
     MEM_TOP_DOWN = 0x100000
     PAGE_READWRITE = 0x04
@@ -62,12 +62,12 @@ elif defined(windows):
   proc virtualAlloc(lpAddress: pointer, dwSize: int, flAllocationType,
                     flProtect: int32): pointer {.
                     header: "<windows.h>", stdcall, importc: "VirtualAlloc".}
-  
-  proc virtualFree(lpAddress: pointer, dwSize: int, 
+
+  proc virtualFree(lpAddress: pointer, dwSize: int,
                    dwFreeType: int32) {.header: "<windows.h>", stdcall,
                    importc: "VirtualFree".}
-  
-  proc osAllocPages(size: int): pointer {.inline.} = 
+
+  proc osAllocPages(size: int): pointer {.inline.} =
     result = virtualAlloc(nil, size, MEM_RESERVE or MEM_COMMIT,
                           PAGE_READWRITE)
     if result == nil: raiseOutOfMem()
@@ -82,7 +82,7 @@ elif defined(windows):
     when reallyOsDealloc: virtualFree(p, 0, MEM_RELEASE)
     #VirtualFree(p, size, MEM_DECOMMIT)
 
-else: 
+else:
   {.error: "Port memory manager to your platform".}
 
 # --------------------- end of non-portable code -----------------------------
@@ -97,17 +97,17 @@ const
   InitialMemoryRequest = ChunkOsReturn div 2 # < ChunkOsReturn!
   SmallChunkSize = PageSize
 
-type 
+type
   PTrunk = ptr TTrunk
-  TTrunk {.final.} = object 
+  TTrunk {.final.} = object
     next: PTrunk         # all nodes are connected with this pointer
     key: int             # start address at bit 0
     bits: array[0..IntsPerTrunk-1, int] # a bit vector
-  
+
   TTrunkBuckets = array[0..255, PTrunk]
-  TIntSet {.final.} = object 
+  TIntSet {.final.} = object
     data: TTrunkBuckets
-  
+
 type
   TAlignType = BiggestFloat
   TFreeCell {.final, pure.} = object
@@ -123,14 +123,14 @@ type
     prevSize: int        # size of previous chunk; for coalescing
     size: int            # if < PageSize it is a small chunk
     used: bool           # later will be optimized into prevSize...
-  
+
   TSmallChunk = object of TBaseChunk
     next, prev: PSmallChunk  # chunks of the same size
     freeList: ptr TFreeCell
-    free: int            # how many bytes remain    
+    free: int            # how many bytes remain
     acc: int             # accumulator for small object allocation
     data: TAlignType     # start of usable memory
-  
+
   TBigChunk = object of TBaseChunk # not necessarily > PageSize!
     next, prev: PBigChunk    # chunks of the same (or bigger) size
     align: int
@@ -139,7 +139,7 @@ type
 template smallChunkOverhead(): expr = sizeof(TSmallChunk)-sizeof(TAlignType)
 template bigChunkOverhead(): expr = sizeof(TBigChunk)-sizeof(TAlignType)
 
-proc roundup(x, v: int): int {.inline.} = 
+proc roundup(x, v: int): int {.inline.} =
   result = (x + (v-1)) and not (v-1)
   sysAssert(result >= x, "roundup: result < x")
   #return ((-x) and (v-1)) +% x
@@ -153,7 +153,7 @@ sysAssert(roundup(65, 8) == 72, "roundup broken 2")
 # endings of big chunks. This is needed by the merging operation. The only
 # remaining operation is best-fit for big chunks. Since there is a size-limit
 # for big chunks (because greater than the limit means they are returned back
-# to the OS), a fixed size array can be used. 
+# to the OS), a fixed size array can be used.
 
 type
   PLLChunk = ptr TLLChunk
@@ -163,21 +163,21 @@ type
     next: PLLChunk           # next low-level chunk; only needed for dealloc
 
   PAvlNode = ptr TAvlNode
-  TAvlNode {.pure, final.} = object 
-    link: array[0..1, PAvlNode] # Left (0) and right (1) links 
+  TAvlNode {.pure, final.} = object
+    link: array[0..1, PAvlNode] # Left (0) and right (1) links
     key, upperBound: int
     level: int
-    
+
   TMemRegion {.final, pure.} = object
     minLargeObj, maxLargeObj: int
     freeSmallChunks: array[0..SmallChunkSize div MemAlign-1, PSmallChunk]
     llmem: PLLChunk
     currMem, maxMem, freeMem: int # memory sizes (allocated from OS)
-    lastSize: int # needed for the case that OS gives us pages linearly 
+    lastSize: int # needed for the case that OS gives us pages linearly
     freeChunksList: PBigChunk # XXX make this a datastructure with O(1) access
     chunkStarts: TIntSet
     root, deleted, last, freeAvlNodes: PAvlNode
-  
+
 # shared:
 var
   bottomData: TAvlNode
@@ -191,7 +191,7 @@ proc initAllocator() =
     bottom.link[1] = bottom
 {.pop.}
 
-proc incCurrMem(a: var TMemRegion, bytes: int) {.inline.} = 
+proc incCurrMem(a: var TMemRegion, bytes: int) {.inline.} =
   inc(a.currMem, bytes)
 
 proc decCurrMem(a: var TMemRegion, bytes: int) {.inline.} =
@@ -199,11 +199,11 @@ proc decCurrMem(a: var TMemRegion, bytes: int) {.inline.} =
   dec(a.currMem, bytes)
 
 proc getMaxMem(a: var TMemRegion): int =
-  # Since we update maxPagesCount only when freeing pages, 
+  # Since we update maxPagesCount only when freeing pages,
   # maxPagesCount may not be up to date. Thus we use the
   # maximum of these both values here:
   result = max(a.currMem, a.maxMem)
-  
+
 proc llAlloc(a: var TMemRegion, size: int): pointer =
   # *low-level* alloc for the memory managers data structures. Deallocation
   # is done at he end of the allocator's life time.
@@ -251,15 +251,15 @@ proc llDeallocAll(a: var TMemRegion) =
     var next = it.next
     osDeallocPages(it, PageSize)
     it = next
-  
-proc intSetGet(t: TIntSet, key: int): PTrunk = 
+
+proc intSetGet(t: TIntSet, key: int): PTrunk =
   var it = t.data[key and high(t.data)]
-  while it != nil: 
+  while it != nil:
     if it.key == key: return it
     it = it.next
   result = nil
 
-proc intSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk = 
+proc intSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk =
   result = intSetGet(t, key)
   if result == nil:
     result = cast[PTrunk](llAlloc(a, sizeof(result[])))
@@ -267,20 +267,20 @@ proc intSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk =
     t.data[key and high(t.data)] = result
     result.key = key
 
-proc contains(s: TIntSet, key: int): bool = 
+proc contains(s: TIntSet, key: int): bool =
   var t = intSetGet(s, key shr TrunkShift)
-  if t != nil: 
+  if t != nil:
     var u = key and TrunkMask
     result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
-  else: 
+  else:
     result = false
-  
-proc incl(a: var TMemRegion, s: var TIntSet, key: int) = 
+
+proc incl(a: var TMemRegion, s: var TIntSet, key: int) =
   var t = intSetPut(a, s, key shr TrunkShift)
   var u = key and TrunkMask
   t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask))
 
-proc excl(s: var TIntSet, key: int) = 
+proc excl(s: var TIntSet, key: int) =
   var t = intSetGet(s, key shr TrunkShift)
   if t != nil:
     var u = key and TrunkMask
@@ -304,11 +304,11 @@ iterator elements(t: TIntSet): int {.inline.} =
           w = w shr 1
         inc(i)
       r = r.next
-  
-proc isSmallChunk(c: PChunk): bool {.inline.} = 
+
+proc isSmallChunk(c: PChunk): bool {.inline.} =
   return c.size <= SmallChunkSize-smallChunkOverhead()
-  
-proc chunkUnused(c: PChunk): bool {.inline.} = 
+
+proc chunkUnused(c: PChunk): bool {.inline.} =
   result = not c.used
 
 iterator allObjects(m: TMemRegion): pointer {.inline.} =
@@ -319,7 +319,7 @@ iterator allObjects(m: TMemRegion): pointer {.inline.} =
       if not chunkUnused(c):
         if isSmallChunk(c):
           var c = cast[PSmallChunk](c)
-          
+
           let size = c.size
           var a = cast[ByteAddress](addr(c.data))
           let limit = a + c.acc
@@ -334,17 +334,17 @@ proc isCell(p: pointer): bool {.inline.} =
   result = cast[ptr TFreeCell](p).zeroField >% 1
 
 # ------------- chunk management ----------------------------------------------
-proc pageIndex(c: PChunk): int {.inline.} = 
+proc pageIndex(c: PChunk): int {.inline.} =
   result = cast[ByteAddress](c) shr PageShift
 
-proc pageIndex(p: pointer): int {.inline.} = 
+proc pageIndex(p: pointer): int {.inline.} =
   result = cast[ByteAddress](p) shr PageShift
 
-proc pageAddr(p: pointer): PChunk {.inline.} = 
+proc pageAddr(p: pointer): PChunk {.inline.} =
   result = cast[PChunk](cast[ByteAddress](p) and not PageMask)
   #sysAssert(Contains(allocator.chunkStarts, pageIndex(result)))
 
-proc requestOsChunks(a: var TMemRegion, size: int): PBigChunk = 
+proc requestOsChunks(a: var TMemRegion, size: int): PBigChunk =
   incCurrMem(a, size)
   inc(a.freeMem, size)
   result = cast[PBigChunk](osAllocPages(size))
@@ -373,7 +373,7 @@ proc requestOsChunks(a: var TMemRegion, size: int): PBigChunk =
     result.prevSize = 0 # unknown
   a.lastSize = size # for next request
 
-proc freeOsChunks(a: var TMemRegion, p: pointer, size: int) = 
+proc freeOsChunks(a: var TMemRegion, p: pointer, size: int) =
   # update next.prevSize:
   var c = cast[PChunk](p)
   var nxt = cast[ByteAddress](p) +% c.size
@@ -387,36 +387,36 @@ proc freeOsChunks(a: var TMemRegion, p: pointer, size: int) =
   dec(a.freeMem, size)
   #c_fprintf(c_stdout, "[Alloc] back to OS: %ld\n", size)
 
-proc isAccessible(a: TMemRegion, p: pointer): bool {.inline.} = 
+proc isAccessible(a: TMemRegion, p: pointer): bool {.inline.} =
   result = contains(a.chunkStarts, pageIndex(p))
 
-proc contains[T](list, x: T): bool = 
+proc contains[T](list, x: T): bool =
   var it = list
   while it != nil:
     if it == x: return true
     it = it.next
-    
+
 proc writeFreeList(a: TMemRegion) =
   var it = a.freeChunksList
   c_fprintf(c_stdout, "freeChunksList: %p\n", it)
-  while it != nil: 
-    c_fprintf(c_stdout, "it: %p, next: %p, prev: %p\n", 
+  while it != nil:
+    c_fprintf(c_stdout, "it: %p, next: %p, prev: %p\n",
               it, it.next, it.prev)
     it = it.next
 
-proc listAdd[T](head: var T, c: T) {.inline.} = 
+proc listAdd[T](head: var T, c: T) {.inline.} =
   sysAssert(c notin head, "listAdd 1")
   sysAssert c.prev == nil, "listAdd 2"
   sysAssert c.next == nil, "listAdd 3"
   c.next = head
-  if head != nil: 
+  if head != nil:
     sysAssert head.prev == nil, "listAdd 4"
     head.prev = c
   head = c
 
 proc listRemove[T](head: var T, c: T) {.inline.} =
   sysAssert(c in head, "listRemove")
-  if c == head: 
+  if c == head:
     head = c.next
     sysAssert c.prev == nil, "listRemove 2"
     if head != nil: head.prev = nil
@@ -426,15 +426,15 @@ proc listRemove[T](head: var T, c: T) {.inline.} =
     if c.next != nil: c.next.prev = c.prev
   c.next = nil
   c.prev = nil
-  
-proc updatePrevSize(a: var TMemRegion, c: PBigChunk, 
-                    prevSize: int) {.inline.} = 
+
+proc updatePrevSize(a: var TMemRegion, c: PBigChunk,
+                    prevSize: int) {.inline.} =
   var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
   sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "updatePrevSize")
   if isAccessible(a, ri):
     ri.prevSize = prevSize
-  
-proc freeBigChunk(a: var TMemRegion, c: PBigChunk) = 
+
+proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
   var c = c
   sysAssert(c.size >= PageSize, "freeBigChunk")
   inc(a.freeMem, c.size)
@@ -448,7 +448,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
         inc(c.size, ri.size)
         excl(a.chunkStarts, pageIndex(ri))
   when coalescLeft:
-    if c.prevSize != 0: 
+    if c.prevSize != 0:
       var le = cast[PChunk](cast[ByteAddress](c) -% c.prevSize)
       sysAssert((cast[ByteAddress](le) and PageMask) == 0, "freeBigChunk 4")
       if isAccessible(a, le) and chunkUnused(le):
@@ -467,7 +467,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
   else:
     freeOsChunks(a, c, c.size)
 
-proc splitChunk(a: var TMemRegion, c: PBigChunk, size: int) = 
+proc splitChunk(a: var TMemRegion, c: PBigChunk, size: int) =
   var rest = cast[PBigChunk](cast[ByteAddress](c) +% size)
   sysAssert(rest notin a.freeChunksList, "splitChunk")
   rest.size = c.size - size
@@ -480,7 +480,7 @@ proc splitChunk(a: var TMemRegion, c: PBigChunk, size: int) =
   incl(a, a.chunkStarts, pageIndex(rest))
   listAdd(a.freeChunksList, rest)
 
-proc getBigChunk(a: var TMemRegion, size: int): PBigChunk = 
+proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
   # use first fit for now:
   sysAssert((size and PageMask) == 0, "getBigChunk 1")
   sysAssert(size > 0, "getBigChunk 2")
@@ -488,7 +488,7 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
   block search:
     while result != nil:
       sysAssert chunkUnused(result), "getBigChunk 3"
-      if result.size == size: 
+      if result.size == size:
         listRemove(a.freeChunksList, result)
         break search
       elif result.size > size:
@@ -497,7 +497,7 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
         break search
       result = result.next
       sysAssert result != a.freeChunksList, "getBigChunk 4"
-    if size < InitialMemoryRequest: 
+    if size < InitialMemoryRequest:
       result = requestOsChunks(a, InitialMemoryRequest)
       splitChunk(a, result, size)
     else:
@@ -507,7 +507,7 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
   incl(a, a.chunkStarts, pageIndex(result))
   dec(a.freeMem, size)
 
-proc getSmallChunk(a: var TMemRegion): PSmallChunk = 
+proc getSmallChunk(a: var TMemRegion): PSmallChunk =
   var res = getBigChunk(a, PageSize)
   sysAssert res.prev == nil, "getSmallChunk 1"
   sysAssert res.next == nil, "getSmallChunk 2"
@@ -521,15 +521,15 @@ proc allocInv(a: TMemRegion): bool =
   for s in low(a.freeSmallChunks)..high(a.freeSmallChunks):
     var c = a.freeSmallChunks[s]
     while c != nil:
-      if c.next == c: 
+      if c.next == c:
         echo "[SYSASSERT] c.next == c"
         return false
-      if c.size != s * MemAlign: 
+      if c.size != s * MemAlign:
         echo "[SYSASSERT] c.size != s * MemAlign"
         return false
       var it = c.freeList
       while it != nil:
-        if it.zeroField != 0: 
+        if it.zeroField != 0:
           echo "[SYSASSERT] it.zeroField != 0"
           c_printf("%ld %p\n", it.zeroField, it)
           return false
@@ -539,16 +539,16 @@ proc allocInv(a: TMemRegion): bool =
 
 proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
   sysAssert(allocInv(a), "rawAlloc: begin")
-  sysAssert(roundup(65, 8) == 72, "rawAlloc 1")
-  sysAssert requestedSize >= sizeof(TFreeCell), "rawAlloc 2"
+  sysAssert(roundup(65, 8) == 72, "rawAlloc: roundup broken")
+  sysAssert(requestedSize >= sizeof(TFreeCell), "rawAlloc: requested size too small")
   var size = roundup(requestedSize, MemAlign)
   sysAssert(size >= requestedSize, "insufficient allocated size!")
   #c_fprintf(c_stdout, "alloc; size: %ld; %ld\n", requestedSize, size)
-  if size <= SmallChunkSize-smallChunkOverhead(): 
+  if size <= SmallChunkSize-smallChunkOverhead():
     # allocate a small block: for small chunks, we use only its next pointer
     var s = size div MemAlign
     var c = a.freeSmallChunks[s]
-    if c == nil: 
+    if c == nil:
       c = getSmallChunk(a)
       c.freeList = nil
       sysAssert c.size == PageSize, "rawAlloc 3"
@@ -567,7 +567,7 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
       #  c_fprintf(c_stdout, "csize: %lld; size %lld\n", c.size, size)
       sysAssert c.size == size, "rawAlloc 6"
       if c.freeList == nil:
-        sysAssert(c.acc + smallChunkOverhead() + size <= SmallChunkSize, 
+        sysAssert(c.acc + smallChunkOverhead() + size <= SmallChunkSize,
                   "rawAlloc 7")
         result = cast[pointer](cast[ByteAddress](addr(c.data)) +% c.acc)
         inc(c.acc, size)
@@ -621,9 +621,9 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
     f.zeroField = 0
     f.next = c.freeList
     c.freeList = f
-    when overwriteFree: 
+    when overwriteFree:
       # set to 0xff to check for usage after free bugs:
-      c_memset(cast[pointer](cast[int](p) +% sizeof(TFreeCell)), -1'i32, 
+      c_memset(cast[pointer](cast[int](p) +% sizeof(TFreeCell)), -1'i32,
                s -% sizeof(TFreeCell))
     # check if it is not in the freeSmallChunks[s] list:
     if c.free < s:
@@ -649,13 +649,13 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
   sysAssert(allocInv(a), "rawDealloc: end")
   when logAlloc: cprintf("rawDealloc: %p\n", p)
 
-proc isAllocatedPtr(a: TMemRegion, p: pointer): bool = 
+proc isAllocatedPtr(a: TMemRegion, p: pointer): bool =
   if isAccessible(a, p):
     var c = pageAddr(p)
     if not chunkUnused(c):
       if isSmallChunk(c):
         var c = cast[PSmallChunk](c)
-        var offset = (cast[ByteAddress](p) and (PageSize-1)) -% 
+        var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
                      smallChunkOverhead()
         result = (c.acc >% offset) and (offset %% c.size == 0) and
           (cast[ptr TFreeCell](p).zeroField >% 1)
@@ -673,12 +673,12 @@ proc interiorAllocatedPtr(a: TMemRegion, p: pointer): pointer =
     if not chunkUnused(c):
       if isSmallChunk(c):
         var c = cast[PSmallChunk](c)
-        var offset = (cast[ByteAddress](p) and (PageSize-1)) -% 
+        var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
                      smallChunkOverhead()
         if c.acc >% offset:
           sysAssert(cast[ByteAddress](addr(c.data)) +% offset ==
                     cast[ByteAddress](p), "offset is not what you think it is")
-          var d = cast[ptr TFreeCell](cast[ByteAddress](addr(c.data)) +% 
+          var d = cast[ptr TFreeCell](cast[ByteAddress](addr(c.data)) +%
                     offset -% (offset %% c.size))
           if d.zeroField >% 1:
             result = d
@@ -711,13 +711,13 @@ proc ptrSize(p: pointer): int =
   if not isSmallChunk(c):
     dec result, bigChunkOverhead()
 
-proc alloc(allocator: var TMemRegion, size: int): pointer =
+proc alloc(allocator: var TMemRegion, size: Natural): pointer =
   result = rawAlloc(allocator, size+sizeof(TFreeCell))
   cast[ptr TFreeCell](result).zeroField = 1 # mark it as used
   sysAssert(not isAllocatedPtr(allocator, result), "alloc")
   result = cast[pointer](cast[ByteAddress](result) +% sizeof(TFreeCell))
 
-proc alloc0(allocator: var TMemRegion, size: int): pointer =
+proc alloc0(allocator: var TMemRegion, size: Natural): pointer =
   result = alloc(allocator, size)
   zeroMem(result, size)
 
@@ -730,7 +730,7 @@ proc dealloc(allocator: var TMemRegion, p: pointer) =
   rawDealloc(allocator, x)
   sysAssert(not isAllocatedPtr(allocator, x), "dealloc 3")
 
-proc realloc(allocator: var TMemRegion, p: pointer, newsize: int): pointer =
+proc realloc(allocator: var TMemRegion, p: pointer, newsize: Natural): pointer =
   if newsize > 0:
     result = alloc0(allocator, newsize)
     if p != nil:
@@ -758,7 +758,7 @@ proc deallocOsPages(a: var TMemRegion) =
 
 proc getFreeMem(a: TMemRegion): int {.inline.} = result = a.freeMem
 proc getTotalMem(a: TMemRegion): int {.inline.} = result = a.currMem
-proc getOccupiedMem(a: TMemRegion): int {.inline.} = 
+proc getOccupiedMem(a: TMemRegion): int {.inline.} =
   result = a.currMem - a.freeMem
 
 # ---------------------- thread memory region -------------------------------
@@ -774,16 +774,16 @@ template instantiateForRegion(allocator: expr) =
 
   proc deallocOsPages = deallocOsPages(allocator)
 
-  proc alloc(size: int): pointer =
+  proc alloc(size: Natural): pointer =
     result = alloc(allocator, size)
 
-  proc alloc0(size: int): pointer =
+  proc alloc0(size: Natural): pointer =
     result = alloc0(allocator, size)
 
   proc dealloc(p: pointer) =
     dealloc(allocator, p)
 
-  proc realloc(p: pointer, newsize: int): pointer =
+  proc realloc(p: pointer, newsize: Natural): pointer =
     result = realloc(allocator, p, newSize)
 
   when false:
@@ -794,7 +794,7 @@ template instantiateForRegion(allocator: expr) =
         inc(result, it.size)
         it = it.next
 
-  proc getFreeMem(): int = 
+  proc getFreeMem(): int =
     result = allocator.freeMem
     #sysAssert(result == countFreeMem())
 
@@ -807,7 +807,7 @@ template instantiateForRegion(allocator: expr) =
     var heapLock: TSysLock
     initSysLock(heapLock)
 
-  proc allocShared(size: int): pointer =
+  proc allocShared(size: Natural): pointer =
     when hasThreadSupport:
       acquireSys(heapLock)
       result = alloc(sharedHeap, size)
@@ -815,20 +815,20 @@ template instantiateForRegion(allocator: expr) =
     else:
       result = alloc(size)
 
-  proc allocShared0(size: int): pointer =
+  proc allocShared0(size: Natural): pointer =
     result = allocShared(size)
     zeroMem(result, size)
 
   proc deallocShared(p: pointer) =
-    when hasThreadSupport: 
+    when hasThreadSupport:
       acquireSys(heapLock)
       dealloc(sharedHeap, p)
       releaseSys(heapLock)
     else:
       dealloc(p)
 
-  proc reallocShared(p: pointer, newsize: int): pointer =
-    when hasThreadSupport: 
+  proc reallocShared(p: pointer, newsize: Natural): pointer =
+    when hasThreadSupport:
       acquireSys(heapLock)
       result = realloc(sharedHeap, p, newsize)
       releaseSys(heapLock)
diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim
index c4df287cf..f68e2dcd9 100644
--- a/lib/system/arithm.nim
+++ b/lib/system/arithm.nim
@@ -15,7 +15,7 @@ proc raiseOverflow {.compilerproc, noinline, noreturn.} =
   sysFatal(OverflowError, "over- or underflow")
 
 proc raiseDivByZero {.compilerproc, noinline, noreturn.} =
-  sysFatal(DivByZeroError, "divison by zero")
+  sysFatal(DivByZeroError, "division by zero")
 
 proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
   result = a +% b
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index 429a92d34..78995954f 100644
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -27,7 +27,7 @@ proc genericAssignAux(dest, src: pointer, n: ptr TNimNode,
     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: 
+    if m != dd and dd != nil:
       genericResetAux(dest, dd)
     copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
             n.typ.size)
@@ -205,9 +205,13 @@ proc genericReset(dest: pointer, mt: PNimType) =
   case mt.kind
   of tyString, tyRef, tySequence:
     unsureAsgnRef(cast[PPointer](dest), nil)
-  of tyObject, tyTuple:
-    # we don't need to reset m_type field for tyObject
+  of tyTuple:
+    genericResetAux(dest, mt.node)
+  of tyObject:
     genericResetAux(dest, mt.node)
+    # also reset the type field for tyObject, for correct branch switching!
+    var pint = cast[ptr PNimType](dest)
+    pint[] = nil
   of tyArray, tyArrayConstr:
     for i in 0..(mt.size div mt.base.size)-1:
       genericReset(cast[pointer](d +% i*% mt.base.size), mt.base)
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index f816c8201..c97d2fc7f 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -21,19 +21,19 @@ when someGcc and hasThreadSupport:
     ## synchronization with another thread.
   var ATOMIC_ACQUIRE* {.importc: "__ATOMIC_ACQUIRE", nodecl.}: AtomMemModel
     ## Barrier to hoisting of code and synchronizes with
-    ## release (or stronger) 
+    ## 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. 
+    ## 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 
+    ## 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 
+    ## with acquire loads
     ## and release stores in all threads.
 
   type
@@ -46,11 +46,11 @@ when someGcc and hasThreadSupport:
     ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_CONSUME.
 
   proc atomicLoad*[T: TAtomType](p, ret: ptr T, mem: AtomMemModel) {.
-    importc: "__atomic_load", nodecl.}  
+    importc: "__atomic_load", nodecl.}
     ## This is the generic version of an atomic load. It returns the contents at p in ret.
 
   proc atomicStoreN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel) {.
-    importc: "__atomic_store_n", nodecl.} 
+    importc: "__atomic_store_n", nodecl.}
     ## This proc implements an atomic store operation. It writes val at p.
     ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, and ATOMIC_RELEASE.
 
@@ -60,39 +60,39 @@ when someGcc and hasThreadSupport:
 
   proc atomicExchangeN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_exchange_n", nodecl.}
-    ## This proc implements an atomic exchange operation. It writes val at p, 
+    ## This proc implements an atomic exchange operation. It writes val at p,
     ## and returns the previous contents at p.
     ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_RELEASE, ATOMIC_ACQ_REL
 
   proc atomicExchange*[T: TAtomType](p, val, ret: ptr T, mem: AtomMemModel) {.
     importc: "__atomic_exchange", nodecl.}
-    ## This is the generic version of an atomic exchange. It stores the contents at val at p. 
+    ## This is the generic version of an atomic exchange. It stores the contents at val at p.
     ## The original value at p is copied into ret.
 
   proc atomicCompareExchangeN*[T: TAtomType](p, expected: ptr T, desired: T,
     weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
-    importc: "__atomic_compare_exchange_n ", nodecl.} 
+    importc: "__atomic_compare_exchange_n ", nodecl.}
     ## This proc implements an atomic compare and exchange operation. This compares the
-    ## contents at p with the contents at expected and if equal, writes desired at p. 
-    ## If they are not equal, the current contents at p is written into expected. 
-    ## Weak is true for weak compare_exchange, and false for the strong variation. 
-    ## Many targets only offer the strong variation and ignore the parameter. 
+    ## contents at p with the contents at expected and if equal, writes desired at p.
+    ## If they are not equal, the current contents at p is written into expected.
+    ## Weak is true for weak compare_exchange, and false for the strong variation.
+    ## Many targets only offer the strong variation and ignore the parameter.
     ## When in doubt, use the strong variation.
-    ## True is returned if desired is written at p and the execution is considered 
-    ## to conform to the memory model specified by success_memmodel. There are no 
-    ## restrictions on what memory model can be used here. False is returned otherwise, 
-    ## and the execution is considered to conform to failure_memmodel. This memory model 
-    ## cannot be __ATOMIC_RELEASE nor __ATOMIC_ACQ_REL. It also cannot be a stronger model 
+    ## True is returned if desired is written at p and the execution is considered
+    ## to conform to the memory model specified by success_memmodel. There are no
+    ## restrictions on what memory model can be used here. False is returned otherwise,
+    ## and the execution is considered to conform to failure_memmodel. This memory model
+    ## cannot be __ATOMIC_RELEASE nor __ATOMIC_ACQ_REL. It also cannot be a stronger model
     ## than that specified by success_memmodel.
 
   proc atomicCompareExchange*[T: TAtomType](p, expected, desired: ptr T,
     weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
-    importc: "__atomic_compare_exchange_n ", nodecl.}  
-    ## This proc implements the generic version of atomic_compare_exchange. 
-    ## The proc is virtually identical to atomic_compare_exchange_n, except the desired 
-    ## value is also a pointer. 
+    importc: "__atomic_compare_exchange", nodecl.}
+    ## This proc implements the generic version of atomic_compare_exchange.
+    ## The proc is virtually identical to atomic_compare_exchange_n, except the desired
+    ## value is also a pointer.
 
-  ## Perform the operation return the new value, all memory models are valid 
+  ## Perform the operation return the new value, all memory models are valid
   proc atomicAddFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_add_fetch", nodecl.}
   proc atomicSubFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
@@ -101,64 +101,64 @@ when someGcc and hasThreadSupport:
     importc: "__atomic_or_fetch ", nodecl.}
   proc atomicAndFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_and_fetch", nodecl.}
-  proc atomicXorFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.   
+  proc atomicXorFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_xor_fetch", nodecl.}
-  proc atomicNandFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.   
-    importc: "__atomic_nand_fetch ", nodecl.} 
+  proc atomicNandFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+    importc: "__atomic_nand_fetch ", nodecl.}
 
-  ## Perform the operation return the old value, all memory models are valid 
+  ## Perform the operation return the old value, all memory models are valid
   proc atomicFetchAdd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_add", nodecl.}
-  proc atomicFetchSub*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.  
+  proc atomicFetchSub*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_sub", nodecl.}
-  proc atomicFetchOr*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.  
+  proc atomicFetchOr*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_or", nodecl.}
-  proc atomicFetchAnd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.   
+  proc atomicFetchAnd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_and", nodecl.}
-  proc atomicFetchXor*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.  
+  proc atomicFetchXor*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_xor", nodecl.}
-  proc atomicFetchNand*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.  
-    importc: "__atomic_fetch_nand", nodecl.} 
+  proc atomicFetchNand*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+    importc: "__atomic_fetch_nand", nodecl.}
 
-  proc atomicTestAndSet*(p: pointer, mem: AtomMemModel): bool {.  
-    importc: "__atomic_test_and_set", nodecl.} 
-    ## This built-in function performs an atomic test-and-set operation on the byte at p. 
+  proc atomicTestAndSet*(p: pointer, mem: AtomMemModel): bool {.
+    importc: "__atomic_test_and_set", nodecl.}
+    ## This built-in function performs an atomic test-and-set operation on the byte at p.
     ## The byte is set to some implementation defined nonzero “set” value and the return
     ## value is true if and only if the previous contents were “set”.
     ## All memory models are valid.
 
-  proc atomicClear*(p: pointer, mem: AtomMemModel) {.  
+  proc atomicClear*(p: pointer, mem: AtomMemModel) {.
     importc: "__atomic_clear", nodecl.}
-    ## This built-in function performs an atomic clear operation at p. 
+    ## This built-in function performs an atomic clear operation at p.
     ## After the operation, at p contains 0.
     ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_RELEASE
 
-  proc atomicThreadFence*(mem: AtomMemModel) {.  
+  proc atomicThreadFence*(mem: AtomMemModel) {.
     importc: "__atomic_thread_fence", nodecl.}
-    ## This built-in function acts as a synchronization fence between threads based 
+    ## This built-in function acts as a synchronization fence between threads based
     ## on the specified memory model. All memory orders are valid.
 
-  proc atomicSignalFence*(mem: AtomMemModel) {.  
+  proc atomicSignalFence*(mem: AtomMemModel) {.
     importc: "__atomic_signal_fence", nodecl.}
-    ## This built-in function acts as a synchronization fence between a thread and 
+    ## This built-in function acts as a synchronization fence between a thread and
     ## signal handlers based in the same thread. All memory orders are valid.
 
-  proc atomicAlwaysLockFree*(size: int, p: pointer): bool {.  
+  proc atomicAlwaysLockFree*(size: int, p: pointer): bool {.
     importc: "__atomic_always_lock_free", nodecl.}
-    ## This built-in function returns true if objects of size bytes always generate 
-    ## lock free atomic instructions for the target architecture. size must resolve 
+    ## This built-in function returns true if objects of size bytes always generate
+    ## lock free atomic instructions for the target architecture. size must resolve
     ## to a compile-time constant and the result also resolves to a compile-time constant.
-    ## ptr is an optional pointer to the object that may be used to determine alignment. 
-    ## A value of 0 indicates typical alignment should be used. The compiler may also 
+    ## ptr is an optional pointer to the object that may be used to determine alignment.
+    ## A value of 0 indicates typical alignment should be used. The compiler may also
     ## ignore this parameter.
 
-  proc atomicIsLockFree*(size: int, p: pointer): bool {.  
+  proc atomicIsLockFree*(size: int, p: pointer): bool {.
     importc: "__atomic_is_lock_free", nodecl.}
-    ## This built-in function returns true if objects of size bytes always generate 
-    ## lock free atomic instructions for the target architecture. If it is not known 
+    ## This built-in function returns true if objects of size bytes always generate
+    ## lock free atomic instructions for the target architecture. If it is not known
     ## to be lock free a call is made to a runtime routine named __atomic_is_lock_free.
-    ## ptr is an optional pointer to the object that may be used to determine alignment. 
-    ## A value of 0 indicates typical alignment should be used. The compiler may also 
+    ## ptr is an optional pointer to the object that may be used to determine alignment.
+    ## A value of 0 indicates typical alignment should be used. The compiler may also
     ## ignore this parameter.
 
   template fence*() = atomicThreadFence(ATOMIC_SEQ_CST)
@@ -178,7 +178,7 @@ proc atomicInc*(memLoc: var int, x: int = 1): int =
   else:
     inc(memLoc, x)
     result = memLoc
-  
+
 proc atomicDec*(memLoc: var int, x: int = 1): int =
   when someGcc and hasThreadSupport:
     when declared(atomic_sub_fetch):
@@ -206,6 +206,9 @@ else:
 when (defined(x86) or defined(amd64)) and someGcc:
   proc cpuRelax* {.inline.} =
     {.emit: """asm volatile("pause" ::: "memory");""".}
+elif someGcc:
+  proc cpuRelax* {.inline.} =
+    {.emit: """asm volatile("" ::: "memory");""".}
 elif (defined(x86) or defined(amd64)) and defined(vcc):
   proc cpuRelax* {.importc: "YieldProcessor", header: "<windows.h>".}
 elif defined(icl):
diff --git a/lib/system/cgprocs.nim b/lib/system/cgprocs.nim
index 089846578..f3acc81f2 100644
--- a/lib/system/cgprocs.nim
+++ b/lib/system/cgprocs.nim
@@ -13,7 +13,7 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.}
 
 type
   TLibHandle = pointer       # private type
-  TProcAddr = pointer        # libary loading and loading of procs:
+  TProcAddr = pointer        # library loading and loading of procs:
 
 proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.}
 proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index 3e5ca0795..ebd30c353 100644
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -1,7 +1,7 @@
 #

 #

 #            Nim's Runtime Library

-#        (c) Copyright 2014 Andreas Rumpf

+#        (c) Copyright 2015 Andreas Rumpf
 #

 #    See the file "copying.txt", included in this

 #    distribution, for details about the copyright.

@@ -232,9 +232,10 @@ proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,
   ## it returns ``(false, default(msg))``.

   var q = cast[PRawChannel](addr(c))

   if q.mask != ChannelDeadMask:

-    if tryAcquireSys(q.lock):

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

-      result.dataAvailable = true

+    if tryAcquireSys(q.lock):
+      if q.count > 0:

+        llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))

+        result.dataAvailable = true

       releaseSys(q.lock)

 

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

diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim
index 5c32a307a..2f6d25a12 100644
--- a/lib/system/chcks.nim
+++ b/lib/system/chcks.nim
@@ -11,7 +11,7 @@
 
 proc raiseRangeError(val: BiggestInt) {.compilerproc, noreturn, noinline.} =
   when hostOS == "standalone":
-    sysFatal(EOutOfRange, "value out of range")
+    sysFatal(RangeError, "value out of range")
   else:
     sysFatal(RangeError, "value out of range: ", $val)
 
@@ -44,7 +44,7 @@ proc chckRangeF(x, a, b: float): float =
     return x
   else:
     when hostOS == "standalone":
-      sysFatal(EOutOfRange, "value out of range")
+      sysFatal(RangeError, "value out of range")
     else:
       sysFatal(RangeError, "value out of range: ", $x)
 
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
index fbebb17a8..093c0f3a7 100644
--- a/lib/system/deepcopy.nim
+++ b/lib/system/deepcopy.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -34,9 +34,9 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.benign.} =
 
 proc copyDeepString(src: NimString): NimString {.inline.} =
   if src != nil:
-    result = rawNewString(src.space)
+    result = rawNewStringNoInit(src.len)
     result.len = src.len
-    c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
+    c_memcpy(result.data, src.data, src.len + 1)
 
 proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
   var
diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim
index e0d99cf88..44f7b67c3 100644
--- a/lib/system/dyncalls.nim
+++ b/lib/system/dyncalls.nim
@@ -8,7 +8,7 @@
 #
 
 # This file implements the ability to call native procs from libraries.
-# It is not possible to do this in a platform independant way, unfortunately.
+# It is not possible to do this in a platform independent way, unfortunately.
 # However, the interface has been designed to take platform differences into
 # account and been ported to all major platforms.
 
@@ -80,15 +80,22 @@ elif defined(windows) or defined(dos):
   # Native Windows Implementation
   # =======================================================================
   #
-  type
-    THINSTANCE {.importc: "HINSTANCE".} = pointer
+  when defined(cpp):
+    type
+      THINSTANCE {.importc: "HINSTANCE".} = object
+        x: pointer
+    proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
+        importcpp: "(void*)GetProcAddress(@)", header: "<windows.h>", stdcall.}
+  else:
+    type
+      THINSTANCE {.importc: "HINSTANCE".} = pointer
+    proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
+        importc: "GetProcAddress", header: "<windows.h>", stdcall.}
 
   proc freeLibrary(lib: THINSTANCE) {.
       importc: "FreeLibrary", header: "<windows.h>", stdcall.}
   proc winLoadLibrary(path: cstring): THINSTANCE {.
       importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
-  proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
-      importc: "GetProcAddress", header: "<windows.h>", stdcall.}
 
   proc nimUnloadLibrary(lib: TLibHandle) =
     freeLibrary(cast[THINSTANCE](lib))
diff --git a/lib/system/embedded.nim b/lib/system/embedded.nim
index 9bb25b8dd..a14f43e7e 100644
--- a/lib/system/embedded.nim
+++ b/lib/system/embedded.nim
@@ -33,11 +33,11 @@ proc quitOrDebug() {.inline.} =
   quit(1)
 
 proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
-  sysFatal(ENoExceptionToReraise, "exception handling is not available")
+  sysFatal(ReraiseError, "exception handling is not available")
 
 proc reraiseException() {.compilerRtl.} =
-  sysFatal(ENoExceptionToReraise, "no exception to reraise")
+  sysFatal(ReraiseError, "no exception to reraise")
 
 proc writeStackTrace() = discard
 
-proc setControlCHook(hook: proc () {.noconv.}) = discard
+proc setControlCHook(hook: proc () {.noconv.} not nil) = discard
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 237b42482..189d52f57 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -58,7 +58,7 @@ proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
 proc popSafePoint {.compilerRtl, inl.} =
   excHandler = excHandler.prev
 
-proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} = 
+proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} =
   e.parent = currException
   currException = e
 
@@ -69,12 +69,12 @@ proc popCurrentException {.compilerRtl, inl.} =
 const
   nativeStackTraceSupported* = (defined(macosx) or defined(linux)) and
                               not NimStackTrace
-  hasSomeStackTrace = NimStackTrace or 
+  hasSomeStackTrace = NimStackTrace or
     defined(nativeStackTrace) and nativeStackTraceSupported
 
 when defined(nativeStacktrace) and nativeStackTraceSupported:
   type
-    TDl_info {.importc: "Dl_info", header: "<dlfcn.h>", 
+    TDl_info {.importc: "Dl_info", header: "<dlfcn.h>",
                final, pure.} = object
       dli_fname: cstring
       dli_fbase: pointer
@@ -98,7 +98,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
         tempDlInfo: TDl_info
     # This is allowed to be expensive since it only happens during crashes
     # (but this way you don't need manual stack tracing)
-    var size = backtrace(cast[ptr pointer](addr(tempAddresses)), 
+    var size = backtrace(cast[ptr pointer](addr(tempAddresses)),
                          len(tempAddresses))
     var enabled = false
     for i in 0..size-1:
@@ -123,7 +123,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
 when not hasThreadSupport:
   var
     tempFrames: array [0..127, PFrame] # should not be alloc'd on stack
-  
+
 proc auxWriteStackTrace(f: PFrame, s: var string) =
   when hasThreadSupport:
     var
@@ -160,7 +160,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
     inc(i)
     b = b.prev
   for j in countdown(i-1, 0):
-    if tempFrames[j] == nil: 
+    if tempFrames[j] == nil:
       add(s, "(")
       add(s, $skipped)
       add(s, " calls omitted) ...")
@@ -175,6 +175,8 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
       add(s, tempFrames[j].procname)
     add(s, "\n")
 
+proc stackTraceAvailable*(): bool
+
 when hasSomeStackTrace:
   proc rawWriteStackTrace(s: var string) =
     when NimStackTrace:
@@ -188,6 +190,18 @@ when hasSomeStackTrace:
       auxWriteStackTraceWithBacktrace(s)
     else:
       add(s, "No stack traceback available\n")
+  proc stackTraceAvailable(): bool =
+    when NimStackTrace:
+      if framePtr == nil:
+        result = false
+      else:
+        result = true
+    elif defined(nativeStackTrace) and nativeStackTraceSupported:
+      result = true
+    else:
+      result = false
+else:
+  proc stackTraceAvailable*(): bool = result = false
 
 proc quitOrDebug() {.inline.} =
   when not defined(endb):
@@ -200,41 +214,49 @@ proc raiseExceptionAux(e: ref Exception) =
     if not localRaiseHook(e): return
   if globalRaiseHook != nil:
     if not globalRaiseHook(e): return
-  if excHandler != nil:
-    if not excHandler.hasRaiseAction or excHandler.raiseAction(e):
+  when defined(cpp):
+    if e[] of OutOfMemError:
+      showErrorMessage(e.name)
+      quitOrDebug()
+    else:
       pushCurrentException(e)
-      c_longjmp(excHandler.context, 1)
-  elif e[] of OutOfMemError:
-    showErrorMessage(e.name)
-    quitOrDebug()
+      {.emit: "throw NimException(`e`, `e`->name);".}
   else:
-    when hasSomeStackTrace:
-      var buf = newStringOfCap(2000)
-      if isNil(e.trace): rawWriteStackTrace(buf)
-      else: add(buf, e.trace)
-      add(buf, "Error: unhandled exception: ")
-      if not isNil(e.msg): add(buf, e.msg)
-      add(buf, " [")
-      add(buf, $e.name)
-      add(buf, "]\n")
-      showErrorMessage(buf)
+    if excHandler != nil:
+      if not excHandler.hasRaiseAction or excHandler.raiseAction(e):
+        pushCurrentException(e)
+        c_longjmp(excHandler.context, 1)
+    elif e[] of OutOfMemError:
+      showErrorMessage(e.name)
+      quitOrDebug()
     else:
-      # ugly, but avoids heap allocations :-)
-      template xadd(buf, s, slen: expr) =
-        if L + slen < high(buf):
-          copyMem(addr(buf[L]), cstring(s), slen)
-          inc L, slen
-      template add(buf, s: expr) =
-        xadd(buf, s, s.len)
-      var buf: array [0..2000, char]
-      var L = 0
-      add(buf, "Error: unhandled exception: ")
-      if not isNil(e.msg): add(buf, e.msg)
-      add(buf, " [")
-      xadd(buf, e.name, c_strlen(e.name))
-      add(buf, "]\n")
-      showErrorMessage(buf)
-    quitOrDebug()
+      when hasSomeStackTrace:
+        var buf = newStringOfCap(2000)
+        if isNil(e.trace): rawWriteStackTrace(buf)
+        else: add(buf, e.trace)
+        add(buf, "Error: unhandled exception: ")
+        if not isNil(e.msg): add(buf, e.msg)
+        add(buf, " [")
+        add(buf, $e.name)
+        add(buf, "]\n")
+        showErrorMessage(buf)
+      else:
+        # ugly, but avoids heap allocations :-)
+        template xadd(buf, s, slen: expr) =
+          if L + slen < high(buf):
+            copyMem(addr(buf[L]), cstring(s), slen)
+            inc L, slen
+        template add(buf, s: expr) =
+          xadd(buf, s, s.len)
+        var buf: array [0..2000, char]
+        var L = 0
+        add(buf, "Error: unhandled exception: ")
+        if not isNil(e.msg): add(buf, e.msg)
+        add(buf, " [")
+        xadd(buf, e.name, c_strlen(e.name))
+        add(buf, "]\n")
+        showErrorMessage(buf)
+      quitOrDebug()
 
 proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
   e.name = ename
@@ -295,8 +317,8 @@ when not defined(noSignalHandler):
   proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
     template processSignal(s, action: expr) {.immediate,  dirty.} =
       if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
-      elif s == SIGSEGV: 
-        action("SIGSEGV: Illegal storage access. (Try to compile with -d:useSysAssert -d:useGcAssert for details.)\n")
+      elif s == SIGSEGV:
+        action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
       elif s == SIGABRT:
         when defined(endb):
           if dbgAborting: return # the debugger wants to abort
@@ -304,7 +326,7 @@ when not defined(noSignalHandler):
       elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n")
       elif s == SIGILL: action("SIGILL: Illegal operation.\n")
       elif s == SIGBUS:
-        action("SIGBUS: Illegal storage access.  (Try to compile with -d:useSysAssert -d:useGcAssert for details.)\n")
+        action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
       else:
         block platformSpecificSignal:
           when declared(SIGPIPE):
@@ -341,7 +363,7 @@ when not defined(noSignalHandler):
 
   registerSignalHandler() # call it in initialization section
 
-proc setControlCHook(hook: proc () {.noconv.}) =
+proc setControlCHook(hook: proc () {.noconv.} not nil) =
   # ugly cast, but should work on all architectures:
   type TSignalHandler = proc (sig: cint) {.noconv, benign.}
   c_signal(SIGINT, cast[TSignalHandler](hook))
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index e0db3fba4..c4374d00c 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -33,7 +33,7 @@ const
 when withRealTime and not declared(getTicks):
   include "system/timers"
 when defined(memProfiler):
-  proc nimProfile(requestedSize: int)
+  proc nimProfile(requestedSize: int) {.benign.}
 
 const
   rcIncrement = 0b1000 # so that lowest 3 bits are not touched
@@ -48,8 +48,8 @@ type
   TWalkOp = enum
     waMarkGlobal,    # part of the backup/debug mark&sweep
     waMarkPrecise,   # part of the backup/debug mark&sweep
-    waZctDecRef, waPush, waCycleDecRef, waMarkGray, waScan, waScanBlack, 
-    waCollectWhite,
+    waZctDecRef, waPush, waCycleDecRef, waMarkGray, waScan, waScanBlack,
+    waCollectWhite #, waDebug
 
   TFinalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
     # A ref type can have a finalizer that is called before the object's
@@ -61,9 +61,9 @@ type
     maxThreshold: int        # max threshold that has been set
     maxStackSize: int        # max stack size
     maxStackCells: int       # max stack cells in ``decStack``
-    cycleTableSize: int      # max entries in cycle table  
+    cycleTableSize: int      # max entries in cycle table
     maxPause: int64          # max measured GC pause in nanoseconds
-  
+
   TGcHeap {.final, pure.} = object # this contains the zero count and
                                    # non-zero count table
     stackBottom: pointer
@@ -88,11 +88,11 @@ var
 when not defined(useNimRtl):
   instantiateForRegion(gch.region)
 
-template acquire(gch: TGcHeap) = 
+template acquire(gch: TGcHeap) =
   when hasThreadSupport and hasSharedHeap:
     acquireSys(HeapLock)
 
-template release(gch: TGcHeap) = 
+template release(gch: TGcHeap) =
   when hasThreadSupport and hasSharedHeap:
     releaseSys(HeapLock)
 
@@ -117,7 +117,7 @@ proc usrToCell(usr: pointer): PCell {.inline.} =
   # convert pointer to userdata to object (=pointer to refcount)
   result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(TCell)))
 
-proc canbeCycleRoot(c: PCell): bool {.inline.} =
+proc canBeCycleRoot(c: PCell): bool {.inline.} =
   result = ntfAcyclic notin c.typ.flags
 
 proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
@@ -163,7 +163,7 @@ when hasThreadSupport and hasSharedHeap:
   template `--`(x: expr): expr = atomicDec(x, rcIncrement) <% rcIncrement
   template `++`(x: expr): stmt = discard atomicInc(x, rcIncrement)
 else:
-  template `--`(x: expr): expr = 
+  template `--`(x: expr): expr =
     dec(x, rcIncrement)
     x <% rcIncrement
   template `++`(x: expr): stmt = inc(x, rcIncrement)
@@ -181,7 +181,7 @@ proc prepareDealloc(cell: PCell) =
     (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
     dec(gch.recGcLock)
 
-proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = 
+proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} =
   # we MUST access gch as a global here, because this crosses DLL boundaries!
   when hasThreadSupport and hasSharedHeap:
     acquireSys(HeapLock)
@@ -211,7 +211,7 @@ proc decRef(c: PCell) {.inline.} =
     rtlAddCycleRoot(c)
     #writeCell("decRef", c)
 
-proc incRef(c: PCell) {.inline.} = 
+proc incRef(c: PCell) {.inline.} =
   gcAssert(isAllocatedPtr(gch.region, c), "incRef: interiorPtr")
   c.refcount = c.refcount +% rcIncrement
   # and not colorMask
@@ -246,12 +246,12 @@ proc asgnRef(dest: PPointer, src: pointer) {.compilerProc, inline.} =
   dest[] = src
 
 proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerProc, inline.} =
-  # the code generator calls this proc if it is known at compile time that no 
+  # the code generator calls this proc if it is known at compile time that no
   # cycle is possible.
   if src != nil:
     var c = usrToCell(src)
     ++c.refcount
-  if dest[] != nil: 
+  if dest[] != nil:
     var c = usrToCell(dest[])
     if --c.refcount:
       rtlAddZCT(c)
@@ -269,7 +269,7 @@ proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerProc.} =
     if cast[int](dest[]) >=% PageSize: decRef(usrToCell(dest[]))
   else:
     # can't be an interior pointer if it's a stack location!
-    gcAssert(interiorAllocatedPtr(gch.region, dest) == nil, 
+    gcAssert(interiorAllocatedPtr(gch.region, dest) == nil,
              "stack loc AND interior pointer")
   dest[] = src
 
@@ -321,7 +321,7 @@ when useMarkForDebug or useBackupGc:
       echo "[GC] cannot register global variable; too many global variables"
       quit 1
 
-proc cellsetReset(s: var TCellSet) = 
+proc cellsetReset(s: var TCellSet) =
   deinit(s)
   init(s)
 
@@ -336,7 +336,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.benign.} =
         if n.sons[i].typ.kind in {tyRef, tyString, tySequence}:
           doOperation(cast[PPointer](d +% n.sons[i].offset)[], op)
         else:
-          forAllChildrenAux(cast[pointer](d +% n.sons[i].offset), 
+          forAllChildrenAux(cast[pointer](d +% n.sons[i].offset),
                             n.sons[i].typ, op)
       else:
         forAllSlotsAux(dest, n.sons[i], op)
@@ -384,7 +384,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
   # we check the last 8 entries (cache line) for a slot that could be reused.
   # In 63% of all cases we succeed here! But we have to optimize the heck
   # out of this small linear search so that ``newObj`` is not slowed down.
-  # 
+  #
   # Slots to try          cache hit
   # 1                     32%
   # 4                     59%
@@ -461,6 +461,10 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
 
 {.pop.}
 
+proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
+  result = rawNewObj(typ, size, gch)
+  when defined(memProfiler): nimProfile(size)
+
 proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
   result = rawNewObj(typ, size, gch)
   zeroMem(result, size)
@@ -481,7 +485,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
   gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
   collectCT(gch)
   sysAssert(allocInv(gch.region), "newObjRC1 after collectCT")
-  
+
   var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
   sysAssert(allocInv(gch.region), "newObjRC1 after rawAlloc")
   sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
@@ -510,7 +514,7 @@ proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
   cast[PGenericSeq](result).len = len
   cast[PGenericSeq](result).reserved = len
   when defined(memProfiler): nimProfile(size)
-  
+
 proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
   acquire(gch)
   collectCT(gch)
@@ -522,34 +526,42 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
   var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(TCell)))
   var elemSize = 1
   if ol.typ.kind != tyString: elemSize = ol.typ.base.size
-  
+
   var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
   copyMem(res, ol, oldsize + sizeof(TCell))
   zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(TCell)),
           newsize-oldsize)
   sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
-  sysAssert(res.refcount shr rcShift <=% 1, "growObj: 4")
-  #if res.refcount <% rcIncrement:
-  #  add(gch.zct, res)
-  #else: # XXX: what to do here?
-  #  decRef(ol)
-  if (ol.refcount and ZctFlag) != 0:
-    var j = gch.zct.len-1
-    var d = gch.zct.d
-    while j >= 0: 
-      if d[j] == ol:
-        d[j] = res
-        break
-      dec(j)
-  if canbeCycleRoot(ol): excl(gch.cycleRoots, ol)
+  # This can be wrong for intermediate temps that are nevertheless on the
+  # heap because of lambda lifting:
+  #gcAssert(res.refcount shr rcShift <=% 1, "growObj: 4")
   when logGC:
     writeCell("growObj old cell", ol)
     writeCell("growObj new cell", res)
   gcTrace(ol, csZctFreed)
   gcTrace(res, csAllocated)
-  when reallyDealloc: 
+  when reallyDealloc:
     sysAssert(allocInv(gch.region), "growObj before dealloc")
-    rawDealloc(gch.region, ol)
+    if ol.refcount shr rcShift <=% 1:
+      # free immediately to save space:
+      if (ol.refcount and ZctFlag) != 0:
+        var j = gch.zct.len-1
+        var d = gch.zct.d
+        while j >= 0:
+          if d[j] == ol:
+            d[j] = res
+            break
+          dec(j)
+      if canbeCycleRoot(ol): excl(gch.cycleRoots, ol)
+      rawDealloc(gch.region, ol)
+    else:
+      # we split the old refcount in 2 parts. XXX This is still not entirely
+      # correct if the pointer that receives growObj's result is on the stack.
+      # A better fix would be to emit the location specific write barrier for
+      # 'growObj', but this is lost of more work and who knows what new problems
+      # this would create.
+      res.refcount = rcIncrement
+      decRef(ol)
   else:
     sysAssert(ol.typ != nil, "growObj: 5")
     zeroMem(ol, sizeof(TCell))
@@ -572,7 +584,7 @@ proc freeCyclicCell(gch: var TGcHeap, c: PCell) =
   prepareDealloc(c)
   gcTrace(c, csCycFreed)
   when logGC: writeCell("cycle collector dealloc cell", c)
-  when reallyDealloc: 
+  when reallyDealloc:
     sysAssert(allocInv(gch.region), "free cyclic cell")
     rawDealloc(gch.region, c)
   else:
@@ -595,9 +607,15 @@ proc scan(s: PCell) =
     else:
       s.setColor(rcWhite)
       forAllChildren(s, waScan)
-  
+
 proc collectWhite(s: PCell) =
-  if s.color == rcWhite and s notin gch.cycleRoots:
+  # This is a hacky way to deal with the following problem (bug #1796)
+  # Consider this content in cycleRoots:
+  #   x -> a; y -> a  where 'a' is an acyclic object so not included in
+  # cycleRoots itself. Then 'collectWhite' used to free 'a' twice. The
+  # 'isAllocatedPtr' check prevents this. This also means we do not need
+  # to query 's notin gch.cycleRoots' at all.
+  if isAllocatedPtr(gch.region, s) and s.color == rcWhite:
     s.setColor(rcBlack)
     forAllChildren(s, waCollectWhite)
     freeCyclicCell(gch, s)
@@ -648,6 +666,28 @@ when useMarkForDebug or useBackupGc:
       if objStart != nil:
         markS(gch, objStart)
 
+when logGC:
+  var
+    cycleCheckA: array[100, PCell]
+    cycleCheckALen = 0
+
+  proc alreadySeen(c: PCell): bool =
+    for i in 0 .. <cycleCheckALen:
+      if cycleCheckA[i] == c: return true
+    if cycleCheckALen == len(cycleCheckA):
+      gcAssert(false, "cycle detection overflow")
+      quit 1
+    cycleCheckA[cycleCheckALen] = c
+    inc cycleCheckALen
+
+  proc debugGraph(s: PCell) =
+    if alreadySeen(s):
+      writeCell("child cell (already seen) ", s)
+    else:
+      writeCell("cell {", s)
+      forAllChildren(s, waDebug)
+      c_fprintf(c_stdout, "}\n")
+
 proc doOperation(p: pointer, op: TWalkOp) =
   if p == nil: return
   var c: PCell = usrToCell(p)
@@ -690,6 +730,7 @@ proc doOperation(p: pointer, op: TWalkOp) =
   of waMarkPrecise:
     when useMarkForDebug or useBackupGc:
       add(gch.tempStack, c)
+  #of waDebug: debugGraph(c)
 
 proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} =
   doOperation(d, TWalkOp(op))
@@ -702,7 +743,6 @@ when useMarkForDebug or useBackupGc:
 
 proc collectRoots(gch: var TGcHeap) =
   for s in elements(gch.cycleRoots):
-    excl(gch.cycleRoots, s)
     collectWhite(s)
 
 proc collectCycles(gch: var TGcHeap) =
@@ -731,7 +771,7 @@ proc collectCycles(gch: var TGcHeap) =
       gcAssert isAllocatedPtr(gch.region, c), "addBackStackRoots"
       gcAssert c.refcount >=% rcIncrement, "addBackStackRoots: dead cell"
       if canBeCycleRoot(c):
-        #if c notin gch.cycleRoots: 
+        #if c notin gch.cycleRoots:
         inc cycleRootsLen
         incl(gch.cycleRoots, c)
       gcAssert c.typ != nil, "addBackStackRoots 2"
@@ -758,12 +798,12 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
         add(gch.decStack, cell)
   sysAssert(allocInv(gch.region), "gcMark end")
 
-proc markThreadStacks(gch: var TGcHeap) = 
+proc markThreadStacks(gch: var TGcHeap) =
   when hasThreadSupport and hasSharedHeap:
     {.error: "not fully implemented".}
     var it = threadList
     while it != nil:
-      # mark registers: 
+      # mark registers:
       for i in 0 .. high(it.registers): gcMark(gch, it.registers[i])
       var sp = cast[TAddress](it.stackBottom)
       var max = cast[TAddress](it.stackTop)
@@ -848,7 +888,7 @@ elif stackIncreases:
   var
     jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
       # a little hack to get the size of a TJmpBuf in the generated C code
-      # in a platform independant way
+      # in a platform independent way
 
   template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
     var registers: C_JmpBuf
@@ -897,7 +937,7 @@ else:
       while sp <=% max:
         gcMark(gch, cast[PPointer](sp)[])
         sp = sp +% sizeof(pointer)
-    
+
 proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
   forEachStackSlot(gch, gcMark)
 
@@ -910,13 +950,13 @@ when useMarkForDebug or useBackupGc:
 # ----------------------------------------------------------------------------
 
 proc collectZCT(gch: var TGcHeap): bool =
-  # Note: Freeing may add child objects to the ZCT! So essentially we do 
-  # deep freeing, which is bad for incremental operation. In order to 
+  # Note: Freeing may add child objects to the ZCT! So essentially we do
+  # deep freeing, which is bad for incremental operation. In order to
   # avoid a deep stack, we move objects to keep the ZCT small.
   # This is performance critical!
   const workPackage = 100
   var L = addr(gch.zct.len)
-  
+
   when withRealTime:
     var steps = workPackage
     var t0: TTicks
@@ -926,15 +966,15 @@ proc collectZCT(gch: var TGcHeap): bool =
     sysAssert(isAllocatedPtr(gch.region, c), "CollectZCT: isAllocatedPtr")
     # remove from ZCT:
     gcAssert((c.refcount and ZctFlag) == ZctFlag, "collectZCT")
-    
+
     c.refcount = c.refcount and not ZctFlag
     gch.zct.d[0] = gch.zct.d[L[] - 1]
     dec(L[])
     when withRealTime: dec steps
-    if c.refcount <% rcIncrement: 
+    if c.refcount <% rcIncrement:
       # It may have a RC > 0, if it is in the hardware stack or
       # it has not been removed yet from the ZCT. This is because
-      # ``incref`` does not bother to remove the cell from the ZCT 
+      # ``incref`` does not bother to remove the cell from the ZCT
       # as this might be too slow.
       # In any case, it should be removed from the ZCT. But not
       # freed. **KEEP THIS IN MIND WHEN MAKING THIS INCREMENTAL!**
@@ -947,7 +987,7 @@ proc collectZCT(gch: var TGcHeap): bool =
       # access invalid memory. This is done by prepareDealloc():
       prepareDealloc(c)
       forAllChildren(c, waZctDecRef)
-      when reallyDealloc: 
+      when reallyDealloc:
         sysAssert(allocInv(gch.region), "collectZCT: rawDealloc")
         rawDealloc(gch.region, c)
       else:
@@ -958,7 +998,7 @@ proc collectZCT(gch: var TGcHeap): bool =
         steps = workPackage
         if gch.maxPause > 0:
           let duration = getticks() - t0
-          # the GC's measuring is not accurate and needs some cleanup actions 
+          # the GC's measuring is not accurate and needs some cleanup actions
           # (stack unmarking), so subtract some short amount of time in
           # order to miss deadlines less often:
           if duration >= gch.maxPause - 50_000:
@@ -981,7 +1021,7 @@ proc collectCTBody(gch: var TGcHeap) =
   when withRealTime:
     let t0 = getticks()
   sysAssert(allocInv(gch.region), "collectCT: begin")
-  
+
   gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
   sysAssert(gch.decStack.len == 0, "collectCT")
   prepareForInteriorPointerChecking(gch.region)
@@ -1000,7 +1040,7 @@ proc collectCTBody(gch: var TGcHeap) =
         gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
   unmarkStackAndRegisters(gch)
   sysAssert(allocInv(gch.region), "collectCT: end")
-  
+
   when withRealTime:
     let duration = getticks() - t0
     gch.stat.maxPause = max(gch.stat.maxPause, duration)
@@ -1014,8 +1054,12 @@ when useMarkForDebug or useBackupGc:
     markGlobals(gch)
 
 proc collectCT(gch: var TGcHeap) =
-  if (gch.zct.len >= ZctThreshold or (cycleGC and
-      getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and 
+  # stackMarkCosts prevents some pathological behaviour: Stack marking
+  # becomes more expensive with large stacks and large stacks mean that
+  # cells with RC=0 are more likely to be kept alive by the stack.
+  let stackMarkCosts = max(stackSize() div (16*sizeof(int)), ZctThreshold)
+  if (gch.zct.len >= stackMarkCosts or (cycleGC and
+      getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and
       gch.recGcLock == 0:
     when useMarkForDebug:
       prepareForInteriorPointerChecking(gch.region)
@@ -1034,7 +1078,7 @@ when withRealTime:
     acquire(gch)
     gch.maxPause = us.toNano
     if (gch.zct.len >= ZctThreshold or (cycleGC and
-        getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or 
+        getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or
         strongAdvice:
       collectCTBody(gch)
     release(gch)
@@ -1042,13 +1086,13 @@ when withRealTime:
   proc GC_step*(us: int, strongAdvice = false) = GC_step(gch, us, strongAdvice)
 
 when not defined(useNimRtl):
-  proc GC_disable() = 
+  proc GC_disable() =
     when hasThreadSupport and hasSharedHeap:
       discard atomicInc(gch.recGcLock, 1)
     else:
       inc(gch.recGcLock)
   proc GC_enable() =
-    if gch.recGcLock > 0: 
+    if gch.recGcLock > 0:
       when hasThreadSupport and hasSharedHeap:
         discard atomicDec(gch.recGcLock, 1)
       else:
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index ee52b54f5..4e3dee51c 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -128,7 +128,7 @@ type
                              # cycle roots table that uses a cheap linear scan
                              # to find only possitively dead objects.
                              # One strategy is to perform it only for new objects
-                             # allocated between the invocations of CollectZCT.
+                             # allocated between the invocations of collectZCT.
                              # This index indicates the start of the range of
                              # such new objects within the table.
     when withRealTime:
@@ -140,7 +140,7 @@ var
   gch* {.rtlThreadVar.}: TGcHeap
 
 when not defined(useNimRtl):
-  InstantiateForRegion(gch.region)
+  instantiateForRegion(gch.region)
 
 template acquire(gch: TGcHeap) = 
   when hasThreadSupport and hasSharedHeap:
@@ -233,11 +233,11 @@ template addCycleRoot(cycleRoots: var TCellSeq, c: PCell) =
 
 proc cellToUsr(cell: PCell): pointer {.inline.} =
   # convert object (=pointer to refcount) to pointer to userdata
-  result = cast[pointer](cast[TAddress](cell)+%TAddress(sizeof(TCell)))
+  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(TCell)))
 
 proc usrToCell*(usr: pointer): PCell {.inline.} =
   # convert pointer to userdata to object (=pointer to refcount)
-  result = cast[PCell](cast[TAddress](usr)-%TAddress(sizeof(TCell)))
+  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(TCell)))
 
 proc canbeCycleRoot(c: PCell): bool {.inline.} =
   result = ntfAcyclic notin c.typ.flags
@@ -255,10 +255,10 @@ when BitsPerPage mod (sizeof(int)*8) != 0:
 
 # forward declarations:
 proc collectCT(gch: var TGcHeap)
-proc IsOnStack*(p: pointer): bool {.noinline.}
+proc isOnStack*(p: pointer): bool {.noinline.}
 proc forAllChildren(cell: PCell, op: TWalkOp)
 proc doOperation(p: pointer, op: TWalkOp)
-proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp)
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp)
 # we need the prototype here for debugging purposes
 
 proc prepareDealloc(cell: PCell) =
@@ -432,7 +432,7 @@ proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} =
     sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 2")
   sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 5")
 
-template doAsgnRef(dest: ppointer, src: pointer,
+template doAsgnRef(dest: PPointer, src: pointer,
                   heapType = LocalHeap, cycleFlag = MaybeCyclic): stmt =
   sysAssert(not isOnStack(dest), "asgnRef")
   # BUGFIX: first incRef then decRef!
@@ -440,20 +440,20 @@ template doAsgnRef(dest: ppointer, src: pointer,
   if dest[] != nil: doDecRef(usrToCell(dest[]), heapType, cycleFlag)
   dest[] = src
 
-proc asgnRef(dest: ppointer, src: pointer) {.compilerProc, inline.} =
+proc asgnRef(dest: PPointer, src: pointer) {.compilerProc, inline.} =
   # the code generator calls this proc!
   doAsgnRef(dest, src, LocalHeap, MaybeCyclic)
 
-proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerProc, inline.} =
+proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerProc, inline.} =
   # the code generator calls this proc if it is known at compile time that no 
   # cycle is possible.
   doAsgnRef(dest, src, LocalHeap, Acyclic)
 
-proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerProc.} =
+proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerProc.} =
   # unsureAsgnRef updates the reference counters only if dest is not on the
   # stack. It is used by the code generator if it cannot decide wether a
   # reference is in the stack or not (this can happen for var parameters).
-  if not IsOnStack(dest):
+  if not isOnStack(dest):
     if src != nil: doIncRef(usrToCell(src))
     # XXX we must detect a shared heap here
     # better idea may be to just eliminate the need for unsureAsgnRef
@@ -470,16 +470,16 @@ proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerProc.} =
 
 when hasThreadSupport and hasSharedHeap:
   # shared heap version of the above procs
-  proc asgnRefSh(dest: ppointer, src: pointer) {.compilerProc, inline.} =
+  proc asgnRefSh(dest: PPointer, src: pointer) {.compilerProc, inline.} =
     doAsgnRef(dest, src, SharedHeap, MaybeCyclic)
 
-  proc asgnRefNoCycleSh(dest: ppointer, src: pointer) {.compilerProc, inline.} =
+  proc asgnRefNoCycleSh(dest: PPointer, src: pointer) {.compilerProc, inline.} =
     doAsgnRef(dest, src, SharedHeap, Acyclic)
 
 proc initGC() =
   when not defined(useNimRtl):
     when traceGC:
-      for i in low(TCellState)..high(TCellState): Init(states[i])
+      for i in low(TCellState)..high(TCellState): init(states[i])
     gch.cycleThreshold = InitialCycleThreshold
     gch.stat.stackScans = 0
     gch.stat.cycleCollections = 0
@@ -491,11 +491,11 @@ proc initGC() =
     init(gch.zct)
     init(gch.tempStack)
     init(gch.freeStack)
-    Init(gch.cycleRoots)
-    Init(gch.decStack)
+    init(gch.cycleRoots)
+    init(gch.decStack)
 
 proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
-  var d = cast[TAddress](dest)
+  var d = cast[ByteAddress](dest)
   case n.kind
   of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
   of nkList:
@@ -503,7 +503,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
       # inlined for speed
       if n.sons[i].kind == nkSlot:
         if n.sons[i].typ.kind in {tyRef, tyString, tySequence}:
-          doOperation(cast[ppointer](d +% n.sons[i].offset)[], op)
+          doOperation(cast[PPointer](d +% n.sons[i].offset)[], op)
         else:
           forAllChildrenAux(cast[pointer](d +% n.sons[i].offset), 
                             n.sons[i].typ, op)
@@ -514,19 +514,19 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
     if m != nil: forAllSlotsAux(dest, m, op)
   of nkNone: sysAssert(false, "forAllSlotsAux")
 
-proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
-  var d = cast[TAddress](dest)
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
+  var d = cast[ByteAddress](dest)
   if dest == nil: return # nothing to do
   if ntfNoRefs notin mt.flags:
-    case mt.Kind
+    case mt.kind
     of tyRef, tyString, tySequence: # leaf:
-      doOperation(cast[ppointer](d)[], op)
+      doOperation(cast[PPointer](d)[], op)
     of tyObject, tyTuple:
       forAllSlotsAux(dest, mt.node, op)
     of tyArray, tyArrayConstr, tyOpenArray:
       for i in 0..(mt.size div mt.base.size)-1:
         forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
-    else: nil
+    else: discard
 
 proc forAllChildren(cell: PCell, op: TWalkOp) =
   sysAssert(cell != nil, "forAllChildren: 1")
@@ -536,18 +536,18 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
   if marker != nil:
     marker(cellToUsr(cell), op.int)
   else:
-    case cell.typ.Kind
+    case cell.typ.kind
     of tyRef: # common case
       forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
     of tySequence:
-      var d = cast[TAddress](cellToUsr(cell))
+      var d = cast[ByteAddress](cellToUsr(cell))
       var s = cast[PGenericSeq](d)
       if s != nil:
         let baseAddr = d +% GenericSeqSize
         for i in 0..s.len-1:
           forAllChildrenAux(cast[pointer](baseAddr +% i *% cell.typ.base.size),
                             cell.typ.base, op)
-    else: nil
+    else: discard
 
 proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
   # we check the last 8 entries (cache line) for a slot that could be reused.
@@ -593,7 +593,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
         return
     add(gch.zct, res)
 
-proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1: bool): pointer =
+proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1 = false): pointer =
   # generates a new object and sets its reference counter to 0
   acquire(gch)
   sysAssert(allocInv(gch.region), "rawNewObj begin")
@@ -605,7 +605,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1: bool): pointer =
   var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
   sysAssert(allocInv(gch.region), "rawNewObj after rawAlloc")
 
-  sysAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
+  sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
   
   res.typ = typ
   
@@ -634,8 +634,6 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1: bool): pointer =
   gcTrace(res, csAllocated)
   release(gch)
   result = cellToUsr(res)
-  zeroMem(result, size)
-  when defined(memProfiler): nimProfile(size)
   sysAssert(allocInv(gch.region), "rawNewObj end")
 
 {.pop.}
@@ -670,23 +668,31 @@ template trimAt(roots: var TCellSeq, at: int): stmt =
 proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
   setStackTop(gch)
   result = rawNewObj(typ, size, gch, false)
-  
+  zeroMem(result, size)
+  when defined(memProfiler): nimProfile(size)
+
+proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
+  setStackTop(gch)
+  result = rawNewObj(typ, size, gch, false)
+  when defined(memProfiler): nimProfile(size)
+
 proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
   setStackTop(gch)
-  # `rawNewObj` already uses locks, so no need for them here.
+  # `newObj` already uses locks, so no need for them here.
   let size = addInt(mulInt(len, typ.base.size), GenericSeqSize)
-  result = rawNewObj(typ, size, gch, false)
+  result = newObj(typ, size)
   cast[PGenericSeq](result).len = len
   cast[PGenericSeq](result).reserved = len
 
 proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
   setStackTop(gch)
   result = rawNewObj(typ, size, gch, true)
+  when defined(memProfiler): nimProfile(size)
 
 proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
   setStackTop(gch)
   let size = addInt(mulInt(len, typ.base.size), GenericSeqSize)
-  result = rawNewObj(typ, size, gch, true)
+  result = newObjRC1(typ, size)
   cast[PGenericSeq](result).len = len
   cast[PGenericSeq](result).reserved = len
 
@@ -708,10 +714,10 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
   # call user-defined move code
   # call user-defined default constructor
   copyMem(res, ol, oldsize + sizeof(TCell))
-  zeroMem(cast[pointer](cast[TAddress](res)+% oldsize +% sizeof(TCell)),
+  zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(TCell)),
           newsize-oldsize)
 
-  sysAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
+  sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
   sysAssert(res.refcount shr rcShift <=% 1, "growObj: 4")
   
   when false:
@@ -786,10 +792,10 @@ type
     FromChildren,
     FromRoot
 
-proc CollectZCT(gch: var TGcHeap): bool
+proc collectZCT(gch: var TGcHeap): bool
 
 template pseudoRecursion(typ: TRecursionType, body: stmt): stmt =
-  #
+  discard
 
 proc trimCycleRoots(gch: var TGcHeap, startIdx = gch.cycleRootsTrimIdx) =
   var i = startIdx
@@ -967,17 +973,17 @@ proc collectCycles(gch: var TGcHeap) =
       maybedeads,
       collected
 
-  Deinit(gch.cycleRoots)
-  Init(gch.cycleRoots)
+  deinit(gch.cycleRoots)
+  init(gch.cycleRoots)
 
-  Deinit(gch.freeStack)
-  Init(gch.freeStack)
+  deinit(gch.freeStack)
+  init(gch.freeStack)
 
   when MarkingSkipsAcyclicObjects:
     # Collect the acyclic objects that became unreachable due to collected
     # cyclic objects. 
-    discard CollectZCT(gch)
-    # CollectZCT may add new cycle candidates and we may decide to loop here
+    discard collectZCT(gch)
+    # collectZCT may add new cycle candidates and we may decide to loop here
     # if gch.cycleRoots.len > 0: repeat
 
 var gcDebugging* = false
@@ -988,7 +994,7 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
   # the addresses are not as cells on the stack, so turn them to cells:
   sysAssert(allocInv(gch.region), "gcMark begin")
   var cell = usrToCell(p)
-  var c = cast[TAddress](cell)
+  var c = cast[ByteAddress](cell)
   if c >% PageSize:
     # fast check: does it look like a cell?
     var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell))
@@ -997,6 +1003,7 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
       if objStart.color != rcReallyDead:
         if gcDebugging:
           # writeCell("marking ", objStart)
+          discard
         else:
           inc objStart.refcount, rcIncrement
           gch.decStack.add objStart
@@ -1009,6 +1016,7 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
         # coincidence due to the conservative stack marking.
         when debugGC:
           # writeCell("marking dead object", objStart)
+          discard
     when false:
       if isAllocatedPtr(gch.region, cell):
         sysAssert false, "allocated pointer but not interior?"
@@ -1024,12 +1032,12 @@ proc markThreadStacks(gch: var TGcHeap) =
     while it != nil:
       # mark registers: 
       for i in 0 .. high(it.registers): gcMark(gch, it.registers[i])
-      var sp = cast[TAddress](it.stackBottom)
-      var max = cast[TAddress](it.stackTop)
+      var sp = cast[ByteAddress](it.stackBottom)
+      var max = cast[ByteAddress](it.stackTop)
       # XXX stack direction?
       # XXX unroll this loop:
       while sp <=% max:
-        gcMark(gch, cast[ppointer](sp)[])
+        gcMark(gch, cast[PPointer](sp)[])
         sp = sp +% sizeof(pointer)
       it = it.next
 
@@ -1051,8 +1059,8 @@ when not defined(useNimRtl):
     # the first init must be the one that defines the stack bottom:
     if gch.stackBottom == nil: gch.stackBottom = theStackBottom
     else:
-      var a = cast[TAddress](theStackBottom) # and not PageMask - PageSize*2
-      var b = cast[TAddress](gch.stackBottom)
+      var a = cast[ByteAddress](theStackBottom) # and not PageMask - PageSize*2
+      var b = cast[ByteAddress](gch.stackBottom)
       #c_fprintf(c_stdout, "old: %p new: %p;\n",gch.stackBottom,theStackBottom)
       when stackIncreases:
         gch.stackBottom = cast[pointer](min(a, b))
@@ -1067,15 +1075,15 @@ proc stackSize(): int {.noinline.} =
 var
   jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
     # a little hack to get the size of a TJmpBuf in the generated C code
-    # in a platform independant way
+    # in a platform independent way
 
 when defined(sparc): # For SPARC architecture.
   proc isOnStack(p: pointer): bool =
     var stackTop {.volatile.}: pointer
     stackTop = addr(stackTop)
-    var b = cast[TAddress](gch.stackBottom)
-    var a = cast[TAddress](stackTop)
-    var x = cast[TAddress](p)
+    var b = cast[ByteAddress](gch.stackBottom)
+    var a = cast[ByteAddress](stackTop)
+    var x = cast[ByteAddress](p)
     result = a <=% x and x <=% b
 
   proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
@@ -1092,7 +1100,7 @@ when defined(sparc): # For SPARC architecture.
     # Addresses decrease as the stack grows.
     while sp <= max:
       gcMark(gch, sp[])
-      sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
+      sp = cast[PPointer](cast[ByteAddress](sp) +% sizeof(pointer))
 
 elif defined(ELATE):
   {.error: "stack marking code is to be written for this architecture".}
@@ -1104,20 +1112,20 @@ elif stackIncreases:
   proc isOnStack(p: pointer): bool =
     var stackTop {.volatile.}: pointer
     stackTop = addr(stackTop)
-    var a = cast[TAddress](gch.stackBottom)
-    var b = cast[TAddress](stackTop)
-    var x = cast[TAddress](p)
+    var a = cast[ByteAddress](gch.stackBottom)
+    var b = cast[ByteAddress](stackTop)
+    var x = cast[ByteAddress](p)
     result = a <=% x and x <=% b
   
   proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
     var registers: C_JmpBuf
     if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
-      var max = cast[TAddress](gch.stackBottom)
-      var sp = cast[TAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
+      var max = cast[ByteAddress](gch.stackBottom)
+      var sp = cast[ByteAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
       # sp will traverse the JMP_BUF as well (jmp_buf size is added,
       # otherwise sp would be below the registers structure).
       while sp >=% max:
-        gcMark(gch, cast[ppointer](sp)[])
+        gcMark(gch, cast[PPointer](sp)[])
         sp = sp -% sizeof(pointer)
 
 else:
@@ -1127,9 +1135,9 @@ else:
   proc isOnStack(p: pointer): bool =
     var stackTop {.volatile.}: pointer
     stackTop = addr(stackTop)
-    var b = cast[TAddress](gch.stackBottom)
-    var a = cast[TAddress](stackTop)
-    var x = cast[TAddress](p)
+    var b = cast[ByteAddress](gch.stackBottom)
+    var a = cast[ByteAddress](stackTop)
+    var x = cast[ByteAddress](p)
     result = a <=% x and x <=% b
 
   proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
@@ -1141,18 +1149,18 @@ else:
     if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
       when MinimumStackMarking:
         # mark the registers
-        var jmpbufPtr = cast[TAddress](addr(registers))
+        var jmpbufPtr = cast[ByteAddress](addr(registers))
         var jmpbufEnd = jmpbufPtr +% jmpbufSize
       
         while jmpbufPtr <=% jmpbufEnd:
-          gcMark(gch, cast[ppointer](jmpbufPtr)[])
+          gcMark(gch, cast[PPointer](jmpbufPtr)[])
           jmpbufPtr = jmpbufPtr +% sizeof(pointer)
 
-        var sp = cast[TAddress](gch.stackTop)
+        var sp = cast[ByteAddress](gch.stackTop)
       else:
-        var sp = cast[TAddress](addr(registers))
+        var sp = cast[ByteAddress](addr(registers))
       # mark the user stack
-      var max = cast[TAddress](gch.stackBottom)
+      var max = cast[ByteAddress](gch.stackBottom)
       # loop unrolled:
       while sp <% max - 8*sizeof(pointer):
         gcMark(gch, cast[PStackSlice](sp)[0])
@@ -1166,7 +1174,7 @@ else:
         sp = sp +% sizeof(pointer)*8
       # last few entries:
       while sp <=% max:
-        gcMark(gch, cast[ppointer](sp)[])
+        gcMark(gch, cast[PPointer](sp)[])
         sp = sp +% sizeof(pointer)
 
 # ----------------------------------------------------------------------------
@@ -1202,7 +1210,7 @@ proc releaseCell(gch: var TGcHeap, cell: PCell) =
   #  recursion).
   # We can ignore it now as the ZCT cleaner will reach it soon.
 
-proc CollectZCT(gch: var TGcHeap): bool =
+proc collectZCT(gch: var TGcHeap): bool =
   const workPackage = 100
   var L = addr(gch.zct.len)
   
@@ -1213,8 +1221,8 @@ proc CollectZCT(gch: var TGcHeap): bool =
   
   while L[] > 0:
     var c = gch.zct.d[0]
-    sysAssert c.isBitUp(rcZct), "CollectZCT: rcZct missing!"
-    sysAssert(isAllocatedPtr(gch.region, c), "CollectZCT: isAllocatedPtr")
+    sysAssert c.isBitUp(rcZct), "collectZCT: rcZct missing!"
+    sysAssert(isAllocatedPtr(gch.region, c), "collectZCT: isAllocatedPtr")
     
     # remove from ZCT:    
     c.clearBit(rcZct)
@@ -1263,7 +1271,7 @@ proc unmarkStackAndRegisters(gch: var TGcHeap) =
     # XXX no need for an atomic dec here:
     if c.refcount--(LocalHeap):
       # the object survived only because of a stack reference
-      # it still doesn't have heap refernces
+      # it still doesn't have heap references
       addZCT(gch.zct, c)
     
     if canbeCycleRoot(c):
@@ -1295,7 +1303,7 @@ proc collectCTBody(gch: var TGcHeap) =
         sysAssert gch.zct.len == 0, "zct is not null after collect cycles"
         inc(gch.stat.cycleCollections)
         gch.cycleThreshold = max(InitialCycleThreshold, getOccupiedMem() *
-                                 cycleIncrease)
+                                 CycleIncrease)
         gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
   unmarkStackAndRegisters(gch)
   sysAssert(allocInv(gch.region), "collectCT: end")
@@ -1344,12 +1352,12 @@ when not defined(useNimRtl):
       else:
         dec(gch.recGcLock)
 
-  proc GC_setStrategy(strategy: TGC_Strategy) =
+  proc GC_setStrategy(strategy: GC_Strategy) =
     case strategy
-    of gcThroughput: nil
-    of gcResponsiveness: nil
-    of gcOptimizeSpace: nil
-    of gcOptimizeTime: nil
+    of gcThroughput: discard
+    of gcResponsiveness: discard
+    of gcOptimizeSpace: discard
+    of gcOptimizeTime: discard
 
   proc GC_enableMarkAndSweep() =
     gch.cycleThreshold = InitialCycleThreshold
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index 0eafd3255..e287bf5d9 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -1,19 +1,19 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# A simple mark&sweep garbage collector for Nim. Define the 
+# A simple mark&sweep garbage collector for Nim. Define the
 # symbol ``gcUseBitvectors`` to generate a variant of this GC.
 {.push profiler:off.}
 
 const
   InitialThreshold = 4*1024*1024 # X MB because marking&sweeping is slow
-  withBitvectors = defined(gcUseBitvectors) 
+  withBitvectors = defined(gcUseBitvectors)
   # bitvectors are significantly faster for GC-bench, but slower for
   # bootstrapping and use more memory
   rcWhite = 0
@@ -29,21 +29,21 @@ type
   TWalkOp = enum
     waMarkGlobal,  # we need to mark conservatively for global marker procs
                    # as these may refer to a global var and not to a thread
-                   # local 
+                   # local
     waMarkPrecise  # fast precise marking
 
   TFinalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
     # A ref type can have a finalizer that is called before the object's
     # storage is freed.
-  
+
   TGlobalMarkerProc = proc () {.nimcall, benign.}
 
   TGcStat = object
     collections: int         # number of performed full collections
     maxThreshold: int        # max threshold that has been set
     maxStackSize: int        # max stack size
-    freedObjects: int        # max entries in cycle table  
-  
+    freedObjects: int        # max entries in cycle table
+
   TGcHeap = object           # this contains the zero count and
                              # non-zero count table
     stackBottom: pointer
@@ -64,11 +64,11 @@ var
 when not defined(useNimRtl):
   instantiateForRegion(gch.region)
 
-template acquire(gch: TGcHeap) = 
+template acquire(gch: TGcHeap) =
   when hasThreadSupport and hasSharedHeap:
     acquireSys(HeapLock)
 
-template release(gch: TGcHeap) = 
+template release(gch: TGcHeap) =
   when hasThreadSupport and hasSharedHeap:
     releaseSys(HeapLock)
 
@@ -134,7 +134,7 @@ proc prepareDealloc(cell: PCell) =
     (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
     dec(gch.recGcLock)
 
-proc nimGCref(p: pointer) {.compilerProc.} = 
+proc nimGCref(p: pointer) {.compilerProc.} =
   # we keep it from being collected by pretending it's not even allocated:
   when false:
     when withBitvectors: excl(gch.allocated, usrToCell(p))
@@ -165,7 +165,7 @@ proc initGC() =
     init(gch.tempStack)
     init(gch.additionalRoots)
     when withBitvectors:
-      Init(gch.allocated)
+      init(gch.allocated)
       init(gch.marked)
 
 var
@@ -261,6 +261,10 @@ proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
   zeroMem(result, size)
   when defined(memProfiler): nimProfile(size)
 
+proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
+  result = rawNewObj(typ, size, gch)
+  when defined(memProfiler): nimProfile(size)
+
 proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
   # `newObj` already uses locks, so no need for them here.
   let size = addInt(mulInt(len, typ.base.size), GenericSeqSize)
@@ -273,34 +277,36 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
   result = rawNewObj(typ, size, gch)
   zeroMem(result, size)
   when defined(memProfiler): nimProfile(size)
-  
+
 proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
   let size = addInt(mulInt(len, typ.base.size), GenericSeqSize)
   result = newObj(typ, size)
   cast[PGenericSeq](result).len = len
   cast[PGenericSeq](result).reserved = len
   when defined(memProfiler): nimProfile(size)
-  
+
 proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
   acquire(gch)
   collectCT(gch)
   var ol = usrToCell(old)
   sysAssert(ol.typ != nil, "growObj: 1")
   gcAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2")
-  
+
   var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(TCell)))
   var elemSize = 1
   if ol.typ.kind != tyString: elemSize = ol.typ.base.size
-  
+
   var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
   copyMem(res, ol, oldsize + sizeof(TCell))
   zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(TCell)),
           newsize-oldsize)
   sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
-  when withBitvectors: excl(gch.allocated, ol)
-  when reallyDealloc: rawDealloc(gch.region, ol)
-  else:
-    zeroMem(ol, sizeof(TCell))
+  when false:
+    # this is wrong since seqs can be shared via 'shallow':
+    when withBitvectors: excl(gch.allocated, ol)
+    when reallyDealloc: rawDealloc(gch.region, ol)
+    else:
+      zeroMem(ol, sizeof(TCell))
   when withBitvectors: incl(gch.allocated, res)
   when useCellIds:
     inc gch.idGenerator
@@ -399,7 +405,7 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
     var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell))
     if objStart != nil:
       mark(gch, objStart)
-  
+
 # ----------------- stack management --------------------------------------
 #  inspired from Smart Eiffel
 
@@ -474,7 +480,7 @@ elif stackIncreases:
   var
     jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
       # a little hack to get the size of a TJmpBuf in the generated C code
-      # in a platform independant way
+      # in a platform independent way
 
   proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
     var registers: C_JmpBuf
@@ -534,7 +540,7 @@ proc collectCTBody(gch: var TGcHeap) =
   markStackAndRegisters(gch)
   markGlobals(gch)
   sweep(gch)
-  
+
   inc(gch.stat.collections)
   when withBitvectors:
     deinit(gch.marked)
@@ -542,19 +548,19 @@ proc collectCTBody(gch: var TGcHeap) =
   gch.cycleThreshold = max(InitialThreshold, getOccupiedMem().mulThreshold)
   gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
   sysAssert(allocInv(gch.region), "collectCT: end")
-  
+
 proc collectCT(gch: var TGcHeap) =
   if getOccupiedMem(gch.region) >= gch.cycleThreshold and gch.recGcLock == 0:
     collectCTBody(gch)
 
 when not defined(useNimRtl):
-  proc GC_disable() = 
+  proc GC_disable() =
     when hasThreadSupport and hasSharedHeap:
       atomicInc(gch.recGcLock, 1)
     else:
       inc(gch.recGcLock)
   proc GC_enable() =
-    if gch.recGcLock > 0: 
+    if gch.recGcLock > 0:
       when hasThreadSupport and hasSharedHeap:
         atomicDec(gch.recGcLock, 1)
       else:
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index e599668a7..aff0c0e6f 100644
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -11,7 +11,7 @@ when declared(NimString):
   # we are in system module:
   {.pragma: codegenType, compilerproc.}
 else:
-  {.pragma: codegenType.}
+  {.pragma: codegenType, importc.}
 
 type 
   # This should be he same as ast.TTypeKind
@@ -26,7 +26,7 @@ type
     tyExpr,
     tyStmt,
     tyTypeDesc,
-    tyGenericInvokation, # ``T[a, b]`` for types to invoke
+    tyGenericInvocation, # ``T[a, b]`` for types to invoke
     tyGenericBody,       # ``T[a, b, body]`` last parameter is the body
     tyGenericInst,       # ``T[a, b, realInstance]`` instantiated generic type
     tyGenericParam,      # ``a`` in the example
@@ -65,7 +65,7 @@ type
     tyBigNum,
 
   TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
-  TNimNode {.codegenType, final.} = object
+  TNimNode {.codegenType.} = object
     kind: TNimNodeKind
     offset: int
     typ: ptr TNimType
@@ -78,7 +78,7 @@ type
     ntfAcyclic = 1,    # type cannot form a cycle
     ntfEnumHole = 2    # enum has holes and thus `$` for them needs the slow
                        # version
-  TNimType {.codegenType, final.} = object
+  TNimType {.codegenType.} = object
     size: int
     kind: TNimKind
     flags: set[TNimTypeFlag]
diff --git a/lib/system/inclrtl.nim b/lib/system/inclrtl.nim
index aac802229..dbc961402 100644
--- a/lib/system/inclrtl.nim
+++ b/lib/system/inclrtl.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 9b4a7d556..3b55f62ca 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -128,7 +128,7 @@ proc raiseOverflow {.exportc: "raiseOverflow", noreturn.} =
   raise newException(OverflowError, "over- or underflow")
 
 proc raiseDivByZero {.exportc: "raiseDivByZero", noreturn.} =
-  raise newException(DivByZeroError, "divison by zero")
+  raise newException(DivByZeroError, "division by zero")
 
 proc raiseRangeError() {.compilerproc, noreturn.} =
   raise newException(RangeError, "value out of range")
@@ -322,10 +322,10 @@ when defined(kwin):
       }
       print(buf);
     """
-    
+
 elif defined(nodejs):
   proc ewriteln(x: cstring) = log(x)
-  
+
   proc rawEcho {.compilerproc, asmNoStackFrame.} =
     asm """
       var buf = "";
@@ -339,12 +339,12 @@ else:
   var
     document {.importc, nodecl.}: ref TDocument
 
-  proc ewriteln(x: cstring) = 
+  proc ewriteln(x: cstring) =
     var node = document.getElementsByTagName("body")[0]
-    if node != nil: 
+    if node != nil:
       node.appendChild(document.createTextNode(x))
       node.appendChild(document.createElement("br"))
-    else: 
+    else:
       raise newException(ValueError, "<body> element does not exist yet!")
 
   proc rawEcho {.compilerproc.} =
@@ -563,7 +563,11 @@ proc nimCopy(x: pointer, ti: PNimType): pointer =
       }
     """
   of tyString:
-    asm "`result` = `x`.slice(0);"
+    asm """
+      if (`x` !== null) {
+        `result` = `x`.slice(0);
+      }
+    """
   else:
     result = x
 
@@ -679,7 +683,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat, start = 0): int {
   if s[i] == 'I' or s[i] == 'i':
     if s[i+1] == 'N' or s[i+1] == 'n':
       if s[i+2] == 'F' or s[i+2] == 'f':
-        if s[i+3] notin IdentChars: 
+        if s[i+3] notin IdentChars:
           number = Inf*sign
           return i+3 - start
     return 0
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index e091c0889..a378f86e7 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -23,7 +23,7 @@ const
   leakDetector = false
   overwriteFree = false
   trackAllocationSource = leakDetector
-  
+
   cycleGC = true # (de)activate the cycle GC
   reallyDealloc = true # for debugging purposes this can be set to false
   reallyOsDealloc = true
@@ -71,13 +71,13 @@ when defined(boehmgc):
     const boehmLib = "libgc.dylib"
   else:
     const boehmLib = "/usr/lib/libgc.so.1"
-    
+
   proc boehmGCinit {.importc: "GC_init", dynlib: boehmLib.}
-  proc boehmGC_disable {.importc: "GC_disable", dynlib: boehmLib.} 
-  proc boehmGC_enable {.importc: "GC_enable", dynlib: boehmLib.} 
+  proc boehmGC_disable {.importc: "GC_disable", dynlib: boehmLib.}
+  proc boehmGC_enable {.importc: "GC_enable", dynlib: boehmLib.}
   proc boehmGCincremental {.
-    importc: "GC_enable_incremental", dynlib: boehmLib.} 
-  proc boehmGCfullCollect {.importc: "GC_gcollect", dynlib: boehmLib.}  
+    importc: "GC_enable_incremental", dynlib: boehmLib.}
+  proc boehmGCfullCollect {.importc: "GC_gcollect", dynlib: boehmLib.}
   proc boehmAlloc(size: int): pointer {.
     importc: "GC_malloc", dynlib: boehmLib.}
   proc boehmAllocAtomic(size: int): pointer {.
@@ -85,7 +85,7 @@ when defined(boehmgc):
   proc boehmRealloc(p: pointer, size: int): pointer {.
     importc: "GC_realloc", dynlib: boehmLib.}
   proc boehmDealloc(p: pointer) {.importc: "GC_free", dynlib: boehmLib.}
-  
+
   proc boehmGetHeapSize: int {.importc: "GC_get_heap_size", dynlib: boehmLib.}
     ## Return the number of bytes in the heap.  Excludes collector private
     ## data structures. Includes empty blocks and fragmentation loss.
@@ -108,25 +108,25 @@ when defined(boehmgc):
     zeroMem(result, size)
 
   when not defined(useNimRtl):
-    
-    proc alloc(size: int): pointer =
+
+    proc alloc(size: Natural): pointer =
       result = boehmAlloc(size)
       if result == nil: raiseOutOfMem()
-    proc alloc0(size: int): pointer =
+    proc alloc0(size: Natural): pointer =
       result = alloc(size)
       zeroMem(result, size)
-    proc realloc(p: pointer, newsize: int): pointer =
+    proc realloc(p: pointer, newsize: Natural): pointer =
       result = boehmRealloc(p, newsize)
       if result == nil: raiseOutOfMem()
     proc dealloc(p: pointer) = boehmDealloc(p)
-    
-    proc allocShared(size: int): pointer =
+
+    proc allocShared(size: Natural): pointer =
       result = boehmAlloc(size)
       if result == nil: raiseOutOfMem()
-    proc allocShared0(size: int): pointer =
+    proc allocShared0(size: Natural): pointer =
       result = alloc(size)
       zeroMem(result, size)
-    proc reallocShared(p: pointer, newsize: int): pointer =
+    proc reallocShared(p: pointer, newsize: Natural): pointer =
       result = boehmRealloc(p, newsize)
       if result == nil: raiseOutOfMem()
     proc deallocShared(p: pointer) = boehmDealloc(p)
@@ -144,18 +144,18 @@ when defined(boehmgc):
     proc GC_disable() = boehmGC_disable()
     proc GC_enable() = boehmGC_enable()
     proc GC_fullCollect() = boehmGCfullCollect()
-    proc GC_setStrategy(strategy: TGC_Strategy) = discard
+    proc GC_setStrategy(strategy: GC_Strategy) = discard
     proc GC_enableMarkAndSweep() = discard
     proc GC_disableMarkAndSweep() = discard
     proc GC_getStatistics(): string = return ""
-    
+
     proc getOccupiedMem(): int = return boehmGetHeapSize()-boehmGetFreeBytes()
     proc getFreeMem(): int = return boehmGetFreeBytes()
     proc getTotalMem(): int = return boehmGetHeapSize()
 
     proc setStackBottom(theStackBottom: pointer) = discard
 
-  proc initGC() = 
+  proc initGC() =
     when defined(macosx): boehmGCinit()
 
   proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
@@ -171,7 +171,7 @@ 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.} =
     dest[] = src
   proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
@@ -181,39 +181,39 @@ when defined(boehmgc):
 
   type
     TMemRegion = object {.final, pure.}
-  
+
   proc alloc(r: var TMemRegion, size: int): pointer =
     result = boehmAlloc(size)
     if result == nil: raiseOutOfMem()
   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
 
   include "system/cellsets"
 elif defined(nogc) and defined(useMalloc):
-  
+
   when not defined(useNimRtl):
-    proc alloc(size: int): pointer =
+    proc alloc(size: Natural): pointer =
       result = cmalloc(size)
       if result == nil: raiseOutOfMem()
-    proc alloc0(size: int): pointer =
+    proc alloc0(size: Natural): pointer =
       result = alloc(size)
       zeroMem(result, size)
-    proc realloc(p: pointer, newsize: int): pointer =
+    proc realloc(p: pointer, newsize: Natural): pointer =
       result = crealloc(p, newsize)
       if result == nil: raiseOutOfMem()
     proc dealloc(p: pointer) = cfree(p)
-    
-    proc allocShared(size: int): pointer =
+
+    proc allocShared(size: Natural): pointer =
       result = cmalloc(size)
       if result == nil: raiseOutOfMem()
-    proc allocShared0(size: int): pointer =
+    proc allocShared0(size: Natural): pointer =
       result = alloc(size)
       zeroMem(result, size)
-    proc reallocShared(p: pointer, newsize: int): pointer =
+    proc reallocShared(p: pointer, newsize: Natural): pointer =
       result = crealloc(p, newsize)
       if result == nil: raiseOutOfMem()
     proc deallocShared(p: pointer) = cfree(p)
@@ -221,15 +221,15 @@ elif defined(nogc) and defined(useMalloc):
     proc GC_disable() = discard
     proc GC_enable() = discard
     proc GC_fullCollect() = discard
-    proc GC_setStrategy(strategy: TGC_Strategy) = discard
+    proc GC_setStrategy(strategy: GC_Strategy) = discard
     proc GC_enableMarkAndSweep() = discard
     proc GC_disableMarkAndSweep() = discard
     proc GC_getStatistics(): string = return ""
-    
+
     proc getOccupiedMem(): int = discard
     proc getFreeMem(): int = discard
     proc getTotalMem(): int = discard
-    
+
     proc setStackBottom(theStackBottom: pointer) = discard
 
   proc initGC() = discard
@@ -240,13 +240,15 @@ elif defined(nogc) and defined(useMalloc):
     result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
     cast[PGenericSeq](result).len = len
     cast[PGenericSeq](result).reserved = len
+  proc newObjNoInit(typ: PNimType, size: int): pointer =
+    result = alloc(size)
 
   proc growObj(old: pointer, newsize: int): pointer =
     result = realloc(old, newsize)
 
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
-  
+
   proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
   proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
@@ -256,7 +258,7 @@ elif defined(nogc) and defined(useMalloc):
 
   type
     TMemRegion = object {.final, pure.}
-  
+
   proc alloc(r: var TMemRegion, size: int): pointer =
     result = alloc(size)
   proc alloc0(r: var TMemRegion, size: int): pointer =
@@ -272,23 +274,27 @@ elif defined(nogc):
   # object, because C does not support this operation... Even though every
   # possible implementation has to have a way to determine the object's size.
   # C just sucks.
-  when appType == "lib": 
+  when appType == "lib":
     {.warning: "nogc in a library context may not work".}
-  
+
   include "system/alloc"
 
   proc initGC() = discard
   proc GC_disable() = discard
   proc GC_enable() = discard
   proc GC_fullCollect() = discard
-  proc GC_setStrategy(strategy: TGC_Strategy) = discard
+  proc GC_setStrategy(strategy: GC_Strategy) = discard
   proc GC_enableMarkAndSweep() = discard
   proc GC_disableMarkAndSweep() = discard
   proc GC_getStatistics(): string = return ""
-  
-  
+
+
   proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
     result = alloc0(size)
+
+  proc newObjNoInit(typ: PNimType, size: int): pointer =
+    result = alloc(size)
+
   proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
     result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
     cast[PGenericSeq](result).len = len
@@ -299,7 +305,7 @@ elif defined(nogc):
   proc setStackBottom(theStackBottom: pointer) = discard
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
-  
+
   proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
   proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
@@ -327,6 +333,6 @@ else:
     include "system/gc"
   else:
     include "system/gc"
-  
+
 {.pop.}
 
diff --git a/lib/system/platforms.nim b/lib/system/platforms.nim
index 3ec6a270e..47a01d5fe 100644
--- a/lib/system/platforms.nim
+++ b/lib/system/platforms.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/system/profiler.nim b/lib/system/profiler.nim
index 96ab6abc7..6d6863caa 100644
--- a/lib/system/profiler.nim
+++ b/lib/system/profiler.nim
@@ -51,7 +51,7 @@ proc captureStackTrace(f: PFrame, st: var TStackTrace) =
 
 when defined(memProfiler):
   type
-    TMemProfilerHook* = proc (st: TStackTrace, requestedSize: int) {.nimcall.}
+    TMemProfilerHook* = proc (st: TStackTrace, requestedSize: int) {.nimcall, benign.}
   var
     profilerHook*: TMemProfilerHook
       ## set this variable to provide a procedure that implements a profiler in
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index 2de603cea..f1029ff6a 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -30,14 +30,16 @@ proc reprStrAux(result: var string, s: string) =
     add result, "nil"
     return
   add result, reprPointer(cast[pointer](s)) & "\""
-  for c in items(s):
+  for i in 0.. <s.len:
+    let c = s[i]
     case c
     of '"': add result, "\\\""
     of '\\': add result, "\\\\" # BUGFIX: forgotten
     of '\10': add result, "\\10\"\n\"" # " \n " # better readability
     of '\128' .. '\255', '\0'..'\9', '\11'..'\31':
       add result, "\\" & reprInt(ord(c))
-    else: result.add(c)
+    else:
+      result.add(c)
   add result, "\""
 
 proc reprStr(s: string): string {.compilerRtl.} =
@@ -78,7 +80,7 @@ proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
 type
   PByteArray = ptr array[0.. 0xffff, int8]
 
-proc addSetElem(result: var string, elem: int, typ: PNimType) {.gcsafe.} =
+proc addSetElem(result: var string, elem: int, typ: PNimType) {.benign.} =
   case typ.kind
   of tyEnum: add result, reprEnum(elem, typ)
   of tyBool: add result, reprBool(bool(elem))
@@ -147,7 +149,7 @@ when not defined(useNimRtl):
     for i in 0..cl.indent-1: add result, ' '
 
   proc reprAux(result: var string, p: pointer, typ: PNimType,
-               cl: var TReprClosure) {.gcsafe.}
+               cl: var TReprClosure) {.benign.}
 
   proc reprArray(result: var string, p: pointer, typ: PNimType,
                  cl: var TReprClosure) =
@@ -172,7 +174,7 @@ when not defined(useNimRtl):
     add result, "]"
 
   proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
-                     cl: var TReprClosure) {.gcsafe.} =
+                     cl: var TReprClosure) {.benign.} =
     case n.kind
     of nkNone: sysAssert(false, "reprRecordAux")
     of nkSlot:
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 7908fbe4d..3f860655e 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -16,7 +16,7 @@
                        # of the standard library!
 
 
-proc fputs(c: cstring, f: File) {.importc: "fputs", header: "<stdio.h>", 
+proc fputs(c: cstring, f: File) {.importc: "fputs", header: "<stdio.h>",
   tags: [WriteIOEffect].}
 proc fgets(c: cstring, n: int, f: File): cstring {.
   importc: "fgets", header: "<stdio.h>", tags: [ReadIOEffect].}
@@ -26,11 +26,30 @@ proc ungetc(c: cint, f: File) {.importc: "ungetc", header: "<stdio.h>",
   tags: [].}
 proc putc(c: char, stream: File) {.importc: "putc", header: "<stdio.h>",
   tags: [WriteIOEffect].}
-proc fprintf(f: File, frmt: cstring) {.importc: "fprintf", 
+proc fprintf(f: File, frmt: cstring) {.importc: "fprintf",
   header: "<stdio.h>", varargs, tags: [WriteIOEffect].}
 proc strlen(c: cstring): int {.
   importc: "strlen", header: "<string.h>", tags: [].}
 
+when defined(posix):
+  proc getc_unlocked(stream: File): cint {.importc: "getc_unlocked",
+    header: "<stdio.h>", tags: [ReadIOEffect].}
+
+  proc flockfile(stream: File) {.importc: "flockfile", header: "<stdio.h>",
+    tags: [ReadIOEffect].}
+
+  proc funlockfile(stream: File) {.importc: "funlockfile", header: "<stdio.h>",
+    tags: [ReadIOEffect].}
+elif false:
+  # doesn't work on Windows yet:
+  proc getc_unlocked(stream: File): cint {.importc: "_fgetc_nolock",
+    header: "<stdio.h>", tags: [ReadIOEffect].}
+
+  proc flockfile(stream: File) {.importc: "_lock_file", header: "<stdio.h>",
+    tags: [ReadIOEffect].}
+
+  proc funlockfile(stream: File) {.importc: "_unlock_file", header: "<stdio.h>",
+    tags: [ReadIOEffect].}
 
 # C routine that is used here:
 proc fread(buf: pointer, size, n: int, f: File): int {.
@@ -67,39 +86,57 @@ const
 proc raiseEIO(msg: string) {.noinline, noreturn.} =
   sysFatal(IOError, msg)
 
-proc readLine(f: File, line: var TaintedString): bool =
-  # of course this could be optimized a bit; but IO is slow anyway...
-  # and it was difficult to get this CORRECT with Ansi C's methods
-  setLen(line.string, 0) # reuse the buffer!
-  while true:
-    var c = fgetc(f)
-    if c < 0'i32:
-      if line.len > 0: break
-      else: return false
-    if c == 10'i32: break # LF
-    if c == 13'i32:  # CR
-      c = fgetc(f) # is the next char LF?
-      if c != 10'i32: ungetc(c, f) # no, put the character back
-      break
-    add line.string, chr(int(c))
-  result = true
+when declared(getc_unlocked):
+  proc readLine(f: File, line: var TaintedString): bool =
+    setLen(line.string, 0) # reuse the buffer!
+    flockfile(f)
+    while true:
+      var c = getc_unlocked(f)
+      if c < 0'i32:
+        if line.len > 0: break
+        else: return false
+      if c == 10'i32: break # LF
+      if c == 13'i32:  # CR
+        c = getc_unlocked(f) # is the next char LF?
+        if c != 10'i32: ungetc(c, f) # no, put the character back
+        break
+      add line.string, chr(int(c))
+    result = true
+    funlockfile(f)
+else:
+  proc readLine(f: File, line: var TaintedString): bool =
+    # of course this could be optimized a bit; but IO is slow anyway...
+    # and it was difficult to get this CORRECT with Ansi C's methods
+    setLen(line.string, 0) # reuse the buffer!
+    while true:
+      var c = fgetc(f)
+      if c < 0'i32:
+        if line.len > 0: break
+        else: return false
+      if c == 10'i32: break # LF
+      if c == 13'i32:  # CR
+        c = fgetc(f) # is the next char LF?
+        if c != 10'i32: ungetc(c, f) # no, put the character back
+        break
+      add line.string, chr(int(c))
+    result = true
 
 proc readLine(f: File): TaintedString =
   result = TaintedString(newStringOfCap(80))
   if not readLine(f, result): raiseEIO("EOF reached")
 
-proc write(f: File, i: int) = 
+proc write(f: File, i: int) =
   when sizeof(int) == 8:
     fprintf(f, "%lld", i)
   else:
     fprintf(f, "%ld", i)
 
-proc write(f: File, i: BiggestInt) = 
+proc write(f: File, i: BiggestInt) =
   when sizeof(BiggestInt) == 8:
     fprintf(f, "%lld", i)
   else:
     fprintf(f, "%ld", i)
-    
+
 proc write(f: File, b: bool) =
   if b: write(f, "true")
   else: write(f, "false")
@@ -110,7 +147,7 @@ proc write(f: File, c: char) = putc(c, f)
 proc write(f: File, a: varargs[string, `$`]) =
   for x in items(a): write(f, x)
 
-proc readAllBuffer(file: File): string = 
+proc readAllBuffer(file: File): string =
   # This proc is for File we want to read but don't know how many
   # bytes we need to read before the buffer is empty.
   result = ""
@@ -123,8 +160,8 @@ proc readAllBuffer(file: File): string =
       buffer.setLen(bytesRead)
       result.add(buffer)
       break
-  
-proc rawFileSize(file: File): int = 
+
+proc rawFileSize(file: File): int =
   # this does not raise an error opposed to `getFileSize`
   var oldPos = ftell(file)
   discard fseek(file, 0, 2) # seek the end of the file
@@ -132,7 +169,7 @@ proc rawFileSize(file: File): int =
   discard fseek(file, clong(oldPos), 0)
 
 proc readAllFile(file: File, len: int): string =
-  # We aquire the filesize beforehand and hope it doesn't change.
+  # We acquire the filesize beforehand and hope it doesn't change.
   # Speeds things up.
   result = newString(int(len))
   if readBuffer(file, addr(result[0]), int(len)) != len:
@@ -141,20 +178,20 @@ proc readAllFile(file: File, len: int): string =
 proc readAllFile(file: File): string =
   var len = rawFileSize(file)
   result = readAllFile(file, len)
-  
-proc readAll(file: File): TaintedString = 
+
+proc readAll(file: File): TaintedString =
   # Separate handling needed because we need to buffer when we
   # don't know the overall length of the File.
-  var len = rawFileSize(file)
-  if len >= 0:
+  let len = if file != stdin: rawFileSize(file) else: -1
+  if len > 0:
     result = readAllFile(file, len).TaintedString
   else:
     result = readAllBuffer(file).TaintedString
-  
+
 proc readFile(filename: string): TaintedString =
   var f = open(filename)
   try:
-    result = readAllFile(f).TaintedString
+    result = readAll(f).TaintedString
   finally:
     close(f)
 
@@ -183,11 +220,17 @@ proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n")
 when (defined(windows) and not defined(useWinAnsi)) or defined(nimdoc):
   include "system/widestrs"
 
-when defined(windows) and not defined(useWinAnsi):  
-  proc wfopen(filename, mode: WideCString): pointer {.
-    importc: "_wfopen", nodecl.}
-  proc wfreopen(filename, mode: WideCString, stream: File): File {.
-    importc: "_wfreopen", nodecl.}
+when defined(windows) and not defined(useWinAnsi):
+  when defined(cpp):
+    proc wfopen(filename, mode: WideCString): pointer {.
+      importcpp: "_wfopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.}
+    proc wfreopen(filename, mode: WideCString, stream: File): File {.
+      importcpp: "_wfreopen((const wchar_t*)#, (const wchar_t*)#, #)", nodecl.}
+  else:
+    proc wfopen(filename, mode: WideCString): pointer {.
+      importc: "_wfopen", nodecl.}
+    proc wfreopen(filename, mode: WideCString, stream: File): File {.
+      importc: "_wfreopen", nodecl.}
 
   proc fopen(filename, mode: cstring): pointer =
     var f = newWideCString(filename)
@@ -223,7 +266,7 @@ proc open(f: var File, filename: string,
     elif bufSize == 0:
       discard setvbuf(f, nil, IONBF, 0)
 
-proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool = 
+proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool =
   var p: pointer = freopen(filename, FormatOpen[mode], f)
   result = p != nil
 
@@ -237,23 +280,23 @@ proc open(f: var File, filehandle: FileHandle, mode: FileMode): bool =
 proc fwrite(buf: pointer, size, n: int, f: File): int {.
   importc: "fwrite", noDecl.}
 
-proc readBuffer(f: File, buffer: pointer, len: int): int =
+proc readBuffer(f: File, buffer: pointer, len: Natural): int =
   result = fread(buffer, 1, len, f)
 
-proc readBytes(f: File, a: var openArray[int8], start, len: int): int =
+proc readBytes(f: File, a: var openArray[int8|uint8], start, len: Natural): int =
   result = readBuffer(f, addr(a[start]), len)
 
-proc readChars(f: File, a: var openArray[char], start, len: int): int =
+proc readChars(f: File, a: var openArray[char], start, len: Natural): int =
   result = readBuffer(f, addr(a[start]), len)
 
 {.push stackTrace:off, profiler:off.}
-proc writeBytes(f: File, a: openArray[int8], start, len: int): int =
+proc writeBytes(f: File, a: openArray[int8|uint8], start, len: Natural): int =
   var x = cast[ptr array[0..1000_000_000, int8]](a)
   result = writeBuffer(f, addr(x[start]), len)
-proc writeChars(f: File, a: openArray[char], start, len: int): int =
+proc writeChars(f: File, a: openArray[char], start, len: Natural): int =
   var x = cast[ptr array[0..1000_000_000, int8]](a)
   result = writeBuffer(f, addr(x[start]), len)
-proc writeBuffer(f: File, buffer: pointer, len: int): int =
+proc writeBuffer(f: File, buffer: pointer, len: Natural): int =
   result = fwrite(buffer, 1, len, f)
 
 proc write(f: File, s: string) =
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index 04f30872d..6f45f1509 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 440d040a5..5b4020c8c 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -30,18 +30,30 @@ proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
   if a == b: return true
   if a == nil or b == nil: return false
   return a.len == b.len and
-    c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32
+    c_memcmp(a.data, b.data, a.len) == 0'i32
 
 when declared(allocAtomic):
   template allocStr(size: expr): expr =
     cast[NimString](allocAtomic(size))
+
+  template allocStrNoInit(size: expr): expr =
+    cast[NimString](boehmAllocAtomic(size))
 else:
   template allocStr(size: expr): expr =
     cast[NimString](newObj(addr(strDesc), size))
 
+  template allocStrNoInit(size: expr): expr =
+    cast[NimString](newObjNoInit(addr(strDesc), size))
+
+proc rawNewStringNoInit(space: int): NimString {.compilerProc.} =
+  var s = space
+  if s < 7: s = 7
+  result = allocStrNoInit(sizeof(TGenericSeq) + s + 1)
+  result.reserved = s
+
 proc rawNewString(space: int): NimString {.compilerProc.} =
   var s = space
-  if s < 8: s = 7
+  if s < 7: s = 7
   result = allocStr(sizeof(TGenericSeq) + s + 1)
   result.reserved = s
 
@@ -53,10 +65,10 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.compilerProc.} =
   var start = max(start, 0)
   var len = min(last, s.len-1) - start + 1
   if len > 0:
-    result = rawNewString(len)
+    result = rawNewStringNoInit(len)
     result.len = len
-    c_memcpy(result.data, addr(s.data[start]), len * sizeof(char))
-    #result.data[len] = '\0'
+    c_memcpy(result.data, addr(s.data[start]), len)
+    result.data[len] = '\0'
   else:
     result = rawNewString(len)
 
@@ -64,10 +76,9 @@ proc copyStr(s: NimString, start: int): NimString {.compilerProc.} =
   result = copyStrLast(s, start, s.len-1)
 
 proc toNimStr(str: cstring, len: int): NimString {.compilerProc.} =
-  result = rawNewString(len)
+  result = rawNewStringNoInit(len)
   result.len = len
-  c_memcpy(result.data, str, (len+1) * sizeof(char))
-  #result.data[len] = '\0' # readline relies on this!
+  c_memcpy(result.data, str, len + 1)
 
 proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} =
   result = toNimStr(str, c_strlen(str))
@@ -77,23 +88,24 @@ proc copyString(src: NimString): NimString {.compilerRtl.} =
     if (src.reserved and seqShallowFlag) != 0:
       result = src
     else:
-      result = rawNewString(src.space)
+      result = rawNewStringNoInit(src.len)
       result.len = src.len
-      c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
+      c_memcpy(result.data, src.data, src.len + 1)
 
 proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
   if src != nil:
-    var s = src.space
-    if s < 8: s = 7
     when declared(newObjRC1):
+      var s = src.len
+      if s < 7: s = 7
       result = cast[NimString](newObjRC1(addr(strDesc), sizeof(TGenericSeq) +
                                s+1))
+      result.reserved = s
     else:
-      result = allocStr(sizeof(TGenericSeq) + s + 1)
-    result.reserved = s
+      result = rawNewStringNoInit(src.len)
     result.len = src.len
     c_memcpy(result.data, src.data, src.len + 1)
 
+
 proc hashString(s: string): int {.compilerproc.} =
   # the compiler needs exactly the same hash function!
   # this used to be used for efficient generation of string case statements
@@ -113,7 +125,7 @@ proc addChar(s: NimString, c: char): NimString =
   if result.len >= result.space:
     result.reserved = resize(result.space)
     result = cast[NimString](growObj(result,
-      sizeof(TGenericSeq) + (result.reserved+1) * sizeof(char)))
+      sizeof(TGenericSeq) + result.reserved + 1))
   result.data[result.len] = c
   result.data[result.len+1] = '\0'
   inc(result.len)
@@ -157,7 +169,7 @@ proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
     result = cast[NimString](growObj(dest, sizeof(TGenericSeq) + sp + 1))
     result.reserved = sp
     #result = rawNewString(sp)
-    #copyMem(result, dest, dest.len * sizeof(char) + sizeof(TGenericSeq))
+    #copyMem(result, dest, dest.len + sizeof(TGenericSeq))
     # DO NOT UPDATE LEN YET: dest.len = newLen
 
 proc appendString(dest, src: NimString) {.compilerproc, inline.} =
@@ -203,12 +215,12 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
                                GenericSeqSize))
   elif newLen < result.len:
     # we need to decref here, otherwise the GC leaks!
-    when not defined(boehmGC) and not defined(nogc) and 
+    when not defined(boehmGC) and not defined(nogc) and
          not defined(gcMarkAndSweep):
       when compileOption("gc", "v2"):
         for i in newLen..result.len-1:
           let len0 = gch.tempStack.len
-          forAllChildrenAux(cast[pointer](cast[TAddress](result) +%
+          forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
                             GenericSeqSize +% (i*%elemSize)),
                             extGetCellType(result).base, waPush)
           let len1 = gch.tempStack.len
@@ -220,11 +232,11 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
           forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
                             GenericSeqSize +% (i*%elemSize)),
                             extGetCellType(result).base, waZctDecRef)
-      
+
     # XXX: zeroing out the memory can still result in crashes if a wiped-out
-    # cell is aliased by another pointer (ie proc paramter or a let variable).
+    # cell is aliased by another pointer (ie proc parameter or a let variable).
     # This is a tought problem, because even if we don't zeroMem here, in the
-    # presense of user defined destructors, the user will expect the cell to be
+    # presence of user defined destructors, the user will expect the cell to be
     # "destroyed" thus creating the same problem. We can destoy the cell in the
     # finalizer of the sequence, but this makes destruction non-deterministic.
     zeroMem(cast[pointer](cast[ByteAddress](result) +% GenericSeqSize +%
@@ -258,13 +270,23 @@ proc nimFloatToStr(f: float): string {.compilerproc.} =
     if buf[i] == ',':
       buf[i] = '.'
       hasDot = true
-    elif buf[i] in {'a'..'z', 'A'..'Z', '.'}: 
+    elif buf[i] in {'a'..'z', 'A'..'Z', '.'}:
       hasDot = true
   if not hasDot:
     buf[n] = '.'
     buf[n+1] = '0'
     buf[n+2] = '\0'
-  result = $buf
+  # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' are produced.
+  # We want to get rid of these here:
+  if buf[n-1] == 'N':
+    result = "nan"
+  elif buf[n-1] == 'F':
+    if buf[0] == '-':
+      result = "-inf"
+    else:
+      result = "inf"
+  else:
+    result = $buf
 
 proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc,
   header: "<stdlib.h>", noSideEffect.}
@@ -299,7 +321,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
   template addToBuf(c) =
     if ti < t.high:
       t[ti] = c; inc(ti)
-  
+
   # Sign?
   if s[i] == '+' or s[i] == '-':
     if s[i] == '-':
@@ -320,7 +342,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
   if s[i] == 'I' or s[i] == 'i':
     if s[i+1] == 'N' or s[i+1] == 'n':
       if s[i+2] == 'F' or s[i+2] == 'f':
-        if s[i+3] notin IdentChars: 
+        if s[i+3] notin IdentChars:
           number = Inf*sign
           return i+3 - start
     return 0
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 496c31af1..d8e011ecb 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -84,8 +84,18 @@ when defined(windows):
       importc: "TlsAlloc", stdcall, header: "<windows.h>".}
     proc threadVarSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
       importc: "TlsSetValue", stdcall, header: "<windows.h>".}
-    proc threadVarGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
+    proc tlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
       importc: "TlsGetValue", stdcall, header: "<windows.h>".}
+
+    proc getLastError(): uint32 {.
+      importc: "GetLastError", stdcall, header: "<windows.h>".}
+    proc setLastError(x: uint32) {.
+      importc: "SetLastError", stdcall, header: "<windows.h>".}
+
+    proc threadVarGetValue(dwTlsIndex: TThreadVarSlot): pointer =
+      let realLastError = getLastError()
+      result = tlsGetValue(dwTlsIndex)
+      setLastError(realLastError)
   else:
     proc threadVarAlloc(): TThreadVarSlot {.
       importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
@@ -95,7 +105,9 @@ when defined(windows):
       importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
   
 else:
-  {.passL: "-pthread".}
+  when not defined(macosx):
+    {.passL: "-pthread".}
+
   {.passC: "-pthread".}
 
   type
@@ -115,7 +127,7 @@ else:
     importc, header: "<pthread.h>".}
 
   proc pthread_create(a1: var TSysThread, a2: var TPthread_attr,
-            a3: proc (x: pointer) {.noconv.}, 
+            a3: proc (x: pointer): pointer {.noconv.}, 
             a4: pointer): cint {.importc: "pthread_create", 
             header: "<pthread.h>".}
   proc pthread_join(a1: TSysThread, a2: ptr pointer): cint {.
@@ -303,7 +315,7 @@ when defined(windows):
     threadProcWrapperBody(closure)
     # implicitly return 0
 else:
-  proc threadProcWrapper[TArg](closure: pointer) {.noconv.} = 
+  proc threadProcWrapper[TArg](closure: pointer): pointer {.noconv.} = 
     threadProcWrapperBody(closure)
 {.pop.}
 
diff --git a/lib/system/timers.nim b/lib/system/timers.nim
index e58ff7adc..e5de791ac 100644
--- a/lib/system/timers.nim
+++ b/lib/system/timers.nim
@@ -27,9 +27,9 @@ when defined(windows):
   proc `-`(a, b: TTicks): TNanos =
     var frequency: int64
     QueryPerformanceFrequency(frequency)
-    var performanceCounterRate = 1000000000.0 / toFloat(frequency.int)
+    var performanceCounterRate = 1e+9'f64 / float64(frequency)
 
-    result = ((a.int64 - b.int64).int.toFloat * performanceCounterRate).TNanos
+    result = TNanos(float64(a.int64 - b.int64) * performanceCounterRate)
 
 elif defined(macosx):
   type
diff --git a/lib/windows/windows.nim b/lib/windows/windows.nim
index f0895217b..b76dea6c5 100644
--- a/lib/windows/windows.nim
+++ b/lib/windows/windows.nim
@@ -11,7 +11,7 @@
 ## Unicode version.

 

 {.deadCodeElim: on.}

-

+{.push gcsafe.}

 type

   WideChar* = uint16

   PWideChar* = ptr uint16

@@ -11616,7 +11616,7 @@ type
     dwPageSize*: DWORD

     lpMinimumApplicationAddress*: LPVOID

     lpMaximumApplicationAddress*: LPVOID

-    dwActiveProcessorMask*: DWORD

+    dwActiveProcessorMask*: DWORD_PTR

     dwNumberOfProcessors*: DWORD

     dwProcessorType*: DWORD

     dwAllocationGranularity*: DWORD

@@ -23481,7 +23481,7 @@ proc ListView_EnsureVisible(hwndLV: HWND, i, fPartialOK: int32): LRESULT =
                        MAKELPARAM(fPartialOK, 0))

 

 proc ListView_FindItem(wnd: HWND, iStart: int32, lvfi: var LV_FINDINFO): int32 =

-  result = SendMessage(wnd, LVM_FINDITEM, WPARAM(iStart), 

+  result = SendMessage(wnd, LVM_FINDITEM, WPARAM(iStart),

                        cast[LPARAM](addr(lvfi))).int32

 

 proc ListView_GetBkColor(wnd: HWND): LRESULT =

@@ -23615,9 +23615,9 @@ proc ListView_SetTextBkColor(wnd: HWND, clrTextBk: COLORREF): LRESULT =
 proc ListView_SetTextColor(wnd: HWND, clrText: COLORREF): LRESULT =

   result = SendMessage(wnd, LVM_SETTEXTCOLOR, 0, LPARAM(clrText))

 

-proc ListView_SortItems(hwndLV: HWND, pfnCompare: PFNLVCOMPARE, 

+proc ListView_SortItems(hwndLV: HWND, pfnCompare: PFNLVCOMPARE,

                         lPrm: LPARAM): LRESULT =

-  result = SendMessage(hwndLV, LVM_SORTITEMS, WPARAM(lPrm), 

+  result = SendMessage(hwndLV, LVM_SORTITEMS, WPARAM(lPrm),

                        cast[LPARAM](pfnCompare))

 

 proc ListView_Update(hwndLV: HWND, i: int32): LRESULT =

@@ -23924,3 +23924,5 @@ proc LOCALE_NEUTRAL(): DWORD =
 

 proc LOCALE_INVARIANT(): DWORD =

   result = MAKELCID(MAKELANGID(toU16(LANG_INVARIANT), SUBLANG_NEUTRAL), SORT_DEFAULT)

+

+{.pop.}

diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 76d17bc4a..584f7cf48 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -284,6 +284,10 @@ when useWinUnicode:
                  bFailIfExists: cint): cint {.
     importc: "CopyFileW", stdcall, dynlib: "kernel32".}
 
+  proc moveFileW*(lpExistingFileName, lpNewFileName: WideCString,
+                 bFailIfExists: cint): cint {.
+    importc: "MoveFileW", stdcall, dynlib: "kernel32".}
+
   proc getEnvironmentStringsW*(): WideCString {.
     stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsW".}
   proc freeEnvironmentStringsW*(para1: WideCString): int32 {.
@@ -308,6 +312,10 @@ else:
                  bFailIfExists: cint): cint {.
     importc: "CopyFileA", stdcall, dynlib: "kernel32".}
 
+  proc moveFileA*(lpExistingFileName, lpNewFileName: cstring,
+                 bFailIfExists: cint): cint {.
+    importc: "MoveFileA", stdcall, dynlib: "kernel32".}
+
   proc getEnvironmentStringsA*(): cstring {.
     stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsA".}
   proc freeEnvironmentStringsA*(para1: cstring): int32 {.
@@ -368,32 +376,32 @@ type
 {.deprecated: [TSocketHandle: SocketHandle].}
 
 type
-  WSAData* {.importc: "WSADATA", header: "Winsock2.h".} = object 
+  WSAData* {.importc: "WSADATA", header: "winsock2.h".} = object 
     wVersion, wHighVersion: int16
     szDescription: array[0..WSADESCRIPTION_LEN, char]
     szSystemStatus: array[0..WSASYS_STATUS_LEN, char]
     iMaxSockets, iMaxUdpDg: int16
     lpVendorInfo: cstring
     
-  SockAddr* {.importc: "SOCKADDR", header: "Winsock2.h".} = object 
+  SockAddr* {.importc: "SOCKADDR", header: "winsock2.h".} = object 
     sa_family*: int16 # unsigned
     sa_data: array[0..13, char]
 
-  InAddr* {.importc: "IN_ADDR", header: "Winsock2.h".} = object
+  InAddr* {.importc: "IN_ADDR", header: "winsock2.h".} = object
     s_addr*: int32  # IP address
   
   Sockaddr_in* {.importc: "SOCKADDR_IN", 
-                  header: "Winsock2.h".} = object
+                  header: "winsock2.h".} = object
     sin_family*: int16
     sin_port*: int16 # unsigned
     sin_addr*: InAddr
     sin_zero*: array[0..7, char]
 
-  In6_addr* {.importc: "IN6_ADDR", header: "Winsock2.h".} = object 
+  In6_addr* {.importc: "IN6_ADDR", header: "winsock2.h".} = object 
     bytes*: array[0..15, char]
 
   Sockaddr_in6* {.importc: "SOCKADDR_IN6", 
-                   header: "Winsock2.h".} = object
+                   header: "winsock2.h".} = object
     sin6_family*: int16
     sin6_port*: int16 # unsigned
     sin6_flowinfo*: int32 # unsigned
@@ -450,22 +458,22 @@ type
 
 
 var
-  SOMAXCONN* {.importc, header: "Winsock2.h".}: cint
-  INVALID_SOCKET* {.importc, header: "Winsock2.h".}: SocketHandle
-  SOL_SOCKET* {.importc, header: "Winsock2.h".}: cint
-  SO_DEBUG* {.importc, header: "Winsock2.h".}: cint ## turn on debugging info recording
-  SO_ACCEPTCONN* {.importc, header: "Winsock2.h".}: cint # socket has had listen()
-  SO_REUSEADDR* {.importc, header: "Winsock2.h".}: cint # allow local address reuse
-  SO_KEEPALIVE* {.importc, header: "Winsock2.h".}: cint # keep connections alive
-  SO_DONTROUTE* {.importc, header: "Winsock2.h".}: cint # just use interface addresses
-  SO_BROADCAST* {.importc, header: "Winsock2.h".}: cint # permit sending of broadcast msgs
-  SO_USELOOPBACK* {.importc, header: "Winsock2.h".}: cint # bypass hardware when possible
-  SO_LINGER* {.importc, header: "Winsock2.h".}: cint # linger on close if data present
-  SO_OOBINLINE* {.importc, header: "Winsock2.h".}: cint # leave received OOB data in line
-
-  SO_DONTLINGER* {.importc, header: "Winsock2.h".}: cint
-  SO_EXCLUSIVEADDRUSE* {.importc, header: "Winsock2.h".}: cint # disallow local address reuse
-  SO_ERROR* {.importc, header: "Winsock2.h".}: cint
+  SOMAXCONN* {.importc, header: "winsock2.h".}: cint
+  INVALID_SOCKET* {.importc, header: "winsock2.h".}: SocketHandle
+  SOL_SOCKET* {.importc, header: "winsock2.h".}: cint
+  SO_DEBUG* {.importc, header: "winsock2.h".}: cint ## turn on debugging info recording
+  SO_ACCEPTCONN* {.importc, header: "winsock2.h".}: cint # socket has had listen()
+  SO_REUSEADDR* {.importc, header: "winsock2.h".}: cint # allow local address reuse
+  SO_KEEPALIVE* {.importc, header: "winsock2.h".}: cint # keep connections alive
+  SO_DONTROUTE* {.importc, header: "winsock2.h".}: cint # just use interface addresses
+  SO_BROADCAST* {.importc, header: "winsock2.h".}: cint # permit sending of broadcast msgs
+  SO_USELOOPBACK* {.importc, header: "winsock2.h".}: cint # bypass hardware when possible
+  SO_LINGER* {.importc, header: "winsock2.h".}: cint # linger on close if data present
+  SO_OOBINLINE* {.importc, header: "winsock2.h".}: cint # leave received OOB data in line
+
+  SO_DONTLINGER* {.importc, header: "winsock2.h".}: cint
+  SO_EXCLUSIVEADDRUSE* {.importc, header: "winsock2.h".}: cint # disallow local address reuse
+  SO_ERROR* {.importc, header: "winsock2.h".}: cint
 
 proc `==`*(x, y: SocketHandle): bool {.borrow.}
 
diff --git a/lib/wrappers/claro.nim b/lib/wrappers/claro.nim
index fb06da818..0fb0882bf 100644
--- a/lib/wrappers/claro.nim
+++ b/lib/wrappers/claro.nim
@@ -64,7 +64,7 @@ proc node_move*(n: ptr TNode, oldlist: ptr TList, newlist: ptr TList){.
     cdecl, importc: "node_move", dynlib: clarodll.}

 

 type 

-  TClaroObj*{.pure.} = object 

+  TClaroObj*{.pure, inheritable.} = object 

     typ*: array[0..64 - 1, char]

     destroy_pending*: cint

     event_handlers*: TList

@@ -86,7 +86,7 @@ type
   TEventHandler*{.pure.} = object 

     typ*: array[0..32 - 1, char]

     data*: pointer

-    func*: TEventFunc   # the function that handles this event 

+    fun*: TEventFunc   # the function that handles this event 

   

 

 # #define event_handler(n) void n ( TClaroObj *object, event_t *event )

@@ -121,10 +121,10 @@ proc object_set_parent*(obj: ptr TClaroObj, parent: ptr TClaroObj){.cdecl,
 # event functions 

 

 proc object_addhandler*(obj: ptr TClaroObj, event: cstring, 

-                        func: TEventFunc){.cdecl, 

+                        fun: TEventFunc){.cdecl, 

     importc: "object_addhandler", dynlib: clarodll.}

 proc object_addhandler_interface*(obj: ptr TClaroObj, event: cstring, 

-                                  func: TEventFunc, data: pointer){.cdecl, 

+                                  fun: TEventFunc, data: pointer){.cdecl, 

     importc: "object_addhandler_interface", dynlib: clarodll.}

 proc event_send*(obj: ptr TClaroObj, event: cstring, fmt: cstring): cint{.

     varargs, cdecl, importc: "event_send", dynlib: clarodll.}

@@ -258,7 +258,7 @@ proc image_load_inline_png*(parent: ptr TClaroObj, data: cstring,
   ##  len size of data

 

 when true:

-  nil

+  discard

 else:

   # status icons are not supported on all platforms yet:

   type 

@@ -682,7 +682,7 @@ const
 type 

   TCanvas*{.pure.} = object of TWidget

     surface*: cairo.PSurface

-    cr*: Cairo.PContext

+    cr*: cairo.PContext

     surfdata*: pointer

     fontdata*: pointer

     font_height*: cint

@@ -854,7 +854,7 @@ proc canvas_cairo_buffered_text_display_count*(widget: ptr TCanvas,
     text: cstring, width: cint): cint{.cdecl, 

     importc: "canvas_cairo_buffered_text_display_count", 

     dynlib: clarodll.}

-proc canvas_get_cairo_context*(widget: ptr TCanvas): Cairo.PContext {.cdecl, 

+proc canvas_get_cairo_context*(widget: ptr TCanvas): cairo.PContext {.cdecl, 

     importc: "canvas_get_cairo_context", dynlib: clarodll.}

 

 type 

@@ -2710,7 +2710,7 @@ proc workspace_window_set_icon*(w: ptr TWorkspaceWindow, icon: ptr TImage){.
 claro_base_init()

 claro_graphics_init()

 

-when isMainModule:

+when not defined(testing) and isMainModule:

   var w = newWindow(nil, newBounds(100, 100, 230, 230), 0)

   window_set_title(w, "Hello, World!")

 

diff --git a/lib/wrappers/iup.nim b/lib/wrappers/iup.nim
index 27ab7d870..93e14cccd 100644
--- a/lib/wrappers/iup.nim
+++ b/lib/wrappers/iup.nim
@@ -1,13 +1,13 @@
 #
 #    Binding for the IUP GUI toolkit
-#       (c) 2012 Andreas Rumpf 
+#       (c) 2012 Andreas Rumpf
 #    C header files translated by hand
 #    Licence of IUP follows:
 
 
 # ****************************************************************************
 # Copyright (C) 1994-2009 Tecgraf, PUC-Rio.
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
 # "Software"), to deal in the Software without restriction, including
@@ -30,12 +30,12 @@
 
 {.deadCodeElim: on.}
 
-when defined(windows): 
-  const dllname = "iup(30|27|26|25|24).dll"
+when defined(windows):
+  const dllname = "iup(|30|27|26|25|24).dll"
 elif defined(macosx):
-  const dllname = "libiup(3.0|2.7|2.6|2.5|2.4).dylib"
-else: 
-  const dllname = "libiup(3.0|2.7|2.6|2.5|2.4).so.1"
+  const dllname = "libiup(|3.0|2.7|2.6|2.5|2.4).dylib"
+else:
+  const dllname = "libiup(|3.0|2.7|2.6|2.5|2.4).so(|.1)"
 
 const
   IUP_NAME* = "IUP - Portable User Interface"
@@ -67,8 +67,8 @@ proc alarm*(title, msg, b1, b2, b3: cstring): cint {.
   importc: "IupAlarm", dynlib: dllname, cdecl.}
 proc scanf*(format: cstring): cint {.
   importc: "IupScanf", dynlib: dllname, cdecl, varargs.}
-proc listDialog*(theType: cint, title: cstring, size: cint, 
-                 list: cstringArray, op, maxCol, maxLin: cint, 
+proc listDialog*(theType: cint, title: cstring, size: cint,
+                 list: cstringArray, op, maxCol, maxLin: cint,
                  marks: ptr cint): cint {.
                  importc: "IupListDialog", dynlib: dllname, cdecl.}
 proc getText*(title, text: cstring): cint {.
@@ -77,14 +77,14 @@ proc getColor*(x, y: cint, r, g, b: var byte): cint {.
   importc: "IupGetColor", dynlib: dllname, cdecl.}
 
 type
-  Iparamcb* = proc (dialog: PIhandle, paramIndex: cint, 
+  Iparamcb* = proc (dialog: PIhandle, paramIndex: cint,
                     userData: pointer): cint {.cdecl.}
 
-proc getParam*(title: cstring, action: Iparamcb, userData: pointer, 
+proc getParam*(title: cstring, action: Iparamcb, userData: pointer,
                format: cstring): cint {.
                importc: "IupGetParam", cdecl, varargs, dynlib: dllname.}
-proc getParamv*(title: cstring, action: Iparamcb, userData: pointer, 
-                format: cstring, paramCount, paramExtra: cint, 
+proc getParamv*(title: cstring, action: Iparamcb, userData: pointer,
+                format: cstring, paramCount, paramExtra: cint,
                 paramData: pointer): cint {.
                 importc: "IupGetParamv", cdecl, dynlib: dllname.}
 
@@ -96,11 +96,11 @@ proc open*(argc: ptr cint, argv: ptr cstringArray): cint {.
 proc close*() {.importc: "IupClose", cdecl, dynlib: dllname.}
 proc imageLibOpen*() {.importc: "IupImageLibOpen", cdecl, dynlib: dllname.}
 
-proc mainLoop*(): cint {.importc: "IupMainLoop", cdecl, dynlib: dllname, 
+proc mainLoop*(): cint {.importc: "IupMainLoop", cdecl, dynlib: dllname,
                          discardable.}
 proc loopStep*(): cint {.importc: "IupLoopStep", cdecl, dynlib: dllname,
                          discardable.}
-proc mainLoopLevel*(): cint {.importc: "IupMainLoopLevel", cdecl, 
+proc mainLoopLevel*(): cint {.importc: "IupMainLoopLevel", cdecl,
                               dynlib: dllname, discardable.}
 proc flush*() {.importc: "IupFlush", cdecl, dynlib: dllname.}
 proc exitLoop*() {.importc: "IupExitLoop", cdecl, dynlib: dllname.}
@@ -204,7 +204,7 @@ proc getCallback*(ih: PIhandle, name: cstring): Icallback {.
   importc: "IupGetCallback", cdecl, dynlib: dllname.}
 proc setCallback*(ih: PIhandle, name: cstring, fn: Icallback): Icallback {.
   importc: "IupSetCallback", cdecl, dynlib: dllname, discardable.}
-  
+
 proc setCallbacks*(ih: PIhandle, name: cstring, fn: Icallback): PIhandle {.
   importc: "IupSetCallbacks", cdecl, dynlib: dllname, varargs, discardable.}
 
@@ -235,7 +235,7 @@ proc getClassName*(ih: PIhandle): cstring {.
   importc: "IupGetClassName", cdecl, dynlib: dllname.}
 proc getClassType*(ih: PIhandle): cstring {.
   importc: "IupGetClassType", cdecl, dynlib: dllname.}
-proc getClassAttributes*(classname: cstring, names: cstringArray, 
+proc getClassAttributes*(classname: cstring, names: cstringArray,
                          n: cint): cint {.
   importc: "IupGetClassAttributes", cdecl, dynlib: dllname.}
 proc saveClassAttributes*(ih: PIhandle) {.
@@ -378,12 +378,12 @@ const
   IUP_CONTINUE* = cint(-4)
 
   # IupPopup and IupShowXY Parameter Values
-  IUP_CENTER* = cint(0xFFFF) 
-  IUP_LEFT* = cint(0xFFFE) 
-  IUP_RIGHT* = cint(0xFFFD) 
-  IUP_MOUSEPOS* = cint(0xFFFC) 
-  IUP_CURRENT* = cint(0xFFFB) 
-  IUP_CENTERPARENT* = cint(0xFFFA) 
+  IUP_CENTER* = cint(0xFFFF)
+  IUP_LEFT* = cint(0xFFFE)
+  IUP_RIGHT* = cint(0xFFFD)
+  IUP_MOUSEPOS* = cint(0xFFFC)
+  IUP_CURRENT* = cint(0xFFFB)
+  IUP_CENTERPARENT* = cint(0xFFFA)
   IUP_TOP* = IUP_LEFT
   IUP_BOTTOM* = IUP_RIGHT
 
@@ -397,10 +397,10 @@ const
   # SCROLL_CB Callback Values
   IUP_SBUP* = cint(0)
   IUP_SBDN* = cint(1)
-  IUP_SBPGUP* = cint(2)   
+  IUP_SBPGUP* = cint(2)
   IUP_SBPGDN* = cint(3)
   IUP_SBPOSV* = cint(4)
-  IUP_SBDRAGV* = cint(5) 
+  IUP_SBDRAGV* = cint(5)
   IUP_SBLEFT* = cint(6)
   IUP_SBRIGHT* = cint(7)
   IUP_SBPGLEFT* = cint(8)
@@ -433,12 +433,12 @@ const
   IUP_MASK_EFLOAT* = "[+/-]?(/d+/.?/d*|/./d+)([eE][+/-]?/d+)?"
   IUP_MASK_INT* = "[+/-]?/d+"
   IUP_MASK_UINT* = "/d+"
-  
+
 # from 32 to 126, all character sets are equal,
 # the key code i the same as the character code.
 const
   K_SP* = cint(ord(' '))
-  K_exclam* = cint(ord('!'))   
+  K_exclam* = cint(ord('!'))
   K_quotedbl* = cint(ord('\"'))
   K_numbersign* = cint(ord('#'))
   K_dollar* = cint(ord('$'))
@@ -467,51 +467,51 @@ const
   K_semicolon* = cint(ord(';'))
   K_less* = cint(ord('<'))
   K_equal* = cint(ord('='))
-  K_greater* = cint(ord('>'))   
-  K_question* = cint(ord('?'))   
-  K_at* = cint(ord('@'))   
-  K_upperA* = cint(ord('A'))   
-  K_upperB* = cint(ord('B'))   
-  K_upperC* = cint(ord('C'))   
-  K_upperD* = cint(ord('D'))   
-  K_upperE* = cint(ord('E'))   
-  K_upperF* = cint(ord('F'))   
-  K_upperG* = cint(ord('G'))   
-  K_upperH* = cint(ord('H'))   
-  K_upperI* = cint(ord('I'))   
-  K_upperJ* = cint(ord('J'))   
-  K_upperK* = cint(ord('K'))   
-  K_upperL* = cint(ord('L'))   
-  K_upperM* = cint(ord('M'))   
-  K_upperN* = cint(ord('N'))   
-  K_upperO* = cint(ord('O'))   
-  K_upperP* = cint(ord('P'))   
-  K_upperQ* = cint(ord('Q'))  
-  K_upperR* = cint(ord('R'))  
-  K_upperS* = cint(ord('S'))  
-  K_upperT* = cint(ord('T'))  
-  K_upperU* = cint(ord('U'))  
-  K_upperV* = cint(ord('V')) 
-  K_upperW* = cint(ord('W')) 
-  K_upperX* = cint(ord('X'))  
-  K_upperY* = cint(ord('Y'))  
-  K_upperZ* = cint(ord('Z'))  
-  K_bracketleft* = cint(ord('[')) 
-  K_backslash* = cint(ord('\\'))  
-  K_bracketright* = cint(ord(']'))  
-  K_circum* = cint(ord('^'))   
-  K_underscore* = cint(ord('_'))   
-  K_grave* = cint(ord('`'))   
-  K_lowera* = cint(ord('a'))  
-  K_lowerb* = cint(ord('b'))   
-  K_lowerc* = cint(ord('c')) 
-  K_lowerd* = cint(ord('d'))   
-  K_lowere* = cint(ord('e'))   
-  K_lowerf* = cint(ord('f'))  
+  K_greater* = cint(ord('>'))
+  K_question* = cint(ord('?'))
+  K_at* = cint(ord('@'))
+  K_upperA* = cint(ord('A'))
+  K_upperB* = cint(ord('B'))
+  K_upperC* = cint(ord('C'))
+  K_upperD* = cint(ord('D'))
+  K_upperE* = cint(ord('E'))
+  K_upperF* = cint(ord('F'))
+  K_upperG* = cint(ord('G'))
+  K_upperH* = cint(ord('H'))
+  K_upperI* = cint(ord('I'))
+  K_upperJ* = cint(ord('J'))
+  K_upperK* = cint(ord('K'))
+  K_upperL* = cint(ord('L'))
+  K_upperM* = cint(ord('M'))
+  K_upperN* = cint(ord('N'))
+  K_upperO* = cint(ord('O'))
+  K_upperP* = cint(ord('P'))
+  K_upperQ* = cint(ord('Q'))
+  K_upperR* = cint(ord('R'))
+  K_upperS* = cint(ord('S'))
+  K_upperT* = cint(ord('T'))
+  K_upperU* = cint(ord('U'))
+  K_upperV* = cint(ord('V'))
+  K_upperW* = cint(ord('W'))
+  K_upperX* = cint(ord('X'))
+  K_upperY* = cint(ord('Y'))
+  K_upperZ* = cint(ord('Z'))
+  K_bracketleft* = cint(ord('['))
+  K_backslash* = cint(ord('\\'))
+  K_bracketright* = cint(ord(']'))
+  K_circum* = cint(ord('^'))
+  K_underscore* = cint(ord('_'))
+  K_grave* = cint(ord('`'))
+  K_lowera* = cint(ord('a'))
+  K_lowerb* = cint(ord('b'))
+  K_lowerc* = cint(ord('c'))
+  K_lowerd* = cint(ord('d'))
+  K_lowere* = cint(ord('e'))
+  K_lowerf* = cint(ord('f'))
   K_lowerg* = cint(ord('g'))
-  K_lowerh* = cint(ord('h')) 
-  K_loweri* = cint(ord('i')) 
-  K_lowerj* = cint(ord('j')) 
+  K_lowerh* = cint(ord('h'))
+  K_loweri* = cint(ord('i'))
+  K_lowerj* = cint(ord('j'))
   K_lowerk* = cint(ord('k'))
   K_lowerl* = cint(ord('l'))
   K_lowerm* = cint(ord('m'))
@@ -553,19 +553,19 @@ proc isAltXkey*(c: cint): bool = return c > 768 and c < 1024
 proc isSysXkey*(c: cint): bool = return c > 1024 and c < 1280
 
 proc iUPxCODE*(c: cint): cint = return c + cint(128) # Normal (must be above 128)
-proc iUPsxCODE*(c: cint): cint = 
+proc iUPsxCODE*(c: cint): cint =
   return c + cint(256)
-  # Shift (must have range to include the standard keys and the normal 
+  # Shift (must have range to include the standard keys and the normal
   # extended keys, so must be above 256
 
 proc iUPcxCODE*(c: cint): cint = return c + cint(512) # Ctrl
 proc iUPmxCODE*(c: cint): cint = return c + cint(768) # Alt
-proc iUPyxCODE*(c: cint): cint = return c + cint(1024) # Sys (Win or Apple) 
+proc iUPyxCODE*(c: cint): cint = return c + cint(1024) # Sys (Win or Apple)
 
 const
   IUP_NUMMAXCODES* = 1280 ## 5*256=1280  Normal+Shift+Ctrl+Alt+Sys
 
-  K_HOME* = iUPxCODE(1)                
+  K_HOME* = iUPxCODE(1)
   K_UP* = iUPxCODE(2)
   K_PGUP* = iUPxCODE(3)
   K_LEFT* = iUPxCODE(4)
@@ -574,8 +574,8 @@ const
   K_END* = iUPxCODE(7)
   K_DOWN* = iUPxCODE(8)
   K_PGDN* = iUPxCODE(9)
-  K_INS* = iUPxCODE(10)    
-  K_DEL* = iUPxCODE(11)    
+  K_INS* = iUPxCODE(10)
+  K_DEL* = iUPxCODE(11)
   K_PAUSE* = iUPxCODE(12)
   K_ESC* = iUPxCODE(13)
   K_ccedilla* = iUPxCODE(14)
@@ -728,13 +728,13 @@ const
   K_yPrint* = iUPyxCODE(K_Print)
   K_yMenu* = iUPyxCODE(K_Menu)
 
-  K_sPlus* = iUPsxCODE(K_plus)   
-  K_sComma* = iUPsxCODE(K_comma)   
-  K_sMinus* = iUPsxCODE(K_minus)   
-  K_sPeriod* = iUPsxCODE(K_period)   
-  K_sSlash* = iUPsxCODE(K_slash)   
+  K_sPlus* = iUPsxCODE(K_plus)
+  K_sComma* = iUPsxCODE(K_comma)
+  K_sMinus* = iUPsxCODE(K_minus)
+  K_sPeriod* = iUPsxCODE(K_period)
+  K_sSlash* = iUPsxCODE(K_slash)
   K_sAsterisk* = iUPsxCODE(K_asterisk)
-                        
+
   K_cupperA* = iUPcxCODE(K_upperA)
   K_cupperB* = iUPcxCODE(K_upperB)
   K_cupperC* = iUPcxCODE(K_upperC)
@@ -767,16 +767,16 @@ const
   K_c4* = iUPcxCODE(K_4)
   K_c5* = iUPcxCODE(K_5)
   K_c6* = iUPcxCODE(K_6)
-  K_c7* = iUPcxCODE(K_7)        
-  K_c8* = iUPcxCODE(K_8)         
+  K_c7* = iUPcxCODE(K_7)
+  K_c8* = iUPcxCODE(K_8)
   K_c9* = iUPcxCODE(K_9)
   K_c0* = iUPcxCODE(K_0)
-  K_cPlus* = iUPcxCODE(K_plus)   
-  K_cComma* = iUPcxCODE(K_comma)   
-  K_cMinus* = iUPcxCODE(K_minus)   
-  K_cPeriod* = iUPcxCODE(K_period)   
-  K_cSlash* = iUPcxCODE(K_slash)   
-  K_cSemicolon* = iUPcxCODE(K_semicolon) 
+  K_cPlus* = iUPcxCODE(K_plus)
+  K_cComma* = iUPcxCODE(K_comma)
+  K_cMinus* = iUPcxCODE(K_minus)
+  K_cPeriod* = iUPcxCODE(K_period)
+  K_cSlash* = iUPcxCODE(K_slash)
+  K_cSemicolon* = iUPcxCODE(K_semicolon)
   K_cEqual* = iUPcxCODE(K_equal)
   K_cBracketleft* = iUPcxCODE(K_bracketleft)
   K_cBracketright* = iUPcxCODE(K_bracketright)
@@ -815,16 +815,16 @@ const
   K_m4* = iUPmxCODE(K_4)
   K_m5* = iUPmxCODE(K_5)
   K_m6* = iUPmxCODE(K_6)
-  K_m7* = iUPmxCODE(K_7)        
-  K_m8* = iUPmxCODE(K_8)         
+  K_m7* = iUPmxCODE(K_7)
+  K_m8* = iUPmxCODE(K_8)
   K_m9* = iUPmxCODE(K_9)
   K_m0* = iUPmxCODE(K_0)
-  K_mPlus* = iUPmxCODE(K_plus)   
-  K_mComma* = iUPmxCODE(K_comma)   
-  K_mMinus* = iUPmxCODE(K_minus)   
-  K_mPeriod* = iUPmxCODE(K_period)   
-  K_mSlash* = iUPmxCODE(K_slash)   
-  K_mSemicolon* = iUPmxCODE(K_semicolon) 
+  K_mPlus* = iUPmxCODE(K_plus)
+  K_mComma* = iUPmxCODE(K_comma)
+  K_mMinus* = iUPmxCODE(K_minus)
+  K_mPeriod* = iUPmxCODE(K_period)
+  K_mSlash* = iUPmxCODE(K_slash)
+  K_mSemicolon* = iUPmxCODE(K_semicolon)
   K_mEqual* = iUPmxCODE(K_equal)
   K_mBracketleft* = iUPmxCODE(K_bracketleft)
   K_mBracketright* = iUPmxCODE(K_bracketright)
@@ -863,16 +863,16 @@ const
   K_y4* = iUPyxCODE(K_4)
   K_y5* = iUPyxCODE(K_5)
   K_y6* = iUPyxCODE(K_6)
-  K_y7* = iUPyxCODE(K_7)        
-  K_y8* = iUPyxCODE(K_8)         
+  K_y7* = iUPyxCODE(K_7)
+  K_y8* = iUPyxCODE(K_8)
   K_y9* = iUPyxCODE(K_9)
   K_y0* = iUPyxCODE(K_0)
   K_yPlus* = iUPyxCODE(K_plus)
   K_yComma* = iUPyxCODE(K_comma)
-  K_yMinus* = iUPyxCODE(K_minus)   
-  K_yPeriod* = iUPyxCODE(K_period)   
-  K_ySlash* = iUPyxCODE(K_slash)   
-  K_ySemicolon* = iUPyxCODE(K_semicolon) 
+  K_yMinus* = iUPyxCODE(K_minus)
+  K_yPeriod* = iUPyxCODE(K_period)
+  K_ySlash* = iUPyxCODE(K_slash)
+  K_ySemicolon* = iUPyxCODE(K_semicolon)
   K_yEqual* = iUPyxCODE(K_equal)
   K_yBracketleft* = iUPyxCODE(K_bracketleft)
   K_yBracketright* = iUPyxCODE(K_bracketright)
@@ -893,11 +893,11 @@ proc dial*(theType: cstring): PIhandle {.cdecl, importc: "IupDial", dynlib: dlln
 proc matrix*(action: cstring): PIhandle {.cdecl, importc: "IupMatrix", dynlib: dllname.}
 
 # IupMatrix utilities
-proc matSetAttribute*(ih: PIhandle, name: cstring, lin, col: cint, 
+proc matSetAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
                       value: cstring) {.
                       cdecl, importc: "IupMatSetAttribute", dynlib: dllname.}
-proc matStoreAttribute*(ih: PIhandle, name: cstring, lin, col: cint, 
-                        value: cstring) {.cdecl, 
+proc matStoreAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
+                        value: cstring) {.cdecl,
                         importc: "IupMatStoreAttribute", dynlib: dllname.}
 proc matGetAttribute*(ih: PIhandle, name: cstring, lin, col: cint): cstring {.
   cdecl, importc: "IupMatGetAttribute", dynlib: dllname.}
@@ -905,9 +905,9 @@ proc matGetInt*(ih: PIhandle, name: cstring, lin, col: cint): cint {.
   cdecl, importc: "IupMatGetInt", dynlib: dllname.}
 proc matGetFloat*(ih: PIhandle, name: cstring, lin, col: cint): cfloat {.
   cdecl, importc: "IupMatGetFloat", dynlib: dllname.}
-proc matSetfAttribute*(ih: PIhandle, name: cstring, lin, col: cint, 
-                       format: cstring) {.cdecl, 
-                       importc: "IupMatSetfAttribute", 
+proc matSetfAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
+                       format: cstring) {.cdecl,
+                       importc: "IupMatSetfAttribute",
                        dynlib: dllname, varargs.}
 
 # Used by IupColorbar
@@ -931,10 +931,10 @@ proc pPlotAddStr*(ih: PIhandle, x: cstring, y: cfloat) {.
 proc pPlotEnd*(ih: PIhandle): cint {.
   cdecl, importc: "IupPPlotEnd", dynlib: dllname.}
 
-proc pPlotInsertStr*(ih: PIhandle, index, sampleIndex: cint, x: cstring, 
-                     y: cfloat) {.cdecl, importc: "IupPPlotInsertStr", 
+proc pPlotInsertStr*(ih: PIhandle, index, sampleIndex: cint, x: cstring,
+                     y: cfloat) {.cdecl, importc: "IupPPlotInsertStr",
                      dynlib: dllname.}
-proc pPlotInsert*(ih: PIhandle, index, sampleIndex: cint, 
+proc pPlotInsert*(ih: PIhandle, index, sampleIndex: cint,
                   x, y: cfloat) {.
                   cdecl, importc: "IupPPlotInsert", dynlib: dllname.}
 
diff --git a/lib/wrappers/libffi/msvc/win32.c b/lib/wrappers/libffi/msvc/win32.c
index d1149a85e..2754fd35d 100644
--- a/lib/wrappers/libffi/msvc/win32.c
+++ b/lib/wrappers/libffi/msvc/win32.c
@@ -90,7 +90,7 @@ noclean:
 
 // If the return value pointer is NULL, assume no return value.
 /*
-  Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction,
+  Intel asm is weird. We have to explicitly specify 'DWORD PTR' in the nexr instruction,
   otherwise only one BYTE will be compared (instead of a DWORD)!
  */
 		cmp DWORD PTR [ebp + 24], 0
diff --git a/lib/wrappers/libuv.nim b/lib/wrappers/libuv.nim
index 3189ec408..a52ae0f63 100644
--- a/lib/wrappers/libuv.nim
+++ b/lib/wrappers/libuv.nim
@@ -30,9 +30,9 @@ type
   CheckProc* = proc (handle: PCheck, status: cint) {.cdecl.}
   IdleProc* = proc (handle: PIdle, status: cint) {.cdecl.}
 
-  PSockAddr* = ptr TSockAddr
+  PSockAddr* = ptr SockAddr
 
-  GetAddrInfoProc* = proc (handle: PGetAddrInfo, status: cint, res: ptr TAddrInfo)
+  GetAddrInfoProc* = proc (handle: PGetAddrInfo, status: cint, res: ptr AddrInfo)
 
   ExitProc* = proc (a2: PProcess, exit_status: cint, term_signal: cint)
   FsProc* = proc (req: PFS)
@@ -210,7 +210,7 @@ type
   cunsigned = int
 
   UdpSendProc* = proc (req: PUdpSend, status: cint)
-  UdpRecvProc* = proc (handle: PUdp, nread: cssize, buf: TBuf, adr: ptr TSockAddr, flags: cunsigned)
+  UdpRecvProc* = proc (handle: PUdp, nread: cssize, buf: TBuf, adr: ptr SockAddr, flags: cunsigned)
 
   TUdp* {.pure, final, importc: "uv_udp_t", header: "uv.h".} = object
     loop* {.importc: "loop".}: PLoop
@@ -366,7 +366,7 @@ type
     tcp_port* {.importc: "tcp_port".}: TPort
     socket_send_buffer_size* {.importc: "socket_send_buffer_size".}: int
     socket_recv_buffer_size* {.importc: "socket_receive_buffer_size".}: int
-    servers* {.importc: "servers".}: ptr TInAddr
+    servers* {.importc: "servers".}: ptr InAddr
     nservers* {.importc: "nservers".}: int
     domains* {.importc: "domains".}: ptr cstring
     ndomains* {.importc: "ndomains".}: int
@@ -450,19 +450,19 @@ proc write*(req: PWrite, handle: PStream, bufs: ptr TBuf, bufcnt: cint, send_han
 proc tcp_init*(a2: PLoop, handle: PTcp): cint{.
     importc: "uv_tcp_init", header: "uv.h".}
 
-proc tcp_bind*(handle: PTcp, a3: TSockAddrIn): cint{.
+proc tcp_bind*(handle: PTcp, a3: SockAddrIn): cint{.
     importc: "uv_tcp_bind", header: "uv.h".}
 
 proc tcp_bind6*(handle: PTcp, a3: TSockAddrIn6): cint{.
     importc: "uv_tcp_bind6", header: "uv.h".}
 
-proc tcp_getsockname*(handle: PTcp, name: ptr TSockAddr, namelen: var cint): cint{.
+proc tcp_getsockname*(handle: PTcp, name: ptr SockAddr, namelen: var cint): cint{.
     importc: "uv_tcp_getsockname", header: "uv.h".}
 
-proc tcp_getpeername*(handle: PTcp, name: ptr TSockAddr, namelen: var cint): cint{.
+proc tcp_getpeername*(handle: PTcp, name: ptr SockAddr, namelen: var cint): cint{.
     importc: "uv_tcp_getpeername", header: "uv.h".}
 
-proc tcp_connect*(req: PConnect, handle: PTcp, address: TSockAddrIn, cb: ConnectProc): cint{.
+proc tcp_connect*(req: PConnect, handle: PTcp, address: SockAddrIn, cb: ConnectProc): cint{.
     importc: "uv_tcp_connect", header: "uv.h".}
 
 proc tcp_connect6*(req: PConnect, handle: PTcp, address: TSockAddrIn6, cb: ConnectProc): cint{.
@@ -471,16 +471,16 @@ proc tcp_connect6*(req: PConnect, handle: PTcp, address: TSockAddrIn6, cb: Conne
 proc udp_init*(a2: PLoop, handle: PUdp): cint{.
     importc: "uv_udp_init", header: "uv.h".}
 
-proc udp_bind*(handle: PUdp, adr: TSockAddrIn, flags: cunsigned): cint{.
+proc udp_bind*(handle: PUdp, adr: SockAddrIn, flags: cunsigned): cint{.
     importc: "uv_udp_bind", header: "uv.h".}
 
 proc udp_bind6*(handle: PUdp, adr: TSockAddrIn6, flags: cunsigned): cint{.
     importc: "uv_udp_bind6", header: "uv.h".}
 
-proc udp_getsockname*(handle: PUdp, name: ptr TSockAddr, namelen: var cint): cint{.
+proc udp_getsockname*(handle: PUdp, name: ptr SockAddr, namelen: var cint): cint{.
     importc: "uv_udp_getsockname", header: "uv.h".}
 
-proc udp_send*(req: PUdpSend, handle: PUdp, bufs: ptr TBuf, bufcnt: cint, adr: TSockAddrIn, send_cb: UdpSendProc): cint{.
+proc udp_send*(req: PUdpSend, handle: PUdp, bufs: ptr TBuf, bufcnt: cint, adr: SockAddrIn, send_cb: UdpSendProc): cint{.
     importc: "uv_udp_send", header: "uv.h".}
 
 proc udp_send6*(req: PUdpSend, handle: PUdp, bufs: ptr TBuf, bufcnt: cint, adr: TSockAddrIn6, send_cb: UdpSendProc): cint{.
@@ -492,7 +492,7 @@ proc udp_recv_start*(handle: PUdp, alloc_cb: AllocProc, recv_cb: UdpRecvProc): c
 proc udp_recv_stop*(handle: PUdp): cint{.
     importc: "uv_udp_recv_stop", header: "uv.h".}
 
-proc tty_init*(a2: PLoop, a3: pTTy, fd: TFile): cint{.
+proc tty_init*(a2: PLoop, a3: pTTy, fd: File): cint{.
     importc: "uv_tty_init", header: "uv.h".}
 
 proc tty_set_mode*(a2: pTTy, mode: cint): cint{.
@@ -504,13 +504,13 @@ proc tty_get_winsize*(a2: pTTy, width: var cint, height: var cint): cint{.
 proc tty_reset_mode*() {.
     importc: "uv_tty_reset_mode", header: "uv.h".}
 
-proc guess_handle*(file: TFile): THandleType{.
+proc guess_handle*(file: File): THandleType{.
     importc: "uv_guess_handle", header: "uv.h".}
 
 proc pipe_init*(a2: PLoop, handle: PPipe, ipc: int): cint{.
     importc: "uv_pipe_init", header: "uv.h".}
 
-proc pipe_open*(a2: PPipe, file: TFile){.
+proc pipe_open*(a2: PPipe, file: File){.
     importc: "uv_pipe_open", header: "uv.h".}
 
 proc pipe_bind*(handle: PPipe, name: cstring): cint{.
@@ -576,10 +576,10 @@ proc ares_init_options*(a2: PLoop, channel: PAresChannel, options: PAresOptions,
 proc ares_destroy*(a2: PLoop, channel: PAresChannel){.
     importc: "uv_ares_destroy", header: "uv.h".}
 
-proc getaddrinfo*(a2: PLoop, handle: PGetAddrInfo,getaddrinfo_cb: GetAddrInfoProc, node: cstring, service: cstring, hints: ptr TAddrInfo): cint{.
+proc getaddrinfo*(a2: PLoop, handle: PGetAddrInfo,getaddrinfo_cb: GetAddrInfoProc, node: cstring, service: cstring, hints: ptr AddrInfo): cint{.
     importc: "uv_getaddrinfo", header: "uv.h".}
 
-proc freeaddrinfo*(ai: ptr TAddrInfo){.
+proc freeaddrinfo*(ai: ptr AddrInfo){.
     importc: "uv_freeaddrinfo", header: "uv.h".}
 
 proc spawn*(a2: PLoop, a3: PProcess, options: TProcessOptions): cint{.
@@ -594,19 +594,19 @@ proc queue_work*(loop: PLoop, req: PWork, work_cb: WorkProc, after_work_cb: Afte
 proc req_cleanup*(req: PFS){.
     importc: "uv_fs_req_cleanup", header: "uv.h".}
 
-proc close*(loop: PLoop, req: PFS, file: TFile, cb: FsProc): cint{.
+proc close*(loop: PLoop, req: PFS, file: File, cb: FsProc): cint{.
     importc: "uv_fs_close", header: "uv.h".}
 
 proc open*(loop: PLoop, req: PFS, path: cstring, flags: cint, mode: cint, cb: FsProc): cint{.
     importc: "uv_fs_open", header: "uv.h".}
 
-proc read*(loop: PLoop, req: PFS, file: TFile, buf: pointer, length: csize, offset: coff, cb: FsProc): cint{.
+proc read*(loop: PLoop, req: PFS, file: File, buf: pointer, length: csize, offset: coff, cb: FsProc): cint{.
     importc: "uv_fs_read", header: "uv.h".}
 
 proc unlink*(loop: PLoop, req: PFS, path: cstring, cb: FsProc): cint{.
     importc: "uv_fs_unlink", header: "uv.h".}
 
-proc write*(loop: PLoop, req: PFS, file: TFile, buf: pointer, length: csize, offset: coff, cb: FsProc): cint{.
+proc write*(loop: PLoop, req: PFS, file: File, buf: pointer, length: csize, offset: coff, cb: FsProc): cint{.
     importc: "uv_fs_write", header: "uv.h".}
 
 proc mkdir*(loop: PLoop, req: PFS, path: cstring, mode: cint, cb: FsProc): cint{.
@@ -621,22 +621,22 @@ proc readdir*(loop: PLoop, req: PFS, path: cstring, flags: cint, cb: FsProc): ci
 proc stat*(loop: PLoop, req: PFS, path: cstring, cb: FsProc): cint{.
     importc: "uv_fs_stat", header: "uv.h".}
 
-proc fstat*(loop: PLoop, req: PFS, file: TFile, cb: FsProc): cint{.
+proc fstat*(loop: PLoop, req: PFS, file: File, cb: FsProc): cint{.
     importc: "uv_fs_fstat", header: "uv.h".}
 
 proc rename*(loop: PLoop, req: PFS, path: cstring, new_path: cstring, cb: FsProc): cint{.
     importc: "uv_fs_rename", header: "uv.h".}
 
-proc fsync*(loop: PLoop, req: PFS, file: TFile, cb: FsProc): cint{.
+proc fsync*(loop: PLoop, req: PFS, file: File, cb: FsProc): cint{.
     importc: "uv_fs_fsync", header: "uv.h".}
 
-proc fdatasync*(loop: PLoop, req: PFS, file: TFile, cb: FsProc): cint{.
+proc fdatasync*(loop: PLoop, req: PFS, file: File, cb: FsProc): cint{.
     importc: "uv_fs_fdatasync", header: "uv.h".}
 
-proc ftruncate*(loop: PLoop, req: PFS, file: TFile, offset: coff, cb: FsProc): cint{.
+proc ftruncate*(loop: PLoop, req: PFS, file: File, offset: coff, cb: FsProc): cint{.
     importc: "uv_fs_ftruncate", header: "uv.h".}
 
-proc sendfile*(loop: PLoop, req: PFS, out_fd: TFile, in_fd: TFile, in_offset: coff, length: csize, cb: FsProc): cint{.
+proc sendfile*(loop: PLoop, req: PFS, out_fd: File, in_fd: File, in_offset: coff, length: csize, cb: FsProc): cint{.
     importc: "uv_fs_sendfile", header: "uv.h".}
 
 proc chmod*(loop: PLoop, req: PFS, path: cstring, mode: cint, cb: FsProc): cint{.
@@ -645,7 +645,7 @@ proc chmod*(loop: PLoop, req: PFS, path: cstring, mode: cint, cb: FsProc): cint{
 proc utime*(loop: PLoop, req: PFS, path: cstring, atime: cdouble, mtime: cdouble, cb: FsProc): cint{.
     importc: "uv_fs_utime", header: "uv.h".}
 
-proc futime*(loop: PLoop, req: PFS, file: TFile, atime: cdouble, mtime: cdouble, cb: FsProc): cint{.
+proc futime*(loop: PLoop, req: PFS, file: File, atime: cdouble, mtime: cdouble, cb: FsProc): cint{.
     importc: "uv_fs_futime", header: "uv.h".}
 
 proc lstat*(loop: PLoop, req: PFS, path: cstring, cb: FsProc): cint{.
@@ -660,25 +660,25 @@ proc symlink*(loop: PLoop, req: PFS, path: cstring, new_path: cstring, flags: ci
 proc readlink*(loop: PLoop, req: PFS, path: cstring, cb: FsProc): cint{.
     importc: "uv_fs_readlink", header: "uv.h".}
 
-proc fchmod*(loop: PLoop, req: PFS, file: TFile, mode: cint, cb: FsProc): cint{.
+proc fchmod*(loop: PLoop, req: PFS, file: File, mode: cint, cb: FsProc): cint{.
     importc: "uv_fs_fchmod", header: "uv.h".}
 
 proc chown*(loop: PLoop, req: PFS, path: cstring, uid: cint, gid: cint, cb: FsProc): cint{.
     importc: "uv_fs_chown", header: "uv.h".}
 
-proc fchown*(loop: PLoop, req: PFS, file: TFile, uid: cint, gid: cint, cb: FsProc): cint{.
+proc fchown*(loop: PLoop, req: PFS, file: File, uid: cint, gid: cint, cb: FsProc): cint{.
     importc: "uv_fs_fchown", header: "uv.h".}
 
 proc event_init*(loop: PLoop, handle: PFSEvent, filename: cstring, cb: FsEventProc): cint{.
     importc: "uv_fs_event_init", header: "uv.h".}
 
-proc ip4_addr*(ip: cstring, port: cint): TSockAddrIn{.
+proc ip4_addr*(ip: cstring, port: cint): SockAddrIn{.
     importc: "uv_ip4_addr", header: "uv.h".}
 
 proc ip6_addr*(ip: cstring, port: cint): TSockAddrIn6{.
     importc: "uv_ip6_addr", header: "uv.h".}
 
-proc ip4_name*(src: ptr TSockAddrIn, dst: cstring, size: csize): cint{.
+proc ip4_name*(src: ptr SockAddrIn, dst: cstring, size: csize): cint{.
     importc: "uv_ip4_name", header: "uv.h".}
 
 proc ip6_name*(src: ptr TSockAddrIn6, dst: cstring, size: csize): cint{.
diff --git a/lib/wrappers/mysql.nim b/lib/wrappers/mysql.nim
index 945e09ecf..937a8952a 100644
--- a/lib/wrappers/mysql.nim
+++ b/lib/wrappers/mysql.nim
@@ -10,11 +10,15 @@
 {.deadCodeElim: on.}
 {.push, callconv: cdecl.}
 
-when defined(Unix): 
-  const 
-    lib = "libmysqlclient.so.15"
-when defined(Windows): 
-  const 
+when defined(Unix):
+  when defined(macosx):
+    const
+      lib = "libmysqlclient.(15|16|17|18).dylib"
+  else:
+    const
+      lib = "libmysqlclient.so.(15|16|17|18)"
+when defined(Windows):
+  const
     lib = "libmysql.dll"
 type 
   my_bool* = bool
@@ -59,9 +63,9 @@ type
 const 
   SCRAMBLE_LENGTH* = 20 # Length of random string sent by server on handshake; 
                         # this is also length of obfuscated password, 
-                        # recieved from client
+                        # received from client
   SCRAMBLE_LENGTH_323* = 8    # length of password stored in the db: 
-                              # new passwords are preceeded with '*'  
+                              # new passwords are preceded with '*'  
   SCRAMBLED_PASSWORD_CHAR_LENGTH* = SCRAMBLE_LENGTH * 2 + 1
   SCRAMBLED_PASSWORD_CHAR_LENGTH_323* = SCRAMBLE_LENGTH_323 * 2
   NOT_NULL_FLAG* = 1          #  Field can't be NULL
@@ -142,7 +146,7 @@ const
   MAX_MEDIUMINT_WIDTH* = 8    # Max width for a INT24 w.o. sign
   MAX_INT_WIDTH* = 10         # Max width for a LONG w.o. sign
   MAX_BIGINT_WIDTH* = 20      # Max width for a LONGLONG
-  MAX_CHAR_WIDTH* = 255       # Max length for a CHAR colum
+  MAX_CHAR_WIDTH* = 255       # Max length for a CHAR column
   MAX_BLOB_WIDTH* = 8192      # Default width for blob
 
 type 
@@ -554,7 +558,7 @@ type
   Tstatus* = enum 
     STATUS_READY, STATUS_GET_RESULT, STATUS_USE_RESULT
   Tprotocol_type* = enum  # There are three types of queries - the ones that have to go to
-                          # the master, the ones that go to a slave, and the adminstrative
+                          # the master, the ones that go to a slave, and the administrative
                           # type which must happen on the pivot connectioin 
     PROTOCOL_DEFAULT, PROTOCOL_TCP, PROTOCOL_SOCKET, PROTOCOL_PIPE, 
     PROTOCOL_MEMORY
@@ -786,7 +790,7 @@ proc server_init*(argc: cint, argv: cstringArray, groups: cstringArray): cint{.
 proc server_end*(){.cdecl, dynlib: lib, importc: "mysql_server_end".}
   # mysql_server_init/end need to be called when using libmysqld or
   #      libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so
-  #      you don't need to call it explicitely; but you need to call
+  #      you don't need to call it explicitly; but you need to call
   #      mysql_server_end() to free memory). The names are a bit misleading
   #      (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general
   #      names which suit well whether you're using libmysqld or libmysqlclient. We
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index f091d8f46..03729dbab 100644
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
@@ -50,7 +50,7 @@ when useWinVersion:
   from winlean import SocketHandle
 else:
   const
-    versions = "(|.1.0.0|.0.9.9|.0.9.8|.0.9.7|.0.9.6|.0.9.5|.0.9.4)"
+    versions = "(.10|.1.0.1|.1.0.0|.0.9.9|.0.9.8)"
   when defined(macosx):
     const
       DLLSSLName = "libssl" & versions & ".dylib"
@@ -141,6 +141,14 @@ const
   SSL_CTRL_GET_MAX_CERT_LIST* = 50
   SSL_CTRL_SET_MAX_CERT_LIST* = 51 #* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
                                    # * when just a single record has been written): *
+  SSL_CTRL_SET_TLSEXT_SERVERNAME_CB = 53
+  SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG = 54
+  SSL_CTRL_SET_TLSEXT_HOSTNAME = 55
+  TLSEXT_NAMETYPE_host_name* = 0
+  SSL_TLSEXT_ERR_OK* = 0
+  SSL_TLSEXT_ERR_ALERT_WARNING* = 1
+  SSL_TLSEXT_ERR_ALERT_FATAL* = 2
+  SSL_TLSEXT_ERR_NOACK* = 3
   SSL_MODE_ENABLE_PARTIAL_WRITE* = 1 #* Make it possible to retry SSL_write() with changed buffer location
                                      # * (buffer contents must stay the same!); this is not the default to avoid
                                      # * the misconception that non-blocking SSL_write() behaves like
@@ -290,15 +298,47 @@ when not useWinVersion:
     if p != nil: dealloc(p)
 
 proc CRYPTO_malloc_init*() =
-  when not useWinVersion:
+  when not useWinVersion and not defined(macosx):
     CRYPTO_set_mem_functions(allocWrapper, reallocWrapper, deallocWrapper)
 
 proc SSL_CTX_ctrl*(ctx: SslCtx, cmd: cInt, larg: int, parg: pointer): int{.
   cdecl, dynlib: DLLSSLName, importc.}
 
+proc SSL_CTX_callback_ctrl(ctx: SslCtx, typ: cInt, fp: PFunction): int{.
+  cdecl, dynlib: DLLSSLName, importc.}
+
 proc SSLCTXSetMode*(ctx: SslCtx, mode: int): int =
   result = SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, mode, nil)
 
+proc SSL_ctrl*(ssl: SslPtr, cmd: cInt, larg: int, parg: pointer): int{.
+  cdecl, dynlib: DLLSSLName, importc.}
+
+proc SSL_set_tlsext_host_name*(ssl: SslPtr, name: cstring): int =
+  result = SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, name)
+  ## Set the SNI server name extension to be used in a client hello.
+  ## Returns 1 if SNI was set, 0 if current SSL configuration doesn't support SNI.
+
+
+proc SSL_get_servername*(ssl: SslPtr, typ: cInt = TLSEXT_NAMETYPE_host_name): cstring {.cdecl, dynlib: DLLSSLName, importc.}
+  ## Retrieve the server name requested in the client hello. This can be used
+  ## in the callback set in `SSL_CTX_set_tlsext_servername_callback` to
+  ## implement virtual hosting. May return `nil`.
+
+proc SSL_CTX_set_tlsext_servername_callback*(ctx: SslCtx, cb: proc(ssl: SslPtr, cb_id: int, arg: pointer): int {.cdecl.}): int =
+  ## Set the callback to be used on listening SSL connections when the client hello is received.
+  ##
+  ## The callback should return one of:
+  ## * SSL_TLSEXT_ERR_OK
+  ## * SSL_TLSEXT_ERR_ALERT_WARNING
+  ## * SSL_TLSEXT_ERR_ALERT_FATAL
+  ## * SSL_TLSEXT_ERR_NOACK
+  result = SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, cast[PFunction](cb))
+
+proc SSL_CTX_set_tlsext_servername_arg*(ctx: SslCtx, arg: pointer): int =
+  ## Set the pointer to be used in the callback registered to ``SSL_CTX_set_tlsext_servername_callback``.
+  result = SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, arg)
+
+
 proc bioNew*(b: PBIO_METHOD): BIO{.cdecl, dynlib: DLLUtilName, importc: "BIO_new".}
 proc bioFreeAll*(b: BIO){.cdecl, dynlib: DLLUtilName, importc: "BIO_free_all".}
 proc bioSMem*(): PBIO_METHOD{.cdecl, dynlib: DLLUtilName, importc: "BIO_s_mem".}
@@ -341,8 +381,6 @@ else:
       dynlib: DLLSSLName, importc.}
 
   proc SslSetFd*(s: PSSL, fd: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.}
-  proc SslCtrl*(ssl: PSSL, cmd: cInt, larg: int, parg: Pointer): int{.cdecl, 
-      dynlib: DLLSSLName, importc.}
   proc SslCTXCtrl*(ctx: PSSL_CTX, cmd: cInt, larg: int, parg: Pointer): int{.
       cdecl, dynlib: DLLSSLName, importc.}
 
diff --git a/lib/wrappers/pcre.nim b/lib/wrappers/pcre.nim
index afa8f447a..67436f026 100644
--- a/lib/wrappers/pcre.nim
+++ b/lib/wrappers/pcre.nim
@@ -1,158 +1,190 @@
 #************************************************
-#       Perl-Compatible Regular Expressions      *
-#***********************************************
+#       Perl-Compatible Regular Expressions     *
+#************************************************
 # This is the public header file for the PCRE library, to be #included by
-#applications that call the PCRE functions.
+# applications that call the PCRE functions.
 #
-#           Copyright (c) 1997-2010 University of Cambridge
+#           Copyright (c) 1997-2014 University of Cambridge
 #
 #-----------------------------------------------------------------------------
-#Redistribution and use in source and binary forms, with or without
-#modification, are permitted provided that the following conditions are met:
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
 #
-#     Redistributions of source code must retain the above copyright notice,
+#    * Redistributions of source code must retain the above copyright notice,
 #      this list of conditions and the following disclaimer.
 #
-#     Redistributions in binary form must reproduce the above copyright
+#    * Redistributions in binary form must reproduce the above copyright
 #      notice, this list of conditions and the following disclaimer in the
 #      documentation and/or other materials provided with the distribution.
 #
-#     Neither the name of the University of Cambridge nor the names of its
+#    * Neither the name of the University of Cambridge nor the names of its
 #      contributors may be used to endorse or promote products derived from
 #      this software without specific prior written permission.
 #
-#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-#POSSIBILITY OF SUCH DAMAGE.
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
 #-----------------------------------------------------------------------------
-#
 
-{.deadcodeElim: on.}
-
-when not defined(pcreDll):
-  when hostOS == "windows":
-    const pcreDll = "pcre.dll"
-  elif hostOS == "macosx":
-    const pcreDll = "libpcre(.3|.1|).dylib"
-  else:
-    const pcreDll = "libpcre.so(.3|.1|)"
-  {.pragma: pcreImport, dynlib: pcreDll.}
-else:
-  {.pragma: pcreImport, header: "<pcre.h>".}
+{.deadCodeElim: on.}
 
-# The current PCRE version information. 
+# The current PCRE version information.
 
-const 
-  MAJOR* = 8
-  MINOR* = 31
-  PRERELEASE* = true
-  DATE* = "2012-07-06"
+const
+  PCRE_MAJOR* = 8
+  PCRE_MINOR* = 36
+  PCRE_PRERELEASE* = true
+  PCRE_DATE* = "2014-09-26"
 
 # When an application links to a PCRE DLL in Windows, the symbols that are
 # imported have to be identified as such. When building PCRE, the appropriate
 # export setting is defined in pcre_internal.h, which includes this file. So we
-# don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. 
-
-# Have to include stdlib.h in order to ensure that size_t is defined;
-# it is needed here for malloc. 
-
-# Allow for C++ users 
-
-# Options. Some are compile-time only, some are run-time only, and some are
-# both, so we keep them all distinct. 
-
-const 
-  CASELESS* = 0x00000001
-  MULTILINE* = 0x00000002
-  DOTALL* = 0x00000004
-  EXTENDED* = 0x00000008
-  ANCHORED* = 0x00000010
-  DOLLAR_ENDONLY* = 0x00000020
-  EXTRA* = 0x00000040
-  NOTBOL* = 0x00000080
-  NOTEOL* = 0x00000100
-  UNGREEDY* = 0x00000200
-  NOTEMPTY* = 0x00000400
-  UTF8* = 0x00000800
-  NO_AUTO_CAPTURE* = 0x00001000
-  NO_UTF8_CHECK* = 0x00002000
-  AUTO_CALLOUT* = 0x00004000
-  PARTIAL_SOFT* = 0x00008000
-  PARTIAL* = 0x00008000       # Backwards compatible synonym 
-  DFA_SHORTEST* = 0x00010000
-  DFA_RESTART* = 0x00020000
-  FIRSTLINE* = 0x00040000
-  DUPNAMES* = 0x00080000
-  NEWLINE_CR* = 0x00100000
-  NEWLINE_LF* = 0x00200000
-  NEWLINE_CRLF* = 0x00300000
-  NEWLINE_ANY* = 0x00400000
-  NEWLINE_ANYCRLF* = 0x00500000
-  BSR_ANYCRLF* = 0x00800000
-  BSR_UNICODE* = 0x01000000
-  JAVASCRIPT_COMPAT* = 0x02000000
-  NO_START_OPTIMIZE* = 0x04000000
-  NO_START_OPTIMISE* = 0x04000000
-  PARTIAL_HARD* = 0x08000000
-  NOTEMPTY_ATSTART* = 0x10000000
-  UCP* = 0x20000000
-
-# Exec-time and get/set-time error codes 
-
-const 
-  ERROR_NOMATCH* = (- 1)
-  ERROR_NULL* = (- 2)
-  ERROR_BADOPTION* = (- 3)
-  ERROR_BADMAGIC* = (- 4)
-  ERROR_UNKNOWN_OPCODE* = (- 5)
-  ERROR_UNKNOWN_NODE* = (- 5) # For backward compatibility 
-  ERROR_NOMEMORY* = (- 6)
-  ERROR_NOSUBSTRING* = (- 7)
-  ERROR_MATCHLIMIT* = (- 8)
-  ERROR_CALLOUT* = (- 9)      # Never used by PCRE itself 
-  ERROR_BADUTF8* = (- 10)
-  ERROR_BADUTF8_OFFSET* = (- 11)
-  ERROR_PARTIAL* = (- 12)
-  ERROR_BADPARTIAL* = (- 13)
-  ERROR_INTERNAL* = (- 14)
-  ERROR_BADCOUNT* = (- 15)
-  ERROR_DFA_UITEM* = (- 16)
-  ERROR_DFA_UCOND* = (- 17)
-  ERROR_DFA_UMLIMIT* = (- 18)
-  ERROR_DFA_WSSIZE* = (- 19)
-  ERROR_DFA_RECURSE* = (- 20)
-  ERROR_RECURSIONLIMIT* = (- 21)
-  ERROR_NULLWSLIMIT* = (- 22) # No longer actually used 
-  ERROR_BADNEWLINE* = (- 23)
-  ERROR_BADOFFSET* = (- 24)
-  ERROR_SHORTUTF8* = (- 25)
-  ERROR_RECURSELOOP* = (- 26)
-  ERROR_JIT_STACKLIMIT* = (- 27)
-  ERROR_BADMODE* = (- 28)
-  ERROR_BADENDIANNESS* = (- 29)
-  ERROR_DFA_BADRESTART* = (- 30)
-
-# Specific error codes for UTF-8 validity checks
+# don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL.
+
+# By default, we use the standard "extern" declarations.
+
+# Allow for C++ users
+
+# Public options. Some are compile-time only, some are run-time only, and some
+# are both. Most of the compile-time options are saved with the compiled regex
+# so that they can be inspected during studying (and therefore JIT compiling).
+# Note that pcre_study() has its own set of options. Originally, all the options
+# defined here used distinct bits. However, almost all the bits in a 32-bit word
+# are now used, so in order to conserve them, option bits that were previously
+# only recognized at matching time (i.e. by pcre_exec() or pcre_dfa_exec()) may
+# also be used for compile-time options that affect only compiling and are not
+# relevant for studying or JIT compiling.
+#
+# Some options for pcre_compile() change its behaviour but do not affect the
+# behaviour of the execution functions. Other options are passed through to the
+# execution functions and affect their behaviour, with or without affecting the
+# behaviour of pcre_compile().
+#
+# Options that can be passed to pcre_compile() are tagged Cx below, with these
+# variants:
+#
+# C1   Affects compile only
+# C2   Does not affect compile; affects exec, dfa_exec
+# C3   Affects compile, exec, dfa_exec
+# C4   Affects compile, exec, dfa_exec, study
+# C5   Affects compile, exec, study
+#
+# Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged 
+# with E and D, respectively. They take precedence over C3, C4, and C5 settings 
+# passed from pcre_compile(). Those that are compatible with JIT execution are 
+# flagged with J.
+
+const
+  CASELESS*          = 0x00000001  # C1
+  MULTILINE*         = 0x00000002  # C1
+  DOTALL*            = 0x00000004  # C1
+  EXTENDED*          = 0x00000008  # C1
+  ANCHORED*          = 0x00000010  # C4 E D
+  DOLLAR_ENDONLY*    = 0x00000020  # C2
+  EXTRA*             = 0x00000040  # C1
+  NOTBOL*            = 0x00000080  #    E D J
+  NOTEOL*            = 0x00000100  #    E D J
+  UNGREEDY*          = 0x00000200  # C1
+  NOTEMPTY*          = 0x00000400  #    E D J
+  UTF8*              = 0x00000800  # C4        )
+  UTF16*             = 0x00000800  # C4        ) Synonyms
+  UTF32*             = 0x00000800  # C4        )
+  NO_AUTO_CAPTURE*   = 0x00001000  # C1
+  NO_UTF8_CHECK*     = 0x00002000  # C1 E D J  )
+  NO_UTF16_CHECK*    = 0x00002000  # C1 E D J  ) Synonyms
+  NO_UTF32_CHECK*    = 0x00002000  # C1 E D J  )
+  AUTO_CALLOUT*      = 0x00004000  # C1
+  PARTIAL_SOFT*      = 0x00008000  #    E D J  ) Synonyms
+  PARTIAL*           = 0x00008000  #    E D J  )
+
+# This pair use the same bit.
+const
+  NEVER_UTF*         = 0x00010000  # C1        ) Overlaid
+  DFA_SHORTEST*      = 0x00010000  #      D    ) Overlaid
 
+# This pair use the same bit.
 const
-  UTF8_ERR0* = 0
-  UTF8_ERR1* = 1
-  UTF8_ERR2* = 2
-  UTF8_ERR3* = 3
-  UTF8_ERR4* = 4
-  UTF8_ERR5* = 5
-  UTF8_ERR6* = 6
-  UTF8_ERR7* = 7
-  UTF8_ERR8* = 8
-  UTF8_ERR9* = 9
+  NO_AUTO_POSSESS*   = 0x00020000  # C1        ) Overlaid
+  DFA_RESTART*       = 0x00020000  #      D    ) Overlaid
+
+const
+  FIRSTLINE*         = 0x00040000  # C3
+  DUPNAMES*          = 0x00080000  # C1
+  NEWLINE_CR*        = 0x00100000  # C3 E D
+  NEWLINE_LF*        = 0x00200000  # C3 E D
+  NEWLINE_CRLF*      = 0x00300000  # C3 E D
+  NEWLINE_ANY*       = 0x00400000  # C3 E D
+  NEWLINE_ANYCRLF*   = 0x00500000  # C3 E D
+  BSR_ANYCRLF*       = 0x00800000  # C3 E D
+  BSR_UNICODE*       = 0x01000000  # C3 E D
+  JAVASCRIPT_COMPAT* = 0x02000000  # C5
+  NO_START_OPTIMIZE* = 0x04000000  # C2 E D    ) Synonyms
+  NO_START_OPTIMISE* = 0x04000000  # C2 E D    )
+  PARTIAL_HARD*      = 0x08000000  #    E D J
+  NOTEMPTY_ATSTART*  = 0x10000000  #    E D J
+  UCP*               = 0x20000000  # C3
+
+## Exec-time and get/set-time error codes
+const
+  ERROR_NOMATCH*          =  -1
+  ERROR_NULL*             =  -2
+  ERROR_BADOPTION*        =  -3
+  ERROR_BADMAGIC*         =  -4
+  ERROR_UNKNOWN_OPCODE*   =  -5
+  ERROR_UNKNOWN_NODE*     =  -5 ## For backward compatibility
+  ERROR_NOMEMORY*         =  -6
+  ERROR_NOSUBSTRING*      =  -7
+  ERROR_MATCHLIMIT*       =  -8
+  ERROR_CALLOUT*          =  -9 ## Never used by PCRE itself
+  ERROR_BADUTF8*          = -10 ## Same for 8/16/32
+  ERROR_BADUTF16*         = -10 ## Same for 8/16/32
+  ERROR_BADUTF32*         = -10 ## Same for 8/16/32
+  ERROR_BADUTF8_OFFSET*   = -11 ## Same for 8/16
+  ERROR_BADUTF16_OFFSET*  = -11 ## Same for 8/16
+  ERROR_PARTIAL*          = -12
+  ERROR_BADPARTIAL*       = -13
+  ERROR_INTERNAL*         = -14
+  ERROR_BADCOUNT*         = -15
+  ERROR_DFA_UITEM*        = -16
+  ERROR_DFA_UCOND*        = -17
+  ERROR_DFA_UMLIMIT*      = -18
+  ERROR_DFA_WSSIZE*       = -19
+  ERROR_DFA_RECURSE*      = -20
+  ERROR_RECURSIONLIMIT*   = -21
+  ERROR_NULLWSLIMIT*      = -22 ## No longer actually used
+  ERROR_BADNEWLINE*       = -23
+  ERROR_BADOFFSET*        = -24
+  ERROR_SHORTUTF8*        = -25
+  ERROR_SHORTUTF16*       = -25 ## Same for 8/16
+  ERROR_RECURSELOOP*      = -26
+  ERROR_JIT_STACKLIMIT*   = -27
+  ERROR_BADMODE*          = -28
+  ERROR_BADENDIANNESS*    = -29
+  ERROR_DFA_BADRESTART*   = -30
+  ERROR_JIT_BADOPTION*    = -31
+  ERROR_BADLENGTH*        = -32
+  ERROR_UNSET*            = -33
+
+## Specific error codes for UTF-8 validity checks
+const
+  UTF8_ERR0*  =  0
+  UTF8_ERR1*  =  1
+  UTF8_ERR2*  =  2
+  UTF8_ERR3*  =  3
+  UTF8_ERR4*  =  4
+  UTF8_ERR5*  =  5
+  UTF8_ERR6*  =  6
+  UTF8_ERR7*  =  7
+  UTF8_ERR8*  =  8
+  UTF8_ERR9*  =  9
   UTF8_ERR10* = 10
   UTF8_ERR11* = 11
   UTF8_ERR12* = 12
@@ -165,193 +197,305 @@ const
   UTF8_ERR19* = 19
   UTF8_ERR20* = 20
   UTF8_ERR21* = 21
+  UTF8_ERR22* = 22 # Unused (was non-character)
 
-# Request types for pcre_fullinfo() 
-
-const 
-  INFO_OPTIONS* = 0
-  INFO_SIZE* = 1
-  INFO_CAPTURECOUNT* = 2
-  INFO_BACKREFMAX* = 3
-  INFO_FIRSTBYTE* = 4
-  INFO_FIRSTCHAR* = 4         # For backwards compatibility 
-  INFO_FIRSTTABLE* = 5
-  INFO_LASTLITERAL* = 6
-  INFO_NAMEENTRYSIZE* = 7
-  INFO_NAMECOUNT* = 8
-  INFO_NAMETABLE* = 9
-  INFO_STUDYSIZE* = 10
-  INFO_DEFAULT_TABLES* = 11
-  INFO_OKPARTIAL* = 12
-  INFO_JCHANGED* = 13
-  INFO_HASCRORLF* = 14
-  INFO_MINLENGTH* = 15
-  INFO_JIT* = 16
-  INFO_JITSIZE* = 17
-  INFO_MAXLOOKBEHIND* = 18
-
-# Request types for pcre_config(). Do not re-arrange, in order to remain
-# compatible. 
-
-const 
-  CONFIG_UTF8* = 0
-  CONFIG_NEWLINE* = 1
-  CONFIG_LINK_SIZE* = 2
-  CONFIG_POSIX_MALLOC_THRESHOLD* = 3
-  CONFIG_MATCH_LIMIT* = 4
-  CONFIG_STACKRECURSE* = 5
-  CONFIG_UNICODE_PROPERTIES* = 6
-  CONFIG_MATCH_LIMIT_RECURSION* = 7
-  CONFIG_BSR* = 8
-  CONFIG_JIT* = 9
-  CONFIG_JITTARGET* = 11
-
-# Request types for pcre_study(). Do not re-arrange, in order to remain
-# compatible.
+## Specific error codes for UTF-16 validity checks
+const
+  UTF16_ERR0* = 0
+  UTF16_ERR1* = 1
+  UTF16_ERR2* = 2
+  UTF16_ERR3* = 3
+  UTF16_ERR4* = 4 # Unused (was non-character)
 
+## Specific error codes for UTF-32 validity checks
 const
-  STUDY_JIT_COMPILE* = 0x00000001
-  STUDY_JIT_PARTIAL_SOFT_COMPILE* = 0x00000002
-  STUDY_JIT_PARTIAL_HARD_COMPILE* = 0x00000004
-
-# Bit flags for the pcre_extra structure. Do not re-arrange or redefine
-# these bits, just add new ones on the end, in order to remain compatible. 
-
-const 
-  EXTRA_STUDY_DATA* = 0x00000001
-  EXTRA_MATCH_LIMIT* = 0x00000002
-  EXTRA_CALLOUT_DATA* = 0x00000004
-  EXTRA_TABLES* = 0x00000008
-  EXTRA_MATCH_LIMIT_RECURSION* = 0x00000010
-  EXTRA_MARK* = 0x00000020
-  EXTRA_EXECUTABLE_JIT* = 0x00000040
-
-# Types 
-
-type 
-  TPcre*{.pure, final.} = object
-  PPcre* = ptr TPcre
-  Tjit_stack*{.pure, final.} = object
-  Pjit_stack* = ptr Tjit_stack
-
-# When PCRE is compiled as a C++ library, the subject pointer type can be
-# replaced with a custom type. For conventional use, the public interface is a
-# const char *. 
-
-# The structure for passing additional data to pcre_exec(). This is defined in
-# such as way as to be extensible. Always add new fields at the end, in order to
-# remain compatible. 
-
-type 
-  TExtra*{.pure, final.} = object 
-    flags*: int                 ## Bits for which fields are set 
-    study_data*: pointer        ## Opaque data from pcre_study() 
-    match_limit*: int           ## Maximum number of calls to match() 
-    callout_data*: pointer      ## Data passed back in callouts 
-    tables*: cstring            ## Pointer to character tables 
-    match_limit_recursion*: int ## Max recursive calls to match() 
-    mark*: ptr cstring          ## For passing back a mark pointer 
-    executable_jit*: pointer    ## Contains a pointer to a compiled jit code
-  
-
-# The structure for passing out data via the pcre_callout_function. We use a
-# structure so that new fields can be added on the end in future versions,
-# without changing the API of the function, thereby allowing old clients to work
-# without modification. 
-
-type 
-  TCalloutBlock*{.pure, final.} = object 
-    version*: cint            ## Identifies version of block 
-    callout_number*: cint     ## Number compiled into pattern 
-    offset_vector*: ptr cint  ## The offset vector 
-    subject*: cstring         ## The subject being matched 
-    subject_length*: cint     ## The length of the subject 
-    start_match*: cint        ## Offset to start of this match attempt 
-    current_position*: cint   ## Where we currently are in the subject 
-    capture_top*: cint        ## Max current capture 
-    capture_last*: cint       ## Most recently closed capture 
-    callout_data*: pointer    ## Data passed in with the call 
-    pattern_position*: cint   ## Offset to next item in the pattern 
-    next_item_length*: cint   ## Length of next item in the pattern
-    mark*: cstring            ## Pointer to current mark or NULL
-
-# Indirection for store get and free functions. These can be set to
-#alternative malloc/free functions if required. Special ones are used in the
-#non-recursive case for "frames". There is also an optional callout function
-#that is triggered by the (?) regex item. For Virtual Pascal, these definitions
-#have to take another form.
-
-# User defined callback which provides a stack just before the match starts.
+  UTF32_ERR0* = 0
+  UTF32_ERR1* = 1
+  UTF32_ERR2* = 2 # Unused (was non-character)
+  UTF32_ERR3* = 3
 
+## Request types for pcre_fullinfo()
+const
+  INFO_OPTIONS*             =  0
+  INFO_SIZE*                =  1
+  INFO_CAPTURECOUNT*        =  2
+  INFO_BACKREFMAX*          =  3
+  INFO_FIRSTBYTE*           =  4
+  INFO_FIRSTCHAR*           =  4 ## For backwards compatibility
+  INFO_FIRSTTABLE*          =  5
+  INFO_LASTLITERAL*         =  6
+  INFO_NAMEENTRYSIZE*       =  7
+  INFO_NAMECOUNT*           =  8
+  INFO_NAMETABLE*           =  9
+  INFO_STUDYSIZE*           = 10
+  INFO_DEFAULT_TABLES*      = 11
+  INFO_OKPARTIAL*           = 12
+  INFO_JCHANGED*            = 13
+  INFO_HASCRORLF*           = 14
+  INFO_MINLENGTH*           = 15
+  INFO_JIT*                 = 16
+  INFO_JITSIZE*             = 17
+  INFO_MAXLOOKBEHIND*       = 18
+  INFO_FIRSTCHARACTER*      = 19
+  INFO_FIRSTCHARACTERFLAGS* = 20
+  INFO_REQUIREDCHAR*        = 21
+  INFO_REQUIREDCHARFLAGS*   = 22
+  INFO_MATCHLIMIT*          = 23
+  INFO_RECURSIONLIMIT*      = 24
+  INFO_MATCH_EMPTY*         = 25
+
+## Request types for pcre_config(). Do not re-arrange, in order to remain
+## compatible.
+const
+  CONFIG_UTF8*                   =  0
+  CONFIG_NEWLINE*                =  1
+  CONFIG_LINK_SIZE*              =  2
+  CONFIG_POSIX_MALLOC_THRESHOLD* =  3
+  CONFIG_MATCH_LIMIT*            =  4
+  CONFIG_STACKRECURSE*           =  5
+  CONFIG_UNICODE_PROPERTIES*     =  6
+  CONFIG_MATCH_LIMIT_RECURSION*  =  7
+  CONFIG_BSR*                    =  8
+  CONFIG_JIT*                    =  9
+  CONFIG_UTF16*                  = 10
+  CONFIG_JITTARGET*              = 11
+  CONFIG_UTF32*                  = 12
+  CONFIG_PARENS_LIMIT*           = 13
+
+## Request types for pcre_study(). Do not re-arrange, in order to remain
+## compatible.
+const
+  STUDY_JIT_COMPILE*              = 0x0001
+  STUDY_JIT_PARTIAL_SOFT_COMPILE* = 0x0002
+  STUDY_JIT_PARTIAL_HARD_COMPILE* = 0x0004
+  STUDY_EXTRA_NEEDED*             = 0x0008
+
+## Bit flags for the pcre[16|32]_extra structure. Do not re-arrange or redefine
+## these bits, just add new ones on the end, in order to remain compatible.
+const
+  EXTRA_STUDY_DATA*            = 0x0001
+  EXTRA_MATCH_LIMIT*           = 0x0002
+  EXTRA_CALLOUT_DATA*          = 0x0004
+  EXTRA_TABLES*                = 0x0008
+  EXTRA_MATCH_LIMIT_RECURSION* = 0x0010
+  EXTRA_MARK*                  = 0x0020
+  EXTRA_EXECUTABLE_JIT*        = 0x0040
+
+## Types
+type
+  Pcre* = object
+  Pcre16* = object
+  Pcre32* = object
+  JitStack* = object
+  JitStack16* = object
+  JitStack32* = object
+
+
+## The structure for passing additional data to pcre_exec(). This is defined in
+## such as way as to be extensible. Always add new fields at the end, in order
+## to remain compatible.
+type
+  ExtraData* = object
+    flags*: clong                  ## Bits for which fields are set
+    study_data*: pointer           ## Opaque data from pcre_study()
+    match_limit*: clong            ## Maximum number of calls to match()
+    callout_data*: pointer         ## Data passed back in callouts
+    tables*: pointer               ## Pointer to character tables
+    match_limit_recursion*: clong  ## Max recursive calls to match()
+    mark*: pointer                 ## For passing back a mark pointer
+    executable_jit*: pointer       ## Contains a pointer to a compiled jit code
+
+## The structure for passing out data via the pcre_callout_function. We use a
+## structure so that new fields can be added on the end in future versions,
+## without changing the API of the function, thereby allowing old clients to
+## work without modification.
 type
-  TJitCallback* = proc(p: pointer): ptr Tjit_stack{.cdecl.}
-
-# Exported PCRE functions 
-
-proc compile*(a2: cstring, a3: cint, a4: ptr cstring, a5: ptr cint, 
-              a6: ptr char): ptr TPcre{.cdecl, importc: "pcre_compile", 
-    pcreImport.}
-proc compile2*(a2: cstring, a3: cint, a4: ptr cint, a5: ptr cstring, 
-               a6: ptr cint, a7: ptr char): ptr TPcre{.cdecl, 
-    importc: "pcre_compile2", pcreImport.}
-proc config*(a2: cint, a3: pointer): cint{.cdecl, importc: "pcre_config", 
-    pcreImport.}
-proc copy_named_substring*(a2: ptr TPcre, a3: cstring, a4: ptr cint, a5: cint, 
-                           a6: cstring, a7: cstring, a8: cint): cint{.cdecl, 
-    importc: "pcre_copy_named_substring", pcreImport.}
-proc copy_substring*(a2: cstring, a3: ptr cint, a4: cint, a5: cint, 
-                     a6: cstring, 
-                     a7: cint): cint{.cdecl, importc: "pcre_copy_substring", 
-                                      pcreImport.}
-proc dfa_exec*(a2: ptr TPcre, a3: ptr TExtra, a4: cstring, a5: cint, 
-               a6: cint, a7: cint, a8: ptr cint, a9: cint, a10: ptr cint, 
-               a11: cint): cint{.cdecl, importc: "pcre_dfa_exec", 
-                                 pcreImport.}
-proc exec*(a2: ptr TPcre, a3: ptr TExtra, a4: cstring, a5: cint, a6: cint, 
-           a7: cint, a8: ptr cint, a9: cint): cint {.
-           cdecl, importc: "pcre_exec", pcreImport.}
-proc free_substring*(a2: cstring){.cdecl, importc: "pcre_free_substring", 
-                                   pcreImport.}
-proc free_substring_list*(a2: cstringArray){.cdecl, 
-    importc: "pcre_free_substring_list", pcreImport.}
-proc fullinfo*(a2: ptr TPcre, a3: ptr TExtra, a4: cint, a5: pointer): cint{.
-    cdecl, importc: "pcre_fullinfo", pcreImport.}
-proc get_named_substring*(a2: ptr TPcre, a3: cstring, a4: ptr cint, a5: cint, 
-                          a6: cstring, a7: cstringArray): cint{.cdecl, 
-    importc: "pcre_get_named_substring", pcreImport.}
-proc get_stringnumber*(a2: ptr TPcre, a3: cstring): cint{.cdecl, 
-    importc: "pcre_get_stringnumber", pcreImport.}
-proc get_stringtable_entries*(a2: ptr TPcre, a3: cstring, a4: cstringArray, 
-                              a5: cstringArray): cint{.cdecl, 
-    importc: "pcre_get_stringtable_entries", pcreImport.}
-proc get_substring*(a2: cstring, a3: ptr cint, a4: cint, a5: cint, 
-                    a6: cstringArray): cint{.cdecl, 
-    importc: "pcre_get_substring", pcreImport.}
-proc get_substring_list*(a2: cstring, a3: ptr cint, a4: cint, 
-                         a5: ptr cstringArray): cint{.cdecl, 
-    importc: "pcre_get_substring_list", pcreImport.}
-proc maketables*(): ptr char{.cdecl, importc: "pcre_maketables", 
-                                       pcreImport.}
-proc refcount*(a2: ptr TPcre, a3: cint): cint{.cdecl, importc: "pcre_refcount", 
-    pcreImport.}
-proc study*(a2: ptr TPcre, a3: cint, a4: var cstring): ptr TExtra{.cdecl, 
-    importc: "pcre_study", pcreImport.}
-proc version*(): cstring{.cdecl, importc: "pcre_version", pcreImport.}
+  CalloutBlock* = object
+    version*         : cint       ## Identifies version of block
+    # ------------------------ Version 0 -------------------------------
+    callout_number*  : cint       ## Number compiled into pattern
+    offset_vector*   : ptr cint   ## The offset vector
+    subject*         : cstring    ## The subject being matched
+    subject_length*  : cint       ## The length of the subject
+    start_match*     : cint       ## Offset to start of this match attempt
+    current_position*: cint       ## Where we currently are in the subject
+    capture_top*     : cint       ## Max current capture
+    capture_last*    : cint       ## Most recently closed capture
+    callout_data*    : pointer    ## Data passed in with the call
+    # ------------------- Added for Version 1 --------------------------
+    pattern_position*: cint       ## Offset to next item in the pattern
+    next_item_length*: cint       ## Length of next item in the pattern
+    # ------------------- Added for Version 2 --------------------------
+    mark*            : pointer    ## Pointer to current mark or NULL
+    # ------------------------------------------------------------------
+
+
+## User defined callback which provides a stack just before the match starts.
+type
+  JitCallback* = proc (a: pointer): ptr JitStack {.cdecl.}
+
+
+when not defined(usePcreHeader):
+  when hostOS == "windows":
+    const pcreDll = "pcre.dll"
+  elif hostOS == "macosx":
+    const pcreDll = "libpcre(.3|.1|).dylib"
+  else:
+    const pcreDll = "libpcre.so(.3|.1|)"
+  {.push dynlib: pcreDll.}
+else:
+  {.push header: "<pcre.h>".}
+
+{.push cdecl, importc: "pcre_$1".}
+
+# Exported PCRE functions
+
+proc compile*(pattern: cstring,
+              options: cint,
+              errptr: ptr cstring,
+              erroffset: ptr cint,
+              tableptr: pointer): ptr Pcre
+
+proc compile2*(pattern: cstring,
+               options: cint,
+               errorcodeptr: ptr cint,
+               errptr: ptr cstring,
+               erroffset: ptr cint,
+               tableptr: pointer): ptr Pcre
+
+proc config*(what: cint,
+             where: pointer): cint
+
+proc copy_named_substring*(code: ptr Pcre,
+                           subject: cstring,
+                           ovector: ptr cint,
+                           stringcount: cint,
+                           stringname: cstring,
+                           buffer: cstring,
+                           buffersize: cint): cint
+
+proc copy_substring*(subject: cstring,
+                     ovector: ptr cint,
+                     stringcount: cint,
+                     stringnumber: cint,
+                     buffer: cstring,
+                     buffersize: cint): cint
+
+proc dfa_exec*(code: ptr Pcre,
+               extra: ptr ExtraData,
+               subject: cstring,
+               length: cint,
+               startoffset: cint,
+               options: cint,
+               ovector: ptr cint,
+               ovecsize: cint,
+               workspace: ptr cint,
+               wscount: cint): cint
+
+proc exec*(code: ptr Pcre,
+           extra: ptr ExtraData,
+           subject: cstring,
+           length: cint,
+           startoffset: cint,
+           options: cint,
+           ovector: ptr cint,
+           ovecsize: cint): cint
+
+proc jit_exec*(code: ptr Pcre,
+               extra: ptr ExtraData,
+               subject: cstring,
+               length: cint,
+               startoffset: cint,
+               options: cint,
+               ovector: ptr cint,
+               ovecsize: cint,
+               jstack: ptr JitStack): cint
+
+proc free_substring*(stringptr: cstring)
+
+proc free_substring_list*(stringptr: cstringArray)
+
+proc fullinfo*(code: ptr Pcre,
+               extra: ptr ExtraData,
+               what: cint,
+               where: pointer): cint
+
+proc get_named_substring*(code: ptr Pcre,
+                          subject: cstring,
+                          ovector: ptr cint,
+                          stringcount: cint,
+                          stringname: cstring,
+                          stringptr: cstringArray): cint
+
+proc get_stringnumber*(code: ptr Pcre,
+                       name: cstring): cint
+
+proc get_stringtable_entries*(code: ptr Pcre,
+                              name: cstring,
+                              first: cstringArray,
+                              last: cstringArray): cint
+
+proc get_substring*(subject: cstring,
+                    ovector: ptr cint,
+                    stringcount: cint,
+                    stringnumber: cint,
+                    stringptr: cstringArray): cint
+
+proc get_substring_list*(subject: cstring,
+                         ovector: ptr cint,
+                         stringcount: cint,
+                         listptr: ptr cstringArray): cint
+
+proc maketables*(): pointer
+
+proc refcount*(code: ptr Pcre,
+               adjust: cint): cint
+
+proc study*(code: ptr Pcre,
+            options: cint,
+            errptr: ptr cstring): ptr ExtraData
+
+proc free_study*(extra: ptr ExtraData)
+
+proc version*(): cstring
 
 # Utility functions for byte order swaps.
 
-proc pattern_to_host_byte_order*(a2: ptr TPcre, a3: ptr TExtra,
-    a4: ptr char): cint{.cdecl, importc: "pcre_pattern_to_host_byte_order",
-    pcreImport.}
+proc pattern_to_host_byte_order*(code: ptr Pcre,
+                                 extra: ptr ExtraData,
+                                 tables: pointer): cint
 
 # JIT compiler related functions.
 
-proc jit_stack_alloc*(a2: cint, a3: cint): ptr Tjit_stack{.cdecl,
-    importc: "pcre_jit_stack_alloc", pcreImport.}
-proc jit_stack_free*(a2: ptr Tjit_stack){.cdecl, importc: "pcre_jit_stack_free",
-    pcreImport.}
-proc assign_jit_stack*(a2: ptr TExtra, a3: TJitCallback, a4: pointer){.cdecl,
-    importc: "pcre_assign_jit_stack", pcreImport.}
+proc jit_stack_alloc*(startsize: cint,
+                      maxsize: cint): ptr JitStack
+
+proc jit_stack_free*(stack: ptr JitStack)
+
+proc assign_jit_stack*(extra: ptr ExtraData,
+                       callback: JitCallback,
+                       data: pointer)
+
+proc jit_free_unused_memory*()
+
+
+# There was an odd function with `var cstring` instead of `ptr`
+proc study*(code: ptr Pcre,
+            options: cint,
+            errptr: var cstring): ptr ExtraData {.deprecated.}
+
+{.pop.}
+{.pop.}
+
+
+{.deprecated: [MAJOR: PCRE_MAJOR, MINOR: PCRE_MINOR,
+               PRERELEASE: PCRE_PRERELEASE, DATE: PCRE_DATE].}
+
+{.deprecated: [TPcre: Pcre, TJitStack: JitStack].}
+type
+  PPcre* {.deprecated.} = ptr Pcre
+  PJitStack* {.deprecated.} = ptr JitStack
 
-var 
-  pcre_free*: proc (p: ptr TPcre) {.cdecl.} 
+{.deprecated: [TExtra: ExtraData].}
+{.deprecated: [TCalloutBlock: CalloutBlock].}
+{.deprecated: [TJitCallback: JitCallback].}
diff --git a/lib/wrappers/readline/history.nim b/lib/wrappers/readline/history.nim
index caa857ceb..495bc15e4 100644
--- a/lib/wrappers/readline/history.nim
+++ b/lib/wrappers/readline/history.nim
@@ -231,7 +231,7 @@ proc history_truncate_file*(a2: cstring, a3: cint): cint{.cdecl,
 #  -1) If there was an error in expansion.
 #   2) If the returned line should just be printed.
 #
-#  If an error ocurred in expansion, then OUTPUT contains a descriptive
+#  If an error occurred in expansion, then OUTPUT contains a descriptive
 #  error message. 
 
 proc history_expand*(a2: cstring, a3: cstringArray): cint{.cdecl, 
diff --git a/lib/wrappers/readline/tweaked/history.h b/lib/wrappers/readline/tweaked/history.h
index 53bd642b1..b79123790 100644
--- a/lib/wrappers/readline/tweaked/history.h
+++ b/lib/wrappers/readline/tweaked/history.h
@@ -217,7 +217,7 @@ extern int history_truncate_file PARAMS((const char *, int));
   -1) If there was an error in expansion.
    2) If the returned line should just be printed.
 
-  If an error ocurred in expansion, then OUTPUT contains a descriptive
+  If an error occurred in expansion, then OUTPUT contains a descriptive
   error message. */
 extern int history_expand PARAMS((char *, char **));
 
diff --git a/lib/wrappers/sdl/sdl.nim b/lib/wrappers/sdl/sdl.nim
index 449b651f9..5bb5b7ec2 100644
--- a/lib/wrappers/sdl/sdl.nim
+++ b/lib/wrappers/sdl/sdl.nim
@@ -89,7 +89,7 @@
 #                           As most games will need it.
 #
 #   April    02 2001 - DL : Added SDL_getenv.h definitions and tested version
-#                           1.2.0 compatability.
+#                           1.2.0 compatibility.
 #
 #   March    13 2001 - MT : Added Linux compatibility.
 #
@@ -118,7 +118,7 @@
 #
 #  November  30 2001 - DL : SDL_NOFRAME added as pointed out by Simon Rushton.
 #
-#  December  11 2001 - DL : Added $WEAKPACKAGEUNIT ON to facilitate useage in
+#  December  11 2001 - DL : Added $WEAKPACKAGEUNIT ON to facilitate usage in
 #                           Components
 #
 #  January   05 2002 - DL : Added SDL_Swap32 function as suggested by Matthias
@@ -209,7 +209,7 @@
 #  forgot to apply Michalis Kamburelis' patch to the implementation section. now fixed
 #
 #  Revision 1.14  2004/12/23 23:42:18  savage
-#  Applied Patches supplied by Michalis Kamburelis ( THANKS! ), for greater FreePascal compatability.
+#  Applied Patches supplied by Michalis Kamburelis ( THANKS! ), for greater FreePascal compatibility.
 #
 #  Revision 1.13  2004/09/30 22:31:59  savage
 #  Updated with slightly different header comments
@@ -221,7 +221,7 @@
 #  Updated so that Library name defines are correctly defined for MacOS X.
 #
 #  Revision 1.10  2004/07/20 23:57:33  savage
-#  Thanks to Paul Toth for spotting an error in the SDL Audio Convertion structures.
+#  Thanks to Paul Toth for spotting an error in the SDL Audio Conversion structures.
 #  In TSDL_AudioCVT the filters variable should point to and array of pointers and not what I had there previously.
 #
 #  Revision 1.9  2004/07/03 22:07:22  savage
@@ -243,7 +243,7 @@
 #  SDL_GetEnv Fix so that it is not define twice for FPC. Thanks to Rene Hugentobler for pointing out this bug,
 #
 #  Revision 1.3  2004/02/18 22:35:51  savage
-#  Brought sdl.pas up to 1.2.7 compatability
+#  Brought sdl.pas up to 1.2.7 compatibility
 #  Thus...
 #  Added SDL_GL_STEREO,
 #      SDL_GL_MULTISAMPLEBUFFERS,
diff --git a/lib/wrappers/sdl/sdl_mixer.nim b/lib/wrappers/sdl/sdl_mixer.nim
index 33a71508a..2f8664635 100644
--- a/lib/wrappers/sdl/sdl_mixer.nim
+++ b/lib/wrappers/sdl/sdl_mixer.nim
@@ -136,7 +136,7 @@
 #  Windows unit not used in this file, so it was removed to keep the code tidy.
 #
 #  Revision 1.3  2004/03/31 10:05:08  savage
-#  Better defines for Endianess under FreePascal and Borland compilers.
+#  Better defines for Endianness under FreePascal and Borland compilers.
 #
 #  Revision 1.2  2004/03/30 20:23:28  savage
 #  Tidied up use of UNIX compiler directive.
diff --git a/lib/wrappers/zip/zlib.nim b/lib/wrappers/zip/zlib.nim
index 6f51e9a8d..a0d772363 100644
--- a/lib/wrappers/zip/zlib.nim
+++ b/lib/wrappers/zip/zlib.nim
@@ -233,7 +233,7 @@ proc uncompress*(sourceBuf: cstring, sourceLen: int): string =
     return
 
   # Make sure memory allocated by inflateInit2() is freed eventually.
-  finally: discard inflateEnd(z)
+  defer: discard inflateEnd(z)
 
   # Decompress all of self.
   while true: