summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/core/macros.nim2
-rw-r--r--lib/deprecated/pure/actors.nim2
-rw-r--r--lib/deprecated/pure/sockets.nim1
-rw-r--r--lib/impure/nre.nim1
-rw-r--r--lib/impure/rdstdin.nim4
-rw-r--r--lib/nimbase.h24
-rw-r--r--lib/packages/docutils/rst.nim14
-rw-r--r--lib/packages/docutils/rstgen.nim28
-rw-r--r--lib/phpcl.nim50
-rw-r--r--lib/pure/collections/LockFreeHash.nim2
-rw-r--r--lib/pure/collections/sets.nim2
-rw-r--r--lib/pure/colors.nim2
-rw-r--r--lib/pure/concurrency/threadpool.nim6
-rw-r--r--lib/pure/future.nim2
-rw-r--r--lib/pure/json.nim10
-rw-r--r--lib/pure/mersenne.nim2
-rw-r--r--lib/pure/nativesockets.nim2
-rw-r--r--lib/pure/net.nim193
-rw-r--r--lib/pure/nimprof.nim2
-rw-r--r--lib/pure/os.nim8
-rw-r--r--lib/pure/ospaths.nim4
-rw-r--r--lib/pure/osproc.nim17
-rw-r--r--lib/pure/securehash.nim3
-rw-r--r--lib/pure/selectors.nim10
-rw-r--r--lib/pure/streams.nim5
-rw-r--r--lib/system.nim25
-rw-r--r--lib/system/alloc.nim2
-rw-r--r--lib/system/gc.nim15
-rw-r--r--lib/system/gc2.nim16
-rw-r--r--lib/system/gc_common.nim42
-rw-r--r--lib/system/jssys.nim459
-rw-r--r--lib/system/mmdisp.nim4
-rw-r--r--lib/system/sysspawn.nim2
-rw-r--r--lib/windows/winlean.nim99
-rw-r--r--lib/wrappers/openssl.nim11
35 files changed, 695 insertions, 376 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 872d4848d..eda793620 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -601,7 +601,7 @@ proc last*(node: NimNode): NimNode {.compileTime.} = node[<node.len]
 
 
 const
-  RoutineNodes* = {nnkProcDef, nnkMethodDef, nnkDo, nnkLambda, nnkIteratorDef}
+  RoutineNodes* = {nnkProcDef, nnkMethodDef, nnkDo, nnkLambda, nnkIteratorDef, nnkTemplateDef, nnkConverterDef}
   AtomicNodes* = {nnkNone..nnkNilLit}
   CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
     nnkCallStrLit, nnkHiddenCallConv}
diff --git a/lib/deprecated/pure/actors.nim b/lib/deprecated/pure/actors.nim
index f0791f954..36bd41e9e 100644
--- a/lib/deprecated/pure/actors.nim
+++ b/lib/deprecated/pure/actors.nim
@@ -40,7 +40,7 @@ type
 
   Actor[In, Out] = object{.pure, final.}
     i: Channel[Task[In, Out]]
-    t: TThread[ptr Actor[In, Out]]
+    t: Thread[ptr Actor[In, Out]]
 
   PActor*[In, Out] = ptr Actor[In, Out] ## an actor
 {.deprecated: [TTask: Task, TActor: Actor].}
diff --git a/lib/deprecated/pure/sockets.nim b/lib/deprecated/pure/sockets.nim
index 5d6fa0078..f7d0950d8 100644
--- a/lib/deprecated/pure/sockets.nim
+++ b/lib/deprecated/pure/sockets.nim
@@ -39,7 +39,6 @@ when hostOS == "solaris":
 
 import os, parseutils
 from times import epochTime
-import unsigned
 
 when defined(ssl):
   import openssl
diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim
index 973f1f2ee..10700b59b 100644
--- a/lib/impure/nre.nim
+++ b/lib/impure/nre.nim
@@ -10,7 +10,6 @@
 from pcre import nil
 import nre.private.util
 import tables
-import unsigned
 from strutils import toLower, `%`
 from math import ceil
 import options
diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim
index b373859f4..469bb69c5 100644
--- a/lib/impure/rdstdin.nim
+++ b/lib/impure/rdstdin.nim
@@ -55,7 +55,7 @@ when defined(Windows):
       event*: KEY_EVENT_RECORD
       safetyBuffer: array[0..5, DWORD]
 
-  proc readConsoleInputW*(hConsoleInput: THANDLE, lpBuffer: var INPUTRECORD,
+  proc readConsoleInputW*(hConsoleInput: HANDLE, lpBuffer: var INPUTRECORD,
                           nLength: uint32,
                           lpNumberOfEventsRead: var uint32): WINBOOL{.
       stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
@@ -100,7 +100,7 @@ when defined(Windows):
     stdout.write "\n"
 
 else:
-  import linenoise, termios, unsigned
+  import linenoise, termios
 
   proc readLineFromStdin*(prompt: string): TaintedString {.
                           tags: [ReadIOEffect, WriteIOEffect].} =
diff --git a/lib/nimbase.h b/lib/nimbase.h
index bba5ac023..374c0ceb1 100644
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -23,6 +23,30 @@ __clang__
 #ifndef NIMBASE_H
 #define NIMBASE_H
 
+/* ------------ ignore typical warnings in Nim-generated files ------------- */
+#if defined(__GNUC__) || defined(__clang__)
+#  pragma GCC diagnostic ignored "-Wwritable-strings"
+#  pragma GCC diagnostic ignored "-Winvalid-noreturn"
+#  pragma GCC diagnostic ignored "-Wformat"
+#  pragma GCC diagnostic ignored "-Wlogical-not-parentheses"
+#  pragma GCC diagnostic ignored "-Wlogical-op-parentheses"
+#  pragma GCC diagnostic ignored "-Wshadow"
+#  pragma GCC diagnostic ignored "-Wunused-function"
+#  pragma GCC diagnostic ignored "-Wunused-variable"
+#  pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#  pragma GCC diagnostic ignored "-Wtautological-compare"
+#  pragma GCC diagnostic ignored "-Wswitch-bool"
+#  pragma GCC diagnostic ignored "-Wmacro-redefined"
+#  pragma GCC diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
+#endif
+
+#if defined(_MSC_VER)
+#  pragma warning(disable: 4005 4100 4101 4189 4191 4200 4244 4293 4296 4309)
+#  pragma warning(disable: 4310 4365 4456 4477 4514 4574 4611 4668 4702 4706)
+#  pragma warning(disable: 4710 4711 4774 4800 4820 4996)
+#endif
+/* ------------------------------------------------------------------------- */
+
 #if defined(__GNUC__)
 #  define _GNU_SOURCE 1
 #endif
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index 2fbde632e..e1d5f902e 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -1518,7 +1518,7 @@ proc dirInclude(p: var RstParser): PRstNode =
       #  InternalError("Too many binary zeros in include file")
       result = parseDoc(q)
 
-proc dirCodeBlock(p: var RstParser, nimrodExtension = false): PRstNode =
+proc dirCodeBlock(p: var RstParser, nimExtension = false): PRstNode =
   ## Parses a code block.
   ##
   ## Code blocks are rnDirective trees with a `kind` of rnCodeBlock. See the
@@ -1526,8 +1526,8 @@ proc dirCodeBlock(p: var RstParser, nimrodExtension = false): PRstNode =
   ##
   ## Code blocks can come in two forms, the standard `code directive
   ## <http://docutils.sourceforge.net/docs/ref/rst/directives.html#code>`_ and
-  ## the nimrod extension ``.. code-block::``. If the block is an extension, we
-  ## want the default language syntax highlighting to be Nimrod, so we create a
+  ## the nim extension ``.. code-block::``. If the block is an extension, we
+  ## want the default language syntax highlighting to be Nim, so we create a
   ## fake internal field to comminicate with the generator. The field is named
   ## ``default-language``, which is unlikely to collide with a field specified
   ## by any random rst input file.
@@ -1545,16 +1545,16 @@ proc dirCodeBlock(p: var RstParser, nimrodExtension = false): PRstNode =
     result.sons[2] = n
 
   # Extend the field block if we are using our custom extension.
-  if nimrodExtension:
+  if nimExtension:
     # Create a field block if the input block didn't have any.
     if result.sons[1].isNil: result.sons[1] = newRstNode(rnFieldList)
     assert result.sons[1].kind == rnFieldList
-    # Hook the extra field and specify the Nimrod language as value.
+    # Hook the extra field and specify the Nim language as value.
     var extraNode = newRstNode(rnField)
     extraNode.add(newRstNode(rnFieldName))
     extraNode.add(newRstNode(rnFieldBody))
     extraNode.sons[0].add(newRstNode(rnLeaf, "default-language"))
-    extraNode.sons[1].add(newRstNode(rnLeaf, "Nimrod"))
+    extraNode.sons[1].add(newRstNode(rnLeaf, "Nim"))
     result.sons[1].add(extraNode)
 
   result.kind = rnCodeBlock
@@ -1641,7 +1641,7 @@ proc parseDotDot(p: var RstParser): PRstNode =
       else:
         rstMessage(p, meInvalidDirective, d)
     of dkCode: result = dirCodeBlock(p)
-    of dkCodeBlock: result = dirCodeBlock(p, nimrodExtension = true)
+    of dkCodeBlock: result = dirCodeBlock(p, nimExtension = true)
     of dkIndex: result = dirIndex(p)
     else: rstMessage(p, meInvalidDirective, d)
     popInd(p)
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index 22d944597..8b5bb0e8f 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -757,10 +757,15 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
   template valid(s): expr =
     s.len > 0 and allCharsInSet(s, {'.','/',':','%','_','\\','\128'..'\xFF'} +
                                    Digits + Letters + WhiteSpace)
-
-  var options = ""
+  let
+    arg = getArgument(n)
+    isObject = arg.toLower().endsWith(".svg")
+  var
+    options = ""
+    content = ""
   var s = getFieldValue(n, "scale")
-  if s.valid: dispA(d.target, options, " scale=\"$1\"", " scale=$1", [strip(s)])
+  if s.valid: dispA(d.target, options, if isObject: "" else: " scale=\"$1\"",
+                    " scale=$1", [strip(s)])
 
   s = getFieldValue(n, "height")
   if s.valid: dispA(d.target, options, " height=\"$1\"", " height=$1", [strip(s)])
@@ -769,16 +774,21 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
   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)])
+  if s.valid:
+    # <object> displays its content if it cannot render the image
+    if isObject: dispA(d.target, content, "$1", "", [strip(s)])
+    else: 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}",
+    let htmlOut = if isObject:
+        "<object data=\"$1\" type=\"image/svg+xml\"$2 >" & content & "</object>"
+        else: "<img src=\"$1\"$2 />"
+    dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
           [arg, options])
   if len(n) >= 3: renderRstToOut(d, n.sons[2], result)
 
@@ -802,7 +812,7 @@ proc parseCodeBlockField(d: PDoc, n: PRstNode, params: var CodeBlockParams) =
     if parseInt(n.getFieldValue, number) > 0:
       params.startLine = number
   of "file":
-    # The ``file`` option is a Nimrod extension to the official spec, it acts
+    # The ``file`` option is a Nim extension to the official spec, it acts
     # like it would for other directives like ``raw`` or ``cvs-table``. This
     # field is dealt with in ``rst.nim`` which replaces the existing block with
     # the referenced file, so we only need to ignore it here to avoid incorrect
@@ -871,7 +881,7 @@ proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) =
   ## second the code block itself. The code block can use syntax highlighting,
   ## which depends on the directive argument specified by the rst input, and
   ## may also come from the parser through the internal ``default-language``
-  ## option to differentiate between a plain code block and nimrod's code block
+  ## option to differentiate between a plain code block and Nim's code block
   ## extension.
   assert n.kind == rnCodeBlock
   if n.sons[2] == nil: return
diff --git a/lib/phpcl.nim b/lib/phpcl.nim
new file mode 100644
index 000000000..5eaa00f80
--- /dev/null
+++ b/lib/phpcl.nim
@@ -0,0 +1,50 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## PHP compatibility layer.
+
+type
+  PhpArray*[Key, Val] = ref object
+
+  PhpObj* = ref object ## can be a string, an int etc.
+
+proc explode*(sep, x: string): seq[string] {.importc: "explode".}
+template split*(x, sep: string): seq[string] = explode(sep, x)
+
+proc `$`*(x: PhpObj): string {.importcpp: "(#)".}
+proc `++`*(x: PhpObj) {.importcpp: "++(#)".}
+
+proc `==`*(x, y: PhpObj): string {.importcpp: "((#) == (#))".}
+proc `<=`*(x, y: PhpObj): string {.importcpp: "((#) <= (#))".}
+proc `<`*(x, y: PhpObj): string {.importcpp: "((#) < (#))".}
+
+proc toUpper*(x: string): string {.importc: "strtoupper".}
+proc toLower*(x: string): string {.importc: "strtolower".}
+
+proc strtr*(s: string, replacePairs: PhpArray[string, string]): string {.importc.}
+proc strtr*(s, fromm, to: string): string {.importc.}
+
+proc toArray*[K,V](pairs: openarray[(K,V)]): PhpArray[K,V] {.magic:
+  "Array".}
+template strtr*(s: string, replacePairs: openarray[(string, string)]): string =
+  strtr(toArray(replacePairs))
+
+iterator pairs*[K,V](d: PhpArray[K,V]): (K,V) =
+  var k: K
+  var v: V
+  {.emit: "foreach (`d` as `k`=>`v`) {".}
+  yield (k, v)
+  {.emit: "}".}
+
+proc `[]`*[K,V](d: PhpArray[K,V]; k: K): V {.importcpp: "#[#]".}
+proc `[]=`*[K,V](d: PhpArray[K,V]; k: K; v: V) {.importcpp: "#[#] = #".}
+
+proc ksort*[K,V](d: PhpArray[K,V]) {.importc.}
+proc krsort*[K,V](d: PhpArray[K,V]) {.importc.}
+proc keys*[K,V](d: PhpArray[K,V]): seq[K] {.importc.}
diff --git a/lib/pure/collections/LockFreeHash.nim b/lib/pure/collections/LockFreeHash.nim
index 1d4471b21..a3ead81e3 100644
--- a/lib/pure/collections/LockFreeHash.nim
+++ b/lib/pure/collections/LockFreeHash.nim
@@ -1,6 +1,6 @@
 #nim c -t:-march=i686 --cpu:amd64 --threads:on -d:release lockfreehash.nim
 
-import unsigned, math, hashes
+import math, hashes
 
 #------------------------------------------------------------------------------
 ## Memory Utility Functions
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index abe9cf85e..9a42a21ee 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -951,7 +951,7 @@ when isMainModule and not defined(release):
       var b = initOrderedSet[int]()
       for x in [2, 4, 5]: b.incl(x)
       assert($a == $b)
-      assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
+      assert(a == b) # https://github.com/Araq/Nim/issues/1413
 
     block initBlocks:
       var a: OrderedSet[int]
diff --git a/lib/pure/colors.nim b/lib/pure/colors.nim
index 7328f7c24..f4c027576 100644
--- a/lib/pure/colors.nim
+++ b/lib/pure/colors.nim
@@ -6,7 +6,7 @@
 #    distribution, for details about the copyright.
 #
 
-## This module implements color handling for Nimrod. It is used by
+## This module implements color handling for Nim. It is used by
 ## the ``graphics`` module.
 
 import strutils
diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim
index 2603835dd..a30d49889 100644
--- a/lib/pure/concurrency/threadpool.nim
+++ b/lib/pure/concurrency/threadpool.nim
@@ -328,10 +328,10 @@ proc distinguishedSlave(w: ptr Worker) {.thread.} =
     if w.q.len != 0: w.cleanFlowVars
 
 var
-  workers: array[MaxThreadPoolSize, TThread[ptr Worker]]
+  workers: array[MaxThreadPoolSize, Thread[ptr Worker]]
   workersData: array[MaxThreadPoolSize, Worker]
 
-  distinguished: array[MaxDistinguishedThread, TThread[ptr Worker]]
+  distinguished: array[MaxDistinguishedThread, Thread[ptr Worker]]
   distinguishedData: array[MaxDistinguishedThread, Worker]
 
 when defined(nimPinToCpu):
@@ -468,7 +468,7 @@ proc nimSpawn3(fn: WorkerProc; data: pointer) {.compilerProc.} =
       await(gSomeReady)
 
 var
-  distinguishedLock: TLock
+  distinguishedLock: Lock
 
 initLock distinguishedLock
 
diff --git a/lib/pure/future.nim b/lib/pure/future.nim
index 4767266e5..3793edc8b 100644
--- a/lib/pure/future.nim
+++ b/lib/pure/future.nim
@@ -134,7 +134,7 @@ macro `[]`*(lc: ListComprehension, comp, typ: expr): expr =
   ## comprehension, for example ``x | (x <- 1..10, x mod 2 == 0)``. `typ` is
   ## the type that will be stored inside the result seq.
   ##
-  ## .. code-block:: nimrod
+  ## .. code-block:: nim
   ##
   ##   echo lc[x | (x <- 1..10, x mod 2 == 0), int]
   ##
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index ab7d18bd8..f672a0c1b 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -712,17 +712,21 @@ proc `%`*(elements: openArray[JsonNode]): JsonNode =
 
 proc toJson(x: NimNode): NimNode {.compiletime.} =
   case x.kind
-  of nnkBracket:
+  of nnkBracket: # array
     result = newNimNode(nnkBracket)
     for i in 0 .. <x.len:
       result.add(toJson(x[i]))
 
-  of nnkTableConstr:
+  of nnkTableConstr: # object
     result = newNimNode(nnkTableConstr)
     for i in 0 .. <x.len:
-      assert x[i].kind == nnkExprColonExpr
+      x[i].expectKind nnkExprColonExpr
       result.add(newNimNode(nnkExprColonExpr).add(x[i][0]).add(toJson(x[i][1])))
 
+  of nnkCurly: # empty object
+    result = newNimNode(nnkTableConstr)
+    x.expectLen(0)
+
   else:
     result = x
 
diff --git a/lib/pure/mersenne.nim b/lib/pure/mersenne.nim
index c8090dc6a..ae0845714 100644
--- a/lib/pure/mersenne.nim
+++ b/lib/pure/mersenne.nim
@@ -1,5 +1,3 @@
-import unsigned
-
 type
   MersenneTwister* = object
     mt: array[0..623, uint32]
diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim
index b5a8d5777..3951b46a3 100644
--- a/lib/pure/nativesockets.nim
+++ b/lib/pure/nativesockets.nim
@@ -12,7 +12,7 @@
 
 # TODO: Clean up the exports a bit and everything else in general.
 
-import unsigned, os
+import os
 
 when hostOS == "solaris":
   {.passl: "-lsocket -lnsl".}
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index d1016011e..346b656a0 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -10,7 +10,7 @@
 ## This module implements a high-level cross-platform sockets interface.
 
 {.deadCodeElim: on.}
-import nativesockets, os, strutils, unsigned, parseutils, times
+import nativesockets, os, strutils, parseutils, times
 export Port, `$`, `==`
 
 const useWinVersion = defined(Windows) or defined(nimdoc)
@@ -102,8 +102,7 @@ type
                                       ## case of IPv4
 {.deprecated: [TIpAddress: IpAddress].}
 
-proc isIpAddress*(address_str: string): bool {.tags: [].}
-proc parseIpAddress*(address_str: string): IpAddress
+
 proc socketError*(socket: Socket, err: int = -1, async = false,
                   lastError = (-1).OSErrorCode): void
 
@@ -548,40 +547,6 @@ proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {
   var valuei = cint(if value: 1 else: 0)
   setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
 
-proc connect*(socket: Socket, address: string,
-    port = Port(0)) {.tags: [ReadIOEffect].} =
-  ## Connects socket to ``address``:``port``. ``Address`` can be an IP address or a
-  ## host name. If ``address`` is a host name, this function will try each IP
-  ## of that host name. ``htons`` is already performed on ``port`` so you must
-  ## not do it.
-  ##
-  ## If ``socket`` is an SSL socket a handshake will be automatically performed.
-  var aiList = getAddrInfo(address, port, socket.domain)
-  # try all possibilities:
-  var success = false
-  var lastError: OSErrorCode
-  var it = aiList
-  while it != nil:
-    if connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen) == 0'i32:
-      success = true
-      break
-    else: lastError = osLastError()
-    it = it.ai_next
-
-  dealloc(aiList)
-  if not success: raiseOSError(lastError)
-
-  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)
-
 when defined(ssl):
   proc handshake*(socket: Socket): bool {.tags: [ReadIOEffect, WriteIOEffect].} =
     ## This proc needs to be called on a socket after it connects. This is
@@ -829,7 +794,7 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
 
   template addNLIfEmpty(): stmt =
     if line.len == 0:
-      line.add("\c\L")
+      line.string.add("\c\L")
 
   template raiseSockError(): stmt {.dirty, immediate.} =
     let lastError = getSocketError(socket)
@@ -971,61 +936,6 @@ proc sendTo*(socket: Socket, address: string, port: Port,
   ## This is the high-level version of the above ``sendTo`` function.
   result = socket.sendTo(address, port, cstring(data), data.len)
 
-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 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.
-  ##
-  ## **Note**: For SSL sockets, the ``handshake`` procedure must be called
-  ## whenever the socket successfully connects to a server.
-  var aiList = getAddrInfo(name, port, af)
-  # try all possibilities:
-  var success = false
-  var lastError: OSErrorCode
-  var it = aiList
-  while it != nil:
-    var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen)
-    if ret == 0'i32:
-      success = true
-      break
-    else:
-      lastError = osLastError()
-      when useWinVersion:
-        # Windows EINTR doesn't behave same as POSIX.
-        if lastError.int32 == WSAEWOULDBLOCK:
-          success = true
-          break
-      else:
-        if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
-          success = true
-          break
-
-    it = it.ai_next
-
-  dealloc(aiList)
-  if not success: raiseOSError(lastError)
-
-proc connect*(socket: Socket, address: string, port = Port(0),
-    timeout: int) {.tags: [ReadIOEffect, WriteIOEffect].} =
-  ## Connects to server as specified by ``address`` on port specified by ``port``.
-  ##
-  ## The ``timeout`` paremeter specifies the time in milliseconds to allow for
-  ## the connection to the server to be made.
-  socket.fd.setBlocking(false)
-
-  socket.connectAsync(address, port, socket.domain)
-  var s = @[socket.fd]
-  if selectWrite(s, timeout) != 1:
-    raise newException(TimeoutError, "Call to 'connect' timed out.")
-  else:
-    when defined(ssl):
-      if socket.isSSL:
-        socket.fd.setBlocking(true)
-        doAssert socket.handshake()
-  socket.fd.setBlocking(true)
 
 proc isSsl*(socket: Socket): bool =
   ## Determines whether ``socket`` is a SSL socket.
@@ -1295,7 +1205,8 @@ proc parseIPv6Address(address_str: string): IpAddress =
     raise newException(ValueError,
       "Invalid IP Address. The address consists of too many groups")
 
-proc parseIpAddress(address_str: string): IpAddress =
+
+proc parseIpAddress*(address_str: string): IpAddress =
   ## Parses an IP address
   ## Raises EInvalidValue on error
   if address_str == nil:
@@ -1305,8 +1216,7 @@ proc parseIpAddress(address_str: string): IpAddress =
   else:
     return parseIPv4Address(address_str)
 
-
-proc isIpAddress(address_str: string): bool =
+proc isIpAddress*(address_str: string): bool {.tags: [].} =
   ## Checks if a string is an IP address
   ## Returns true if it is, false otherwise
   try:
@@ -1314,3 +1224,94 @@ proc isIpAddress(address_str: string): bool =
   except ValueError:
     return false
   return true
+
+
+proc connect*(socket: Socket, address: string,
+    port = Port(0)) {.tags: [ReadIOEffect].} =
+  ## Connects socket to ``address``:``port``. ``Address`` can be an IP address or a
+  ## host name. If ``address`` is a host name, this function will try each IP
+  ## of that host name. ``htons`` is already performed on ``port`` so you must
+  ## not do it.
+  ##
+  ## If ``socket`` is an SSL socket a handshake will be automatically performed.
+  var aiList = getAddrInfo(address, port, socket.domain)
+  # try all possibilities:
+  var success = false
+  var lastError: OSErrorCode
+  var it = aiList
+  while it != nil:
+    if connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen) == 0'i32:
+      success = true
+      break
+    else: lastError = osLastError()
+    it = it.ai_next
+
+  dealloc(aiList)
+  if not success: raiseOSError(lastError)
+
+  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)
+
+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 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.
+  ##
+  ## **Note**: For SSL sockets, the ``handshake`` procedure must be called
+  ## whenever the socket successfully connects to a server.
+  var aiList = getAddrInfo(name, port, af)
+  # try all possibilities:
+  var success = false
+  var lastError: OSErrorCode
+  var it = aiList
+  while it != nil:
+    var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen)
+    if ret == 0'i32:
+      success = true
+      break
+    else:
+      lastError = osLastError()
+      when useWinVersion:
+        # Windows EINTR doesn't behave same as POSIX.
+        if lastError.int32 == WSAEWOULDBLOCK:
+          success = true
+          break
+      else:
+        if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
+          success = true
+          break
+
+    it = it.ai_next
+
+  dealloc(aiList)
+  if not success: raiseOSError(lastError)
+
+proc connect*(socket: Socket, address: string, port = Port(0),
+    timeout: int) {.tags: [ReadIOEffect, WriteIOEffect].} =
+  ## Connects to server as specified by ``address`` on port specified by ``port``.
+  ##
+  ## The ``timeout`` paremeter specifies the time in milliseconds to allow for
+  ## the connection to the server to be made.
+  socket.fd.setBlocking(false)
+
+  socket.connectAsync(address, port, socket.domain)
+  var s = @[socket.fd]
+  if selectWrite(s, timeout) != 1:
+    raise newException(TimeoutError, "Call to 'connect' timed out.")
+  else:
+    when defined(ssl):
+      if socket.isSSL:
+        socket.fd.setBlocking(true)
+        doAssert socket.handshake()
+  socket.fd.setBlocking(true)
diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim
index e2397b91c..5a7deaab0 100644
--- a/lib/pure/nimprof.nim
+++ b/lib/pure/nimprof.nim
@@ -12,7 +12,7 @@
 ## report at program exit.
 
 when not defined(profiler) and not defined(memProfiler):
-  {.warning: "Profiling support is turned off!".}
+  {.error: "Profiling support is turned off! Enable profiling by passing `--profiler:on --stackTrace:on` to the compiler (see the Nim Compiler User Guide for more options).".}
 
 # We don't want to profile the profiling code ...
 {.push profiler: off.}
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 1e00f92b1..a92b74484 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -774,6 +774,7 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} =
       res: int
     res = findFirstFile(pattern, f)
     if res != -1:
+      defer: findClose(res)
       while true:
         if not skipFindData(f) and
             (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) == 0'i32:
@@ -786,7 +787,6 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} =
               pattern[dotPos+1] == '*':
             yield splitFile(pattern).dir / extractFilename(ff)
         if findNextFile(res, f) == 0'i32: break
-      findClose(res)
   else: # here we use glob
     var
       f: Glob
@@ -795,11 +795,11 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} =
     f.gl_pathc = 0
     f.gl_pathv = nil
     res = glob(pattern, 0, nil, addr(f))
+    defer: globfree(addr(f))
     if res == 0:
       for i in 0.. f.gl_pathc - 1:
         assert(f.gl_pathv[i] != nil)
         yield $f.gl_pathv[i]
-    globfree(addr(f))
 
 type
   PathComponent* = enum   ## Enumeration specifying a path component.
@@ -845,6 +845,7 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
       var f: WIN32_FIND_DATA
       var h = findFirstFile(dir / "*", f)
       if h != -1:
+        defer: findClose(h)
         while true:
           var k = pcFile
           if not skipFindData(f):
@@ -856,10 +857,10 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
                      else: dir / extractFilename(getFilename(f))
             yield (k, xx)
           if findNextFile(h, f) == 0'i32: break
-        findClose(h)
     else:
       var d = opendir(dir)
       if d != nil:
+        defer: discard closedir(d)
         while true:
           var x = readdir(d)
           if x == nil: break
@@ -883,7 +884,6 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
             if S_ISDIR(s.st_mode): k = pcDir
             if S_ISLNK(s.st_mode): k = succ(k)
             yield (k, y)
-        discard closedir(d)
 
 iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
   tags: [ReadDirEffect].} =
diff --git a/lib/pure/ospaths.nim b/lib/pure/ospaths.nim
index e9f5bee0a..9fc816f2f 100644
--- a/lib/pure/ospaths.nim
+++ b/lib/pure/ospaths.nim
@@ -567,7 +567,9 @@ when declared(getEnv) or defined(nimscript):
     var path = string(getEnv("PATH"))
     for candidate in split(path, PathSep):
       when defined(windows):
-        var x = candidate / result
+        var x = (if candidate[0] == '"' and candidate[^1] == '"':
+                  substr(candidate, 1, candidate.len-2) else: candidate) /
+               result
       else:
         var x = expandTilde(candidate) / result
       if existsFile(x): return x
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 8560c3ee4..38b0ed4a3 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -876,7 +876,7 @@ elif not defined(useNimRtl):
       let sizeRead = read(data.pErrorPipe[readIdx], addr error, sizeof(error))
       if sizeRead == sizeof(error):
         raiseOSError("Could not find command: '$1'. OS error: $2" %
-            [$data.sysCommand, $strerror(error)])
+          [$data.sysCommand, $strerror(error)])
 
       return pid
 
@@ -886,7 +886,7 @@ elif not defined(useNimRtl):
     discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error))
     exitnow(1)
 
-  when defined(macosx) or defined(freebsd) or defined(netbsd) or defined(android):
+  when not defined(uClibc) and (not defined(linux) or defined(android)):
     var environ {.importc.}: cstringArray
 
   proc startProcessAfterFork(data: ptr StartProcessData) =
@@ -916,17 +916,16 @@ elif not defined(useNimRtl):
     discard fcntl(data.pErrorPipe[writeIdx], F_SETFD, FD_CLOEXEC)
 
     if data.optionPoUsePath:
-      when defined(macosx) or defined(freebsd) or defined(netbsd) or defined(android):
+      when defined(uClibc):
+        # uClibc environment (OpenWrt included) doesn't have the full execvpe
+        discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
+      elif defined(linux) and not defined(android):
+        discard execvpe(data.sysCommand, data.sysArgs, data.sysEnv)
+      else:
         # MacOSX doesn't have execvpe, so we need workaround.
         # On MacOSX we can arrive here only from fork, so this is safe:
         environ = data.sysEnv
         discard execvp(data.sysCommand, data.sysArgs)
-      else:
-        when defined(uClibc):
-          # 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)
     else:
       discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
 
diff --git a/lib/pure/securehash.nim b/lib/pure/securehash.nim
index 8ac6acb0e..657782889 100644
--- a/lib/pure/securehash.nim
+++ b/lib/pure/securehash.nim
@@ -7,8 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-import
-  strutils, unsigned
+import strutils
 
 const Sha1DigestSize = 20
 
diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim
index 832f5f4f9..89e92c133 100644
--- a/lib/pure/selectors.nim
+++ b/lib/pure/selectors.nim
@@ -9,7 +9,7 @@
 
 # TODO: Docs.
 
-import os, unsigned, hashes
+import os, hashes
 
 when defined(linux):
   import posix, epoll
@@ -118,7 +118,7 @@ elif defined(linux):
         # are therefore constantly ready. (leading to 100% CPU usage).
         if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0:
           raiseOSError(osLastError())
-        s.fds.mget(fd).events = events
+        s.fds[fd].events = events
       else:
         var event = createEventStruct(events, fd)
         if s.fds[fd].events == {}:
@@ -129,7 +129,7 @@ elif defined(linux):
         else:
           if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0:
             raiseOSError(osLastError())
-        s.fds.mget(fd).events = events
+        s.fds[fd].events = events
 
   proc unregister*(s: var Selector, fd: SocketHandle) =
     if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0:
@@ -229,7 +229,7 @@ elif defined(macosx) or defined(freebsd) or defined(openbsd) or defined(netbsd):
         modifyKQueue(s.kqFD, fd, event, EV_ADD)
       for event in previousEvents-events:
         modifyKQueue(s.kqFD, fd, event, EV_DELETE)
-      s.fds.mget(fd).events = events
+      s.fds[fd].events = events
 
   proc unregister*(s: var Selector, fd: SocketHandle) =
     for event in s.fds[fd].events:
@@ -298,7 +298,7 @@ elif not defined(nimdoc):
   proc update*(s: var Selector, fd: SocketHandle, events: set[Event]) =
     #if not s.fds.hasKey(fd):
     #  raise newException(ValueError, "File descriptor not found.")
-    s.fds.mget(fd).events = events
+    s.fds[fd].events = events
 
   proc unregister*(s: var Selector, fd: SocketHandle) =
     s.fds.del(fd)
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index 38e91fee4..bb6175a12 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -148,7 +148,10 @@ proc write*[T](s: Stream, x: T) =
 proc write*(s: Stream, x: string) =
   ## writes the string `x` to the the stream `s`. No length field or
   ## terminating zero is written.
-  writeData(s, cstring(x), x.len)
+  when nimvm:
+    writeData(s, cstring(x), x.len)
+  else:
+    if x.len > 0: writeData(s, unsafeAddr x[0], x.len)
 
 proc writeLn*(s: Stream, args: varargs[string, `$`]) {.deprecated.} =
   ## **Deprecated since version 0.11.4:** Use **writeLine** instead.
diff --git a/lib/system.nim b/lib/system.nim
index e884e784c..2c049b6b6 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -151,7 +151,7 @@ proc `addr`*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} =
   ##  echo cast[ptr char](p)[]    # b
   discard
 
-proc unsafeAddr*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} =
+proc unsafeAddr*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} =
   ## Builtin 'addr' operator for taking the address of a memory location.
   ## This works even for ``let`` variables or parameters for better interop
   ## with C and so it is considered even more unsafe than the ordinary ``addr``.
@@ -1811,7 +1811,7 @@ const
   NimMinor*: int = 13
     ## is the minor number of Nim's version.
 
-  NimPatch*: int = 0
+  NimPatch*: int = 1
     ## is the patch number of Nim's version.
 
   NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
@@ -2452,14 +2452,17 @@ type
 
 when defined(JS):
   proc add*(x: var string, y: cstring) {.asmNoStackFrame.} =
-    asm """
-      var len = `x`[0].length-1;
-      for (var i = 0; i < `y`.length; ++i) {
-        `x`[0][len] = `y`.charCodeAt(i);
-        ++len;
-      }
-      `x`[0][len] = 0
-    """
+    when defined(nimphp):
+      asm """`x` .= `y`;"""
+    else:
+      asm """
+        var len = `x`[0].length-1;
+        for (var i = 0; i < `y`.length; ++i) {
+          `x`[0][len] = `y`.charCodeAt(i);
+          ++len;
+        }
+        `x`[0][len] = 0
+      """
   proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".}
 
 elif hasAlloc:
@@ -2960,9 +2963,9 @@ when not defined(JS): #and not defined(nimscript):
       ##       buffer.add(line.replace("a", "0") & '\x0A')
       ##     writeFile(filename, buffer)
       var f = open(filename, bufSize=8000)
+      defer: close(f)
       var res = TaintedString(newStringOfCap(80))
       while f.readLine(res): yield res
-      close(f)
 
     iterator lines*(f: File): TaintedString {.tags: [ReadIOEffect].} =
       ## Iterate over any line in the file `f`.
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index b4462ed83..6de8e19e7 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -688,7 +688,7 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
     sysAssert(((cast[ByteAddress](p) and PageMask) - smallChunkOverhead()) %%
                s == 0, "rawDealloc 3")
     var f = cast[ptr FreeCell](p)
-    #echo("setting to nil: ", $cast[TAddress](addr(f.zeroField)))
+    #echo("setting to nil: ", $cast[ByteAddress](addr(f.zeroField)))
     sysAssert(f.zeroField != 0, "rawDealloc 1")
     f.zeroField = 0
     f.next = c.freeList
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index c25cf4606..d8390ca14 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -325,6 +325,8 @@ proc cellsetReset(s: var CellSet) =
   deinit(s)
   init(s)
 
+{.push stacktrace:off.}
+
 proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
   var d = cast[ByteAddress](dest)
   case n.kind
@@ -459,7 +461,8 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
   result = cellToUsr(res)
   sysAssert(allocInv(gch.region), "rawNewObj end")
 
-{.pop.}
+{.pop.} # .stackTrace off
+{.pop.} # .profiler off
 
 proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
   result = rawNewObj(typ, size, gch)
@@ -576,7 +579,7 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
 proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
   result = growObj(old, newsize, gch)
 
-{.push profiler:off.}
+{.push profiler:off, stackTrace:off.}
 
 # ---------------- cycle collector -------------------------------------------
 
@@ -659,7 +662,7 @@ when useMarkForDebug or useBackupGc:
   proc stackMarkS(gch: var GcHeap, p: pointer) {.inline.} =
     # the addresses are not as cells on the stack, so turn them to cells:
     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))
@@ -805,8 +808,8 @@ proc markThreadStacks(gch: var GcHeap) =
     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:
@@ -1018,4 +1021,4 @@ when not defined(useNimRtl):
       result = result & "[GC] max stack size: " & $gch.stat.maxStackSize & "\n"
     GC_enable()
 
-{.pop.}
+{.pop.} # profiler: off, stackTrace: off
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index e68a8586e..6b6b81824 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -104,8 +104,6 @@ when not defined(useNimRtl):
 
 proc initGC() =
   when not defined(useNimRtl):
-    when traceGC:
-      for i in low(CellState)..high(CellState): init(states[i])
     gch.cycleThreshold = InitialCycleThreshold
     gch.stat.stackScans = 0
     gch.stat.cycleCollections = 0
@@ -168,8 +166,10 @@ proc writeCell(msg: cstring, c: PCell) =
     c_fprintf(c_stdout, "[GC] %s: %p %d rc=%ld; color=%ld\n",
               msg, c, kind, c.refcount shr rcShift, c.color)
 
+proc myastToStr[T](x: T): string {.magic: "AstToStr", noSideEffect.}
+
 template gcTrace(cell, state: expr): stmt {.immediate.} =
-  when traceGC: traceCell(cell, state)
+  when traceGC: writeCell(myastToStr(state), cell)
 
 # forward declarations:
 proc collectCT(gch: var GcHeap) {.benign.}
@@ -568,7 +568,7 @@ template takeTime {.dirty.} =
 
 template checkTime {.dirty.} =
   if debugticker <= 0:
-    echo "in loop"
+    #echo "in loop"
     debugticker = 1000
   when withRealTime:
     if steps == 0:
@@ -602,8 +602,9 @@ proc freeCyclicCell(gch: var GcHeap, c: PCell) =
 
 proc sweep(gch: var GcHeap): bool =
   takeStartTime(100)
-  echo "loop start"
+  #echo "loop start"
   let black = gch.black
+  cfprintf(cstdout, "black is %d\n", black)
   while true:
     let x = allObjectsAsProc(gch.region, addr gch.spaceIter)
     if gch.spaceIter.state < 0: break
@@ -619,7 +620,7 @@ proc sweep(gch: var GcHeap): bool =
       # traversal over the heap!
     checkTime()
   # prepare for next iteration:
-  echo "loop end"
+  #echo "loop end"
   gch.spaceIter = ObjectSpaceIter()
   result = true
 
@@ -634,6 +635,9 @@ proc markIncremental(gch: var GcHeap): bool =
   takeStartTime(100)
   while L[] > 0:
     var c = gch.greyStack.d[0]
+    if not isAllocatedPtr(gch.region, c):
+      c_fprintf(c_stdout, "[GC] not allocated anymore: %p\n", c)
+
     sysAssert(isAllocatedPtr(gch.region, c), "markIncremental: isAllocatedPtr")
     gch.greyStack.d[0] = gch.greyStack.d[L[] - 1]
     dec(L[])
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index 47e8b4b1f..013dc55f8 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -78,19 +78,29 @@ iterator items(stack: ptr GcStack): ptr GcStack =
     yield s
     s = s.next
 
-var
-  localGcInitialized {.rtlThreadVar.}: bool
+# There will be problems with GC in foreign threads if `threads` option is off or TLS emulation is enabled
+const allowForeignThreadGc = compileOption("threads") and not compileOption("tlsEmulation")
 
-proc setupForeignThreadGc*() =
-  ## call this if you registered a callback that will be run from a thread not
-  ## under your control. This has a cheap thread-local guard, so the GC for
-  ## this thread will only be initialized once per thread, no matter how often
-  ## it is called.
-  if not localGcInitialized:
-    localGcInitialized = true
-    var stackTop {.volatile.}: pointer
-    setStackBottom(addr(stackTop))
-    initGC()
+when allowForeignThreadGc:
+  var
+    localGcInitialized {.rtlThreadVar.}: bool
+
+  proc setupForeignThreadGc*() =
+    ## Call this if you registered a callback that will be run from a thread not
+    ## under your control. This has a cheap thread-local guard, so the GC for
+    ## this thread will only be initialized once per thread, no matter how often
+    ## it is called.
+    ##
+    ## This function is availble only when ``--threads:on`` and ``--tlsEmulation:off``
+    ## switches are used
+    if not localGcInitialized:
+      localGcInitialized = true
+      var stackTop {.volatile.}: pointer
+      setStackBottom(addr(stackTop))
+      initGC()
+else:
+  template setupForeignThreadGc*(): stmt =
+    {.error: "setupForeignThreadGc is availble only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
 
 # ----------------- stack management --------------------------------------
 #  inspired from Smart Eiffel
@@ -131,9 +141,9 @@ 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
 
   template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
@@ -150,7 +160,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".}
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 5bac54772..ceeb5563f 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -1,7 +1,7 @@
 #
 #
 #            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.
@@ -61,7 +61,6 @@ proc getCurrentExceptionMsg*(): string =
 proc auxWriteStackTrace(f: PCallFrame): string =
   type
     TempFrame = tuple[procname: cstring, line: int]
-  {.deprecated: [TTempFrame: TempFrame].}
   var
     it = f
     i = 0
@@ -128,8 +127,11 @@ proc reraiseException() {.compilerproc, asmNoStackFrame.} =
   else:
     when not defined(noUnhandledHandler):
       if excHandler == 0:
-        var isNimException : bool
-        asm "`isNimException` = lastJSError.m_type;"
+        var isNimException: bool
+        when defined(nimphp):
+          asm "`isNimException` = isset(`lastJSError`['m_type']);"
+        else:
+          asm "`isNimException` = lastJSError.m_type;"
         if isNimException:
           unhandledException(cast[ref Exception](lastJSError))
     asm "throw lastJSError;"
@@ -150,33 +152,89 @@ proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
   raise newException(FieldError, f & " is not accessible")
 
 proc SetConstr() {.varargs, asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = {};
-    for (var i = 0; i < arguments.length; ++i) {
-      var x = arguments[i];
-      if (typeof(x) == "object") {
-        for (var j = x[0]; j <= x[1]; ++j) {
-          result[j] = true;
+  when defined(nimphp):
+    asm """
+      $args = func_get_args();
+      $result = array();
+      foreach ($args as $x) {
+        if (is_array($x)) {
+          for ($j = $x[0]; $j <= $x[1]; $j++) {
+            $result[$j] = true;
+          }
+        } else {
+          $result[$x] = true;
+        }
+      }
+      return $result;
+    """
+  else:
+    asm """
+      var result = {};
+      for (var i = 0; i < arguments.length; ++i) {
+        var x = arguments[i];
+        if (typeof(x) == "object") {
+          for (var j = x[0]; j <= x[1]; ++j) {
+            result[j] = true;
+          }
+        } else {
+          result[x] = true;
         }
-      } else {
-        result[x] = true;
       }
+      return result;
+    """
+
+proc makeNimstrLit(c: cstring): string {.asmNoStackFrame, compilerproc.} =
+  when defined(nimphp):
+    {.emit: """return `c`;""".}
+  else:
+    {.emit: """
+    var ln = `c`.length;
+    var result = new Array(ln + 1);
+    var i = 0;
+    for (; i < ln; ++i) {
+      result[i] = `c`.charCodeAt(i);
     }
+    result[i] = 0; // terminating zero
     return result;
-  """
+    """.}
 
 proc cstrToNimstr(c: cstring): string {.asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = [];
-    for (var i = 0; i < `c`.length; ++i) {
-      result[i] = `c`.charCodeAt(i);
+  when defined(nimphp):
+    {.emit: """return `c`;""".}
+  else:
+    {.emit: """
+  var ln = `c`.length;
+  var result = new Array(ln);
+  var r = 0;
+  for (var i = 0; i < ln; ++i) {
+    var ch = `c`.charCodeAt(i);
+
+    if (ch < 128) {
+      result[r] = ch;
     }
-    result[result.length] = 0; // terminating zero
-    return result;
-  """
+    else if((ch > 127) && (ch < 2048)) {
+      result[r] = (ch >> 6) | 192;
+      ++r;
+      result[r] = (ch & 63) | 128;
+    }
+    else {
+      result[r] = (ch >> 12) | 224;
+      ++r;
+      result[r] = ((ch >> 6) & 63) | 128;
+      ++r;
+      result[r] = (ch & 63) | 128;
+    }
+    ++r;
+  }
+  result[r] = 0; // terminating zero
+  return result;
+  """.}
 
 proc toJSStr(s: string): cstring {.asmNoStackFrame, compilerproc.} =
-  asm """
+  when defined(nimphp):
+    {.emit: """return `s`;""".}
+  else:
+    asm """
     var len = `s`.length-1;
     var asciiPart = new Array(len);
     var fcc = String.fromCharCode;
@@ -203,62 +261,118 @@ proc toJSStr(s: string): cstring {.asmNoStackFrame, compilerproc.} =
   """
 
 proc mnewString(len: int): string {.asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = new Array(`len`+1);
-    result[0] = 0;
-    result[`len`] = 0;
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      $result = array();
+      for($i = 0; $i < `len`; $i++) $result[] = chr(0);
+      return $result;
+    """
+  else:
+    asm """
+      var result = new Array(`len`+1);
+      result[0] = 0;
+      result[`len`] = 0;
+      return result;
+    """
+
+when defined(nimphp):
+  proc nimSubstr(s: string; a, b: int): string {.
+      asmNoStackFrame, compilerproc.} =
+    asm """return substr(`s`,`a`,`b`-`a`+1);"""
 
 proc SetCard(a: int): int {.compilerproc, asmNoStackFrame.} =
   # argument type is a fake
-  asm """
-    var result = 0;
-    for (var elem in `a`) { ++result; }
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      return count(`a`);
+    """
+  else:
+    asm """
+      var result = 0;
+      for (var elem in `a`) { ++result; }
+      return result;
+    """
 
 proc SetEq(a, b: int): bool {.compilerproc, asmNoStackFrame.} =
-  asm """
-    for (var elem in `a`) { if (!`b`[elem]) return false; }
-    for (var elem in `b`) { if (!`a`[elem]) return false; }
-    return true;
-  """
+  when defined(nimphp):
+    asm """
+      foreach (`a` as $elem=>$_) { if (!isset(`b`[$elem])) return false; }
+      foreach (`b` as $elem=>$_) { if (!isset(`a`[$elem])) return false; }
+      return true;
+    """
+  else:
+    asm """
+      for (var elem in `a`) { if (!`b`[elem]) return false; }
+      for (var elem in `b`) { if (!`a`[elem]) return false; }
+      return true;
+    """
 
 proc SetLe(a, b: int): bool {.compilerproc, asmNoStackFrame.} =
-  asm """
-    for (var elem in `a`) { if (!`b`[elem]) return false; }
-    return true;
-  """
+  when defined(nimphp):
+    asm """
+      foreach (`a` as $elem=>$_) { if (!isset(`b`[$elem])) return false; }
+      return true;
+    """
+  else:
+    asm """
+      for (var elem in `a`) { if (!`b`[elem]) return false; }
+      return true;
+    """
 
 proc SetLt(a, b: int): bool {.compilerproc.} =
   result = SetLe(a, b) and not SetEq(a, b)
 
 proc SetMul(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-  asm """
-    var result = {};
-    for (var elem in `a`) {
-      if (`b`[elem]) { result[elem] = true; }
-    }
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      var $result = array();
+      foreach (`a` as $elem=>$_) {
+        if (isset(`b`[$elem])) { $result[$elem] = true; }
+      }
+      return $result;
+    """
+  else:
+    asm """
+      var result = {};
+      for (var elem in `a`) {
+        if (`b`[elem]) { result[elem] = true; }
+      }
+      return result;
+    """
 
 proc SetPlus(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-  asm """
-    var result = {};
-    for (var elem in `a`) { result[elem] = true; }
-    for (var elem in `b`) { result[elem] = true; }
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      var $result = array();
+      foreach (`a` as $elem=>$_) { $result[$elem] = true; }
+      foreach (`b` as $elem=>$_) { $result[$elem] = true; }
+      return $result;
+    """
+  else:
+    asm """
+      var result = {};
+      for (var elem in `a`) { result[elem] = true; }
+      for (var elem in `b`) { result[elem] = true; }
+      return result;
+    """
 
 proc SetMinus(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-  asm """
-    var result = {};
-    for (var elem in `a`) {
-      if (!`b`[elem]) { result[elem] = true; }
-    }
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      $result = array();
+      foreach (`a` as $elem=>$_) {
+        if (!isset(`b`[$elem])) { $result[$elem] = true; }
+      }
+      return $result;
+    """
+  else:
+    asm """
+      var result = {};
+      for (var elem in `a`) {
+        if (!`b`[elem]) { result[elem] = true; }
+      }
+      return result;
+    """
 
 proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerProc.} =
   asm """
@@ -272,7 +386,15 @@ proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerProc.} =
     return 0;
   """
 
-proc cmp(x, y: string): int = return cmpStrings(x, y)
+proc cmp(x, y: string): int =
+  when defined(nimphp):
+    asm """
+      if(`x` < `y`) `result` = -1;
+      elseif (`x` > `y`) `result` = 1;
+      else `result` = 0;
+    """
+  else:
+    return cmpStrings(x, y)
 
 proc eqStrings(a, b: string): bool {.asmNoStackFrame, compilerProc.} =
   asm """
@@ -307,7 +429,7 @@ elif defined(nodejs):
       console.log(buf);
     """
 
-else:
+elif not defined(nimphp):
   proc ewriteln(x: cstring) =
     var node : JSRef
     {.emit: "`node` = document.getElementsByTagName('body')[0];".}
@@ -333,77 +455,127 @@ else:
 
 # Arithmetic:
 proc addInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = `a` + `b`;
-    if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      return `a` + `b`;
+    """
+  else:
+    asm """
+      var result = `a` + `b`;
+      if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
+      return result;
+    """
 
 proc subInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = `a` - `b`;
-    if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      return `a` - `b`;
+    """
+  else:
+    asm """
+      var result = `a` - `b`;
+      if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
+      return result;
+    """
 
 proc mulInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = `a` * `b`;
-    if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      return `a` * `b`;
+    """
+  else:
+    asm """
+      var result = `a` * `b`;
+      if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
+      return result;
+    """
 
 proc divInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    if (`b` == 0) `raiseDivByZero`();
-    if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
-    return Math.floor(`a` / `b`);
-  """
+  when defined(nimphp):
+    asm """
+      return floor(`a` / `b`);
+    """
+  else:
+    asm """
+      if (`b` == 0) `raiseDivByZero`();
+      if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
+      return Math.floor(`a` / `b`);
+    """
 
 proc modInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    if (`b` == 0) `raiseDivByZero`();
-    if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
-    return Math.floor(`a` % `b`);
-  """
+  when defined(nimphp):
+    asm """
+      return `a` % `b`;
+    """
+  else:
+    asm """
+      if (`b` == 0) `raiseDivByZero`();
+      if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
+      return Math.floor(`a` % `b`);
+    """
 
 proc addInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = `a` + `b`;
-    if (result > 9223372036854775807
-    || result < -9223372036854775808) `raiseOverflow`();
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      return `a` + `b`;
+    """
+  else:
+    asm """
+      var result = `a` + `b`;
+      if (result > 9223372036854775807
+      || result < -9223372036854775808) `raiseOverflow`();
+      return result;
+    """
 
 proc subInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = `a` - `b`;
-    if (result > 9223372036854775807
-    || result < -9223372036854775808) `raiseOverflow`();
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      return `a` - `b`;
+    """
+  else:
+    asm """
+      var result = `a` - `b`;
+      if (result > 9223372036854775807
+      || result < -9223372036854775808) `raiseOverflow`();
+      return result;
+    """
 
 proc mulInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = `a` * `b`;
-    if (result > 9223372036854775807
-    || result < -9223372036854775808) `raiseOverflow`();
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      return `a` * `b`;
+    """
+  else:
+    asm """
+      var result = `a` * `b`;
+      if (result > 9223372036854775807
+      || result < -9223372036854775808) `raiseOverflow`();
+      return result;
+    """
 
 proc divInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    if (`b` == 0) `raiseDivByZero`();
-    if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
-    return Math.floor(`a` / `b`);
-  """
+  when defined(nimphp):
+    asm """
+      return floor(`a` / `b`);
+    """
+  else:
+    asm """
+      if (`b` == 0) `raiseDivByZero`();
+      if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
+      return Math.floor(`a` / `b`);
+    """
 
 proc modInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    if (`b` == 0) `raiseDivByZero`();
-    if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
-    return Math.floor(`a` % `b`);
-  """
+  when defined(nimphp):
+    asm """
+      return `a` % `b`;
+    """
+  else:
+    asm """
+      if (`b` == 0) `raiseDivByZero`();
+      if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
+      return Math.floor(`a` % `b`);
+    """
 
 proc negInt(a: int): int {.compilerproc.} =
   result = a*(-1)
@@ -417,42 +589,6 @@ proc absInt(a: int): int {.compilerproc.} =
 proc absInt64(a: int64): int64 {.compilerproc.} =
   result = if a < 0: a*(-1) else: a
 
-proc leU(a, b: int): bool {.compilerproc.} =
-  result = abs(a) <= abs(b)
-
-proc ltU(a, b: int): bool {.compilerproc.} =
-  result = abs(a) < abs(b)
-
-proc leU64(a, b: int64): bool {.compilerproc.} =
-  result = abs(a) <= abs(b)
-proc ltU64(a, b: int64): bool {.compilerproc.} =
-  result = abs(a) < abs(b)
-
-proc addU(a, b: int): int {.compilerproc.} =
-  result = abs(a) + abs(b)
-proc addU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) + abs(b)
-
-proc subU(a, b: int): int {.compilerproc.} =
-  result = abs(a) - abs(b)
-proc subU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) - abs(b)
-
-proc mulU(a, b: int): int {.compilerproc.} =
-  result = abs(a) * abs(b)
-proc mulU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) * abs(b)
-
-proc divU(a, b: int): int {.compilerproc.} =
-  result = abs(a) div abs(b)
-proc divU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) div abs(b)
-
-proc modU(a, b: int): int {.compilerproc.} =
-  result = abs(a) mod abs(b)
-proc modU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) mod abs(b)
-
 proc ze*(a: int): int {.compilerproc.} =
   result = a
 
@@ -592,11 +728,18 @@ proc genericReset(x: JSRef, ti: PNimType): JSRef {.compilerproc.} =
 proc arrayConstr(len: int, value: JSRef, typ: PNimType): JSRef {.
                  asmNoStackFrame, compilerproc.} =
   # types are fake
-  asm """
-    var result = new Array(`len`);
-    for (var i = 0; i < `len`; ++i) result[i] = nimCopy(null, `value`, `typ`);
-    return result;
-  """
+  when defined(nimphp):
+    asm """
+      $result = array();
+      for ($i = 0; $i < `len`; $i++) $result[] = `value`;
+      return $result;
+    """
+  else:
+    asm """
+      var result = new Array(`len`);
+      for (var i = 0; i < `len`; ++i) result[i] = nimCopy(null, `value`, `typ`);
+      return result;
+    """
 
 proc chckIndx(i, a, b: int): int {.compilerproc.} =
   if i >= a and i <= b: return i
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index 1c13f3ff8..2e0fecd49 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -16,8 +16,8 @@
 const
   debugGC = false # we wish to debug the GC...
   logGC = false
-  traceGC = false # extensive debugging
-  alwaysCycleGC = false
+  traceGC = defined(smokeCycles) # extensive debugging
+  alwaysCycleGC = defined(smokeCycles)
   alwaysGC = defined(fulldebug) # collect after every memory
                                 # allocation (for debugging)
   leakDetector = false
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index 7aef86df9..7da45b4dd 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -138,7 +138,7 @@ proc slave(w: ptr Worker) {.thread.} =
 const NumThreads = 4
 
 var
-  workers: array[NumThreads, TThread[ptr Worker]]
+  workers: array[NumThreads, Thread[ptr Worker]]
   workersData: array[NumThreads, Worker]
 
 proc setup() =
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 4962186fb..d00964a6d 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -12,9 +12,18 @@
 
 {.deadCodeElim:on.}
 
+import dynlib
+
 const
   useWinUnicode* = not defined(useWinAnsi)
 
+when useWinUnicode:
+  type WinChar* = Utf16Char
+  {.deprecated: [TWinChar: WinChar].}
+else:
+  type WinChar* = char
+  {.deprecated: [TWinChar: WinChar].}
+
 type
   Handle* = int
   LONG* = int32
@@ -74,17 +83,18 @@ type
     nFileIndexHigh*: DWORD
     nFileIndexLow*: DWORD
 
+  OSVERSIONINFO* {.final, pure.} = object
+    dwOSVersionInfoSize*: DWORD
+    dwMajorVersion*: DWORD
+    dwMinorVersion*: DWORD
+    dwBuildNumber*: DWORD
+    dwPlatformId*: DWORD
+    szCSDVersion*: array[0..127, WinChar];
+
 {.deprecated: [THandle: Handle, TSECURITY_ATTRIBUTES: SECURITY_ATTRIBUTES,
     TSTARTUPINFO: STARTUPINFO, TPROCESS_INFORMATION: PROCESS_INFORMATION,
     TFILETIME: FILETIME, TBY_HANDLE_FILE_INFORMATION: BY_HANDLE_FILE_INFORMATION].}
 
-when useWinUnicode:
-  type WinChar* = Utf16Char
-  {.deprecated: [TWinChar: WinChar].}
-else:
-  type WinChar* = char
-  {.deprecated: [TWinChar: WinChar].}
-
 const
   STARTF_USESHOWWINDOW* = 1'i32
   STARTF_USESTDHANDLES* = 256'i32
@@ -117,6 +127,13 @@ const
 
   CREATE_NO_WINDOW* = 0x08000000'i32
 
+when useWinUnicode:
+  proc getVersionExW*(lpVersionInfo: ptr OSVERSIONINFO): WINBOOL {.stdcall, dynlib: "kernel32", importc: "GetVersionExW".}
+else:
+  proc getVersionExA*(lpVersionInfo: ptr OSVERSIONINFO): WINBOOL {.stdcall, dynlib: "kernel32", importc: "GetVersionExA".}
+
+proc getVersion*(): DWORD {.stdcall, dynlib: "kernel32", importc: "GetVersion".}
+
 proc closeHandle*(hObject: Handle): WINBOOL {.stdcall, dynlib: "kernel32",
     importc: "CloseHandle".}
 
@@ -192,6 +209,9 @@ proc flushFileBuffers*(hFile: Handle): WINBOOL {.stdcall, dynlib: "kernel32",
 proc getLastError*(): int32 {.importc: "GetLastError",
     stdcall, dynlib: "kernel32".}
 
+proc setLastError*(error: int32) {.importc: "SetLastError",
+    stdcall, dynlib: "kernel32".}
+
 when useWinUnicode:
   proc formatMessageW*(dwFlags: int32, lpSource: pointer,
                       dwMessageId, dwLanguageId: int32,
@@ -289,9 +309,9 @@ when useWinUnicode:
       stdcall, dynlib: "kernel32", importc: "FindNextFileW".}
 else:
   proc findFirstFileA*(lpFileName: cstring,
-                      lpFindFileData: var WIN32_FIND_DATA): THANDLE {.
+                      lpFindFileData: var WIN32_FIND_DATA): Handle {.
       stdcall, dynlib: "kernel32", importc: "FindFirstFileA".}
-  proc findNextFileA*(hFindFile: THANDLE,
+  proc findNextFileA*(hFindFile: Handle,
                      lpFindFileData: var WIN32_FIND_DATA): int32 {.
       stdcall, dynlib: "kernel32", importc: "FindNextFileA".}
 
@@ -597,9 +617,6 @@ proc freeaddrinfo*(ai: ptr AddrInfo) {.
 proc inet_ntoa*(i: InAddr): cstring {.
   stdcall, importc, dynlib: ws2dll.}
 
-proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
-            stringBufSize: int32): cstring {.stdcall, importc, dynlib: ws2dll.}
-
 const
   MAXIMUM_WAIT_OBJECTS* = 0x00000040
 
@@ -645,6 +662,7 @@ const
 const
   ERROR_ACCESS_DENIED* = 5
   ERROR_HANDLE_EOF* = 38
+  ERROR_BAD_ARGUMENTS* = 165
 
 proc duplicateHandle*(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE,
                       hTargetProcessHandle: HANDLE,
@@ -667,7 +685,7 @@ else:
   proc createFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD,
                     lpSecurityAttributes: pointer,
                     dwCreationDisposition, dwFlagsAndAttributes: DWORD,
-                    hTemplateFile: THANDLE): THANDLE {.
+                    hTemplateFile: Handle): Handle {.
       stdcall, dynlib: "kernel32", importc: "CreateFileA".}
   proc deleteFileA*(pathName: cstring): int32 {.
     importc: "DeleteFileA", dynlib: "kernel32", stdcall.}
@@ -697,10 +715,10 @@ proc createFileMappingW*(hFile: Handle,
   stdcall, dynlib: "kernel32", importc: "CreateFileMappingW".}
 
 when not useWinUnicode:
-  proc createFileMappingA*(hFile: THANDLE,
+  proc createFileMappingA*(hFile: Handle,
                            lpFileMappingAttributes: pointer,
                            flProtect, dwMaximumSizeHigh: DWORD,
-                           dwMaximumSizeLow: DWORD, lpName: cstring): THANDLE {.
+                           dwMaximumSizeLow: DWORD, lpName: cstring): Handle {.
       stdcall, dynlib: "kernel32", importc: "CreateFileMappingA".}
 
 proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall,
@@ -806,3 +824,54 @@ proc getSystemTimes*(lpIdleTime, lpKernelTime,
 proc getProcessTimes*(hProcess: Handle; lpCreationTime, lpExitTime,
   lpKernelTime, lpUserTime: var FILETIME): WINBOOL {.stdcall,
   dynlib: "kernel32", importc: "GetProcessTimes".}
+
+type inet_ntop_proc = proc(family: cint, paddr: pointer, pStringBuffer: cstring,
+                      stringBufSize: int32): cstring {.stdcall.}
+
+var inet_ntop_real: inet_ntop_proc = nil
+
+let l = loadLib(ws2dll)
+if l != nil:
+  inet_ntop_real = cast[inet_ntop_proc](symAddr(l, "inet_ntop"))
+
+proc WSAAddressToStringA(pAddr: ptr SockAddr, addrSize: DWORD, unused: pointer, pBuff: cstring, pBuffSize: ptr DWORD): cint {.stdcall, importc, dynlib: ws2dll.}
+proc inet_ntop_emulated(family: cint, paddr: pointer, pStringBuffer: cstring,
+                  stringBufSize: int32): cstring {.stdcall.} =
+    case family
+    of AF_INET:
+      var sa: Sockaddr_in
+      sa.sin_family = AF_INET
+      sa.sin_addr = cast[ptr InAddr](paddr)[]
+      var bs = stringBufSize.DWORD
+      let r = WSAAddressToStringA(cast[ptr SockAddr](sa.addr), sa.sizeof.DWORD, nil, pStringBuffer, bs.addr)
+      if r != 0:
+        result = nil
+      else:
+        result = pStringBuffer
+    of AF_INET6:
+      var sa: Sockaddr_in6
+      sa.sin6_family = AF_INET6
+      sa.sin6_addr = cast[ptr In6_addr](paddr)[]
+      var bs = stringBufSize.DWORD
+      let r = WSAAddressToStringA(cast[ptr SockAddr](sa.addr), sa.sizeof.DWORD, nil, pStringBuffer, bs.addr)
+      if r != 0:
+        result = nil
+      else:
+        result = pStringBuffer
+    else:
+      setLastError(ERROR_BAD_ARGUMENTS)
+      result = nil
+
+proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
+                  stringBufSize: int32): cstring {.stdcall.} =
+  var ver: OSVERSIONINFO
+  ver.dwOSVersionInfoSize = sizeof(ver).DWORD
+  let res = when useWinUnicode: getVersionExW(ver.addr) else: getVersionExA(ver.addr)
+  if res == 0:
+    result = nil
+  elif ver.dwMajorVersion >= 6:
+    if inet_ntop_real == nil:
+      quit("Can't load inet_ntop proc from " & ws2dll)
+    result = inet_ntop_real(family, paddr, pStringBuffer, stringBufSize)
+  else:
+    result = inet_ntop_emulated(family, paddr, pStringBuffer, stringBufSize)
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index a227ac98c..05843e2d3 100644
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
@@ -496,13 +496,12 @@ type
     data: array[MD5_LBLOCK, MD5_LONG]
     num: cuint
 
-{.pragma: ic, importc: "$1".}
 {.push callconv:cdecl, dynlib:DLLUtilName.}
-proc md5_Init*(c: var MD5_CTX): cint{.ic.}
-proc md5_Update*(c: var MD5_CTX; data: pointer; len: csize): cint{.ic.}
-proc md5_Final*(md: cstring; c: var MD5_CTX): cint{.ic.}
-proc md5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.ic.}
-proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.ic.}
+proc md5_Init*(c: var MD5_CTX): cint{.importc: "MD5_Init".}
+proc md5_Update*(c: var MD5_CTX; data: pointer; len: csize): cint{.importc: "MD5_Update".}
+proc md5_Final*(md: cstring; c: var MD5_CTX): cint{.importc: "MD5_Final".}
+proc md5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.importc: "MD5".}
+proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.importc: "MD5_Transform".}
 {.pop.}
 
 from strutils import toHex,toLower