summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2017-05-16 20:51:50 +0200
committerAraq <rumpf_a@web.de>2017-05-16 20:51:50 +0200
commit0f2648c56dec3681bb6e3b0d53c8a75f901c6b96 (patch)
treebf5d0761f2e9918e0082a8898624cb760204ec0b
parent321d1f8b65c1cb41995ad033ea1a6a11bb22df8d (diff)
parent0613f08b2461c5ecb64518a65e20c3769938d21e (diff)
downloadNim-0f2648c56dec3681bb6e3b0d53c8a75f901c6b96.tar.gz
Merge branch 'devel' of github.com:nim-lang/Nim into devel
-rw-r--r--compiler/vmdeps.nim7
-rw-r--r--lib/posix/posix.nim8
-rw-r--r--lib/posix/posix_linux_amd64.nim3
-rw-r--r--lib/posix/posix_linux_amd64_consts.nim3
-rw-r--r--lib/posix/posix_other_consts.nim4
-rw-r--r--lib/pure/asyncdispatch.nim6
-rw-r--r--lib/pure/asyncfile.nim10
-rw-r--r--lib/pure/ospaths.nim9
-rw-r--r--lib/pure/parsecfg.nim3
-rw-r--r--lib/system/excpt.nim9
-rw-r--r--lib/upcoming/asyncdispatch.nim2
-rw-r--r--tests/async/tasyncall.nim77
-rw-r--r--tests/async/tasyncfilewrite.nim17
-rw-r--r--tests/macros/tgettypeinst.nim65
-rw-r--r--tests/stdlib/tjsontestsuite.nim384
-rw-r--r--tests/testament/specs.nim11
-rw-r--r--tests/testament/tester.nim6
-rw-r--r--tools/detect/detect.nim11
-rw-r--r--web/news/e031_version_0_16_2.rst125
19 files changed, 684 insertions, 76 deletions
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 8c7388643..b2b1ec92b 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -175,7 +175,12 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
           result.add mapTypeToAst(t.sons[i], info)
     else:
       result = mapTypeToAstX(t.lastSon, info, inst, allowRecursion)
-  of tyGenericBody, tyOrdinal:
+  of tyGenericBody:
+    if inst:
+      result = mapTypeToAstX(t.lastSon, info, inst, true)
+    else:
+      result = mapTypeToAst(t.lastSon, info)
+  of tyOrdinal:
     result = mapTypeToAst(t.lastSon, info)
   of tyDistinct:
     if inst:
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index 02312a4d5..55d1dd2eb 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -79,6 +79,9 @@ const
   DT_SOCK* = 12   ## UNIX domain socket.
   DT_WHT* = 14
 
+# Special types
+type Sighandler = proc (a: cint) {.noconv.}
+
 # Platform specific stuff
 
 when defined(linux) and defined(amd64):
@@ -86,6 +89,9 @@ when defined(linux) and defined(amd64):
 else:
   include posix_other
 
+# There used to be this name in posix.nim a long time ago, not sure why!
+{.deprecated: [cSIG_HOLD: SIG_HOLD].}
+
 when not defined(macosx):
   proc st_atime*(s: Stat): Time {.inline.} =
     ## Second-granularity time of last access
@@ -659,7 +665,7 @@ proc sighold*(a1: cint): cint {.importc, header: "<signal.h>".}
 proc sigignore*(a1: cint): cint {.importc, header: "<signal.h>".}
 proc siginterrupt*(a1, a2: cint): cint {.importc, header: "<signal.h>".}
 proc sigismember*(a1: var Sigset, a2: cint): cint {.importc, header: "<signal.h>".}
-proc signal*(a1: cint, a2: proc (x: cint) {.noconv.}) {.
+proc signal*(a1: cint, a2: Sighandler) {.
   importc, header: "<signal.h>".}
 proc sigpause*(a1: cint): cint {.importc, header: "<signal.h>".}
 proc sigpending*(a1: var Sigset): cint {.importc, header: "<signal.h>".}
diff --git a/lib/posix/posix_linux_amd64.nim b/lib/posix/posix_linux_amd64.nim
index 70f7e710f..c44128b16 100644
--- a/lib/posix/posix_linux_amd64.nim
+++ b/lib/posix/posix_linux_amd64.nim
@@ -36,6 +36,9 @@ type
 
 {.deprecated: [TSocketHandle: SocketHandle].}
 
+# not detected by detect.nim, guarded by #ifdef __USE_UNIX98 in glibc
+const SIG_HOLD* = cast[SigHandler](2)
+
 type
   Timespec* {.importc: "struct timespec",
                header: "<time.h>", final, pure.} = object ## struct timespec
diff --git a/lib/posix/posix_linux_amd64_consts.nim b/lib/posix/posix_linux_amd64_consts.nim
index 9e2ed32e1..4b693960e 100644
--- a/lib/posix/posix_linux_amd64_consts.nim
+++ b/lib/posix/posix_linux_amd64_consts.nim
@@ -399,6 +399,9 @@ const SS_ONSTACK* = cint(1)
 const SS_DISABLE* = cint(2)
 const MINSIGSTKSZ* = cint(2048)
 const SIGSTKSZ* = cint(8192)
+const SIG_DFL* = cast[Sighandler](0)
+const SIG_ERR* = cast[Sighandler](-1)
+const SIG_IGN* = cast[Sighandler](1)
 
 # <sys/ipc.h>
 const IPC_CREAT* = cint(512)
diff --git a/lib/posix/posix_other_consts.nim b/lib/posix/posix_other_consts.nim
index f2a71d1bd..003414a6a 100644
--- a/lib/posix/posix_other_consts.nim
+++ b/lib/posix/posix_other_consts.nim
@@ -414,6 +414,10 @@ var SS_ONSTACK* {.importc: "SS_ONSTACK", header: "<signal.h>".}: cint
 var SS_DISABLE* {.importc: "SS_DISABLE", header: "<signal.h>".}: cint
 var MINSIGSTKSZ* {.importc: "MINSIGSTKSZ", header: "<signal.h>".}: cint
 var SIGSTKSZ* {.importc: "SIGSTKSZ", header: "<signal.h>".}: cint
+var SIG_HOLD* {.importc: "SIG_HOLD", header: "<signal.h>".}: Sighandler
+var SIG_DFL* {.importc: "SIG_DFL", header: "<signal.h>".}: Sighandler
+var SIG_ERR* {.importc: "SIG_ERR", header: "<signal.h>".}: Sighandler
+var SIG_IGN* {.importc: "SIG_IGN", header: "<signal.h>".}: Sighandler
 
 # <sys/ipc.h>
 var IPC_CREAT* {.importc: "IPC_CREAT", header: "<sys/ipc.h>".}: cint
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index e48fe8d94..8c1cf6b18 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -9,7 +9,7 @@
 
 include "system/inclrtl"
 
-import os, oids, tables, strutils, times, heapqueue, options
+import os, tables, strutils, times, heapqueue, options
 
 import nativesockets, net, deques
 
@@ -163,8 +163,8 @@ include includes/asyncfutures
 
 type
   PDispatcherBase = ref object of RootRef
-    timers: HeapQueue[tuple[finishAt: float, fut: Future[void]]]
-    callbacks: Deque[proc ()]
+    timers*: HeapQueue[tuple[finishAt: float, fut: Future[void]]]
+    callbacks*: Deque[proc ()]
 
 proc processTimers(p: PDispatcherBase) {.inline.} =
   #Process just part if timers at a step
diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim
index 9bd060e30..8fb30075c 100644
--- a/lib/pure/asyncfile.nim
+++ b/lib/pure/asyncfile.nim
@@ -339,13 +339,17 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] =
         if not retFuture.finished:
           if errcode == OSErrorCode(-1):
             assert bytesCount == size.int32
-            f.offset.inc(size)
             retFuture.complete()
           else:
             retFuture.fail(newException(OSError, osErrorMsg(errcode)))
     )
+    # passing -1 here should work according to MSDN, but doesn't. For more
+    # information see
+    # http://stackoverflow.com/questions/33650899/does-asynchronous-file-
+    #   appending-in-windows-preserve-order
     ol.offset = DWord(f.offset and 0xffffffff)
     ol.offsetHigh = DWord(f.offset shr 32)
+    f.offset.inc(size)
 
     # According to MSDN we're supposed to pass nil to lpNumberOfBytesWritten.
     let ret = writeFile(f.fd.Handle, buf, size.int32, nil,
@@ -364,7 +368,6 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] =
         retFuture.fail(newException(OSError, osErrorMsg(osLastError())))
       else:
         assert bytesWritten == size.int32
-        f.offset.inc(size)
         retFuture.complete()
   else:
     var written = 0
@@ -410,7 +413,6 @@ proc write*(f: AsyncFile, data: string): Future[void] =
         if not retFuture.finished:
           if errcode == OSErrorCode(-1):
             assert bytesCount == data.len.int32
-            f.offset.inc(data.len)
             retFuture.complete()
           else:
             retFuture.fail(newException(OSError, osErrorMsg(errcode)))
@@ -420,6 +422,7 @@ proc write*(f: AsyncFile, data: string): Future[void] =
     )
     ol.offset = DWord(f.offset and 0xffffffff)
     ol.offsetHigh = DWord(f.offset shr 32)
+    f.offset.inc(data.len)
 
     # According to MSDN we're supposed to pass nil to lpNumberOfBytesWritten.
     let ret = writeFile(f.fd.Handle, buffer, data.len.int32, nil,
@@ -441,7 +444,6 @@ proc write*(f: AsyncFile, data: string): Future[void] =
         retFuture.fail(newException(OSError, osErrorMsg(osLastError())))
       else:
         assert bytesWritten == data.len.int32
-        f.offset.inc(data.len)
         retFuture.complete()
   else:
     var written = 0
diff --git a/lib/pure/ospaths.nim b/lib/pure/ospaths.nim
index 7720fb2a6..fa5342fcf 100644
--- a/lib/pure/ospaths.nim
+++ b/lib/pure/ospaths.nim
@@ -516,7 +516,16 @@ when declared(getEnv) or defined(nimscript):
   proc getConfigDir*(): string {.rtl, extern: "nos$1",
     tags: [ReadEnvEffect, ReadIOEffect].} =
     ## Returns the config directory of the current user for applications.
+    ##
+    ## On non-Windows OSs, this proc conforms to the XDG Base Directory
+    ## spec. Thus, this proc returns the value of the XDG_CONFIG_DIR environment
+    ## variable if it is set, and returns the default configuration directory,
+    ## "~/.config/", otherwise.
+    ##
+    ## An OS-dependent trailing slash is always present at the end of the
+    ## returned string; `\\` on Windows and `/` on all other OSs.
     when defined(windows): return string(getEnv("APPDATA")) & "\\"
+    elif getEnv("XDG_CONFIG_DIR"): return string(getEnv("XDG_CONFIG_DIR")) & "/"
     else: return string(getEnv("HOME")) & "/.config/"
 
   proc getTempDir*(): string {.rtl, extern: "nos$1",
diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim
index 28681a11f..307808556 100644
--- a/lib/pure/parsecfg.nim
+++ b/lib/pure/parsecfg.nim
@@ -540,7 +540,8 @@ proc writeConfig*(dict: Config, filename: string) =
   ## Writes the contents of the table to the specified configuration file.
   ## Note: Comment statement will be ignored.
   let file = open(filename, fmWrite)
-  let fileStream = newFileStream(filename)
+  defer: file.close()
+  let fileStream = newFileStream(file)
   defer: fileStream.close()
   dict.writeConfig(fileStream)
 
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 8ed1fbb38..096d01845 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -282,8 +282,13 @@ proc raiseExceptionAux(e: ref Exception) =
 proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
   if e.name.isNil: e.name = ename
   when hasSomeStackTrace:
-    e.trace = ""
-    rawWriteStackTrace(e.trace)
+    if e.trace.isNil:
+      e.trace = ""
+      rawWriteStackTrace(e.trace)
+    elif framePtr != nil:
+      e.trace.add "[[reraised from:\n"
+      auxWriteStackTrace(framePtr, e.trace)
+      e.trace.add "]]\n"
   raiseExceptionAux(e)
 
 proc reraiseException() {.compilerRtl.} =
diff --git a/lib/upcoming/asyncdispatch.nim b/lib/upcoming/asyncdispatch.nim
index 8541bf98c..1623d8375 100644
--- a/lib/upcoming/asyncdispatch.nim
+++ b/lib/upcoming/asyncdispatch.nim
@@ -9,7 +9,7 @@
 
 include "system/inclrtl"
 
-import os, oids, tables, strutils, times, heapqueue, lists, options
+import os, tables, strutils, times, heapqueue, lists, options
 
 import nativesockets, net, deques
 
diff --git a/tests/async/tasyncall.nim b/tests/async/tasyncall.nim
index 63b2945a6..7daecd9ef 100644
--- a/tests/async/tasyncall.nim
+++ b/tests/async/tasyncall.nim
@@ -2,19 +2,19 @@ discard """
   file: "tasyncall.nim"
   exitcode: 0
 """
-import times, sequtils
+import times, sequtils, unittest
 import asyncdispatch
 
 const
   taskCount = 10
-  sleepDuration = 500
+  sleepDuration = 50
 
 proc futureWithValue(x: int): Future[int] {.async.} =
   await sleepAsync(sleepDuration)
   return x
 
 proc futureWithoutValue() {.async.} =
-  await sleepAsync(1000)
+  await sleepAsync(sleepDuration)
 
 proc testFuturesWithValue(x: int): seq[int] =
   var tasks = newSeq[Future[int]](taskCount)
@@ -40,38 +40,39 @@ proc testVarargs(x, y, z: int): seq[int] =
 
   result = waitFor all(a, b, c)
 
-block:
-  let
-    startTime = cpuTime()
-    results = testFuturesWithValue(42)
-    expected = repeat(42, taskCount)
-    execTime = cpuTime() - startTime
-
-  doAssert execTime * 1000 < taskCount * sleepDuration
-  doAssert results == expected
-
-block:
-  let startTime = cpuTime()
-  testFuturesWithoutValues()
-  let execTime = cpuTime() - startTime
-
-  doAssert execTime * 1000 < taskCount * sleepDuration
-
-block:
-  let
-    startTime = cpuTime()
-    results = testVarargs(1, 2, 3)
-    expected = @[1, 2, 3]
-    execTime = cpuTime() - startTime
-
-  doAssert execTime * 100 < taskCount * sleepDuration
-  doAssert results == expected
-
-block:
-  let
-    noIntFuturesFut = all(newSeq[Future[int]]())
-    noVoidFuturesFut = all(newSeq[Future[void]]())
-
-  doAssert noIntFuturesFut.finished and not noIntFuturesFut.failed
-  doAssert noVoidFuturesFut.finished and not noVoidFuturesFut.failed
-  doAssert noIntFuturesFut.read() == @[]
+suite "tasyncall":
+  test "testFuturesWithValue":
+    let
+      startTime = cpuTime()
+      results = testFuturesWithValue(42)
+      expected = repeat(42, taskCount)
+      execTime = cpuTime() - startTime
+
+    doAssert execTime * 1000 < taskCount * sleepDuration
+    doAssert results == expected
+
+  test "testFuturesWithoutValues":
+    let startTime = cpuTime()
+    testFuturesWithoutValues()
+    let execTime = cpuTime() - startTime
+
+    doAssert execTime * 1000 < taskCount * sleepDuration
+
+  test "testVarargs":
+    let
+      startTime = cpuTime()
+      results = testVarargs(1, 2, 3)
+      expected = @[1, 2, 3]
+      execTime = cpuTime() - startTime
+
+    doAssert execTime * 100 < taskCount * sleepDuration
+    doAssert results == expected
+
+  test "all on seq[Future]":
+    let
+      noIntFuturesFut = all(newSeq[Future[int]]())
+      noVoidFuturesFut = all(newSeq[Future[void]]())
+
+    doAssert noIntFuturesFut.finished and not noIntFuturesFut.failed
+    doAssert noVoidFuturesFut.finished and not noVoidFuturesFut.failed
+    doAssert noIntFuturesFut.read() == @[]
diff --git a/tests/async/tasyncfilewrite.nim b/tests/async/tasyncfilewrite.nim
new file mode 100644
index 000000000..cda612bae
--- /dev/null
+++ b/tests/async/tasyncfilewrite.nim
@@ -0,0 +1,17 @@
+discard """
+  output: '''string 1
+string 2
+string 3'''
+"""
+# bug #5532
+import os, asyncfile, asyncdispatch
+
+removeFile("test.txt")
+let f = openAsync("test.txt", fmWrite)
+var futs = newSeq[Future[void]]()
+for i in 1..3:
+  futs.add(f.write("string " & $i & "\n"))
+waitFor(all(futs))
+f.close()
+echo readFile("test.txt")
+
diff --git a/tests/macros/tgettypeinst.nim b/tests/macros/tgettypeinst.nim
index 255eff949..f89aa5e0b 100644
--- a/tests/macros/tgettypeinst.nim
+++ b/tests/macros/tgettypeinst.nim
@@ -21,49 +21,67 @@ proc symToIdent(x: NimNode): NimNode =
       for c in x:
         result.add symToIdent(c)
 
+# check getTypeInst and getTypeImpl for given symbol x
 macro testX(x,inst0: typed; recurse: static[bool]; implX: stmt): typed =
+  # check that getTypeInst(x) equals inst0
   let inst = x.getTypeInst
-  let impl = x.getTypeImpl
-  let inst0r = inst0.symToIdent.treeRepr
   let instr = inst.symToIdent.treeRepr
-  #echo inst0r
+  let inst0r = inst0.symToIdent.treeRepr
   #echo instr
+  #echo inst0r
   doAssert(instr == inst0r)
+
+  # check that getTypeImpl(x) is correct
+  #  if implX is nil then compare to inst0
+  #  else we expect implX to be a type definition
+  #       and we extract the implementation from that
+  let impl = x.getTypeImpl
   var impl0 =
     if implX.kind == nnkNilLit: inst0
     else: implX[0][2]
-  let impl0r = impl0.symToIdent.treerepr
   let implr = impl.symToIdent.treerepr
-  #echo impl0r
+  let impl0r = impl0.symToIdent.treerepr
   #echo implr
+  #echo impl0r
   doAssert(implr == impl0r)
-  template echoString(s:string) = echo s.replace("\n","\n  ")
+
   result = newStmtList()
+  #template echoString(s: string) = echo s.replace("\n","\n  ")
   #result.add getAst(echoString("  " & inst0.repr))
   #result.add getAst(echoString("  " & inst.repr))
   #result.add getAst(echoString("  " & impl0.repr))
   #result.add getAst(echoString("  " & impl.repr))
+
   if recurse:
-    template testDecl(n, m :typed) =
+    # now test using a newly formed variable of type getTypeInst(x)
+    template testDecl(n,m: typed) =
       testV(n, false):
         type _ = m
     result.add getAst(testDecl(inst.symToIdent, impl.symToIdent))
 
+# test with a variable (instance) of type
 template testV(inst, recurse, impl) =
   block:
     #echo "testV(" & astToStr(inst) & ", " & $recurse & "):" & astToStr(impl)
     var x: inst
     testX(x, inst, recurse, impl)
-template testT(inst, recurse) =
+
+# test with a newly created typedesc (myType)
+# using the passed type as the implementation
+template testT(impl, recurse) =
   block:
-    type myType = inst
+    type myType = impl
     testV(myType, recurse):
-      type _ = inst
+      type _ = impl
 
+# test a built-in type whose instance is equal to the implementation
 template test(inst) =
   testT(inst, false)
   testV(inst, true, nil)
-template test(inst, impl) = testV(inst, true, impl)
+
+# test a custom type with provided implementation
+template test(inst, impl) =
+  testV(inst, true, impl)
 
 type
   Model = object of RootObj
@@ -87,9 +105,12 @@ type
     value:T
   Foo[N:static[int],T] = object
   Bar[N:static[int],T] = object
-    #baz:Foo[N+1,GenericObject[T]]
+    #baz:Foo[N+1,GenericObject[T]]  # currently fails
     baz:Foo[N,GenericObject[T]]
 
+  Generic[T] = seq[int]
+  Concrete = Generic[int]
+
 test(bool)
 test(char)
 test(int)
@@ -97,13 +118,17 @@ test(float)
 test(ptr int)
 test(ref int)
 test(array[1..10,Bar[2,Foo[3,float]]])
+test(array[MyEnum,Bar[2,Foo[3,float]]])
 test(distinct Bar[2,Foo[3,float]])
 test(tuple[a:int,b:Foo[-1,float]])
-#test(MyEnum):
-#  type _ = enum
-#    valueA, valueB, valueC
-test(set[MyEnum])
 test(seq[int])
+test(set[MyEnum])
+test(proc (a: int, b: Foo[2,float]))
+test(proc (a: int, b: Foo[2,float]): Bar[3,int])
+
+test(MyEnum):
+  type _ = enum
+    valueA, valueB, valueC
 test(Bar[2,Foo[3,float]]):
   type _ = object
     baz: Foo[2, GenericObject[Foo[3, float]]]
@@ -118,8 +143,12 @@ test(Tree):
     value: int
     left: ref Tree
     right: ref Tree
-test(proc (a: int, b: Foo[2,float]))
-test(proc (a: int, b: Foo[2,float]): Bar[3,int])
+test(Concrete):
+  type _ = Generic[int]
+test(Generic[int]):
+  type _ = seq[int]
+test(Generic[float]):
+  type _ = seq[int]
 
 # bug #4862
 static:
diff --git a/tests/stdlib/tjsontestsuite.nim b/tests/stdlib/tjsontestsuite.nim
new file mode 100644
index 000000000..06f783a73
--- /dev/null
+++ b/tests/stdlib/tjsontestsuite.nim
@@ -0,0 +1,384 @@
+## JSON tests based on https://github.com/nst/JSONTestSuite
+
+import unittest,
+  json,
+  strutils
+
+let parsing_testdata = {
+  "i_number_neg_int_huge_exp": """[-1e+9999]""",
+  "i_number_pos_double_huge_exp": """[1.5e+9999]""",
+  "i_object_key_lone_2nd_surrogate": """{"\uDFAA":0}""",
+  "i_string_1st_surrogate_but_2nd_missing": """["\uDADA"]""",
+  "i_string_1st_valid_surrogate_2nd_invalid": """["\uD888\u1234"]""",
+  "i_string_incomplete_surrogate_and_escape_valid": """["\uD800\n"]""",
+  "i_string_incomplete_surrogate_pair": """["\uDd1ea"]""",
+  "i_string_incomplete_surrogates_escape_valid": """["\uD800\uD800\n"]""",
+  "i_string_inverted_surrogates_U+1D11E": """["\uDd1e\uD834"]""",
+  "i_string_lone_second_surrogate": """["\uDFAA"]""",
+  "i_string_not_in_unicode_range": """[""]""",
+  "i_string_truncated-utf-8": """[""]""",
+  "i_string_unicode_U+10FFFE_nonchar": """["\uDBFF\uDFFE"]""",
+  "i_string_unicode_U+1FFFE_nonchar": """["\uD83F\uDFFE"]""",
+  "i_string_unicode_U+FDD0_nonchar": """["\uFDD0"]""",
+  "i_string_unicode_U+FFFE_nonchar": """["\uFFFE"]""",
+  "i_string_UTF-16_invalid_lonely_surrogate": """["\ud800"]""",
+  "i_string_UTF-16_invalid_surrogate": """["\ud800abc"]""",
+  "i_string_UTF-8_invalid_sequence": """["日ш"]""",
+  "i_structure_500_nested_arrays": """[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]""",
+  "i_structure_UTF-8_BOM_empty_object": """{}""",
+  "n_array_1_true_without_comma": """[1 true]""",
+  "n_array_a_invalid_utf8": """[a]""",
+  "n_array_colon_instead_of_comma": """["": 1]""",
+  "n_array_comma_after_close": """[""],""",
+  "n_array_comma_and_number": """[,1]""",
+  "n_array_double_comma": """[1,,2]""",
+  "n_array_double_extra_comma": """["x",,]""",
+  "n_array_extra_close": """["x"]]""",
+  "n_array_extra_comma": """["",]""",
+  "n_array_incomplete_invalid_value": """[x""",
+  "n_array_incomplete": """["x"""",
+  "n_array_inner_array_no_comma": """[3[4]]""",
+  "n_array_invalid_utf8": """[]""",
+  "n_array_items_separated_by_semicolon": """[1:2]""",
+  "n_array_just_comma": """[,]""",
+  "n_array_just_minus": """[-]""",
+  "n_array_missing_value": """[   , ""]""",
+  "n_array_newlines_unclosed": """["a",""",
+  "n_array_newlines_unclosed": """4""",
+  "n_array_newlines_unclosed": """,1,""",
+  "n_array_number_and_comma": """[1,]""",
+  "n_array_number_and_several_commas": """[1,,]""",
+  "n_array_spaces_vertical_tab_formfeed": """["a"\f]""",
+  "n_array_star_inside": """[*]""",
+  "n_array_unclosed": """[""""",
+  "n_array_unclosed_trailing_comma": """[1,""",
+  "n_array_unclosed_with_new_lines": """[1,""",
+  "n_array_unclosed_with_new_lines": """1""",
+  "n_array_unclosed_with_new_lines": """,1""",
+  "n_array_unclosed_with_object_inside": """[{}""",
+  "n_incomplete_false": """[fals]""",
+  "n_incomplete_null": """[nul]""",
+  "n_incomplete_true": """[tru]""",
+  "n_number_0.1.2": """[0.1.2]""",
+  "n_number_-01": """[-01]""",
+  "n_number_0.3e": """[0.3e]""",
+  "n_number_0.3e+": """[0.3e+]""",
+  "n_number_0_capital_E": """[0E]""",
+  "n_number_0_capital_E+": """[0E+]""",
+  "n_number_0.e1": """[0.e1]""",
+  "n_number_0e": """[0e]""",
+  "n_number_0e+": """[0e+]""",
+  "n_number_1_000": """[1 000.0]""",
+  "n_number_1.0e-": """[1.0e-]""",
+  "n_number_1.0e": """[1.0e]""",
+  "n_number_1.0e+": """[1.0e+]""",
+  "n_number_-1.0.": """[-1.0.]""",
+  "n_number_1eE2": """[1eE2]""",
+  "n_number_.-1": """[.-1]""",
+  "n_number_+1": """[+1]""",
+  "n_number_.2e-3": """[.2e-3]""",
+  "n_number_2.e-3": """[2.e-3]""",
+  "n_number_2.e+3": """[2.e+3]""",
+  "n_number_2.e3": """[2.e3]""",
+  "n_number_-2.": """[-2.]""",
+  "n_number_9.e+": """[9.e+]""",
+  "n_number_expression": """[1+2]""",
+  "n_number_hex_1_digit": """[0x1]""",
+  "n_number_hex_2_digits": """[0x42]""",
+  "n_number_infinity": """[Infinity]""",
+  "n_number_+Inf": """[+Inf]""",
+  "n_number_Inf": """[Inf]""",
+  "n_number_invalid+-": """[0e+-1]""",
+  "n_number_invalid-negative-real": """[-123.123foo]""",
+  "n_number_invalid-utf-8-in-bigger-int": """[123]""",
+  "n_number_invalid-utf-8-in-exponent": """[1e1]""",
+  "n_number_invalid-utf-8-in-int": """[0]""",
+  "n_number_++": """[++1234]""",
+  "n_number_minus_infinity": """[-Infinity]""",
+  "n_number_minus_sign_with_trailing_garbage": """[-foo]""",
+  "n_number_minus_space_1": """[- 1]""",
+  "n_number_-NaN": """[-NaN]""",
+  "n_number_NaN": """[NaN]""",
+  "n_number_neg_int_starting_with_zero": """[-012]""",
+  "n_number_neg_real_without_int_part": """[-.123]""",
+  "n_number_neg_with_garbage_at_end": """[-1x]""",
+  "n_number_real_garbage_after_e": """[1ea]""",
+  "n_number_real_with_invalid_utf8_after_e": """[1e]""",
+  "n_number_real_without_fractional_part": """[1.]""",
+  "n_number_starting_with_dot": """[.123]""",
+  "n_number_then_00": """1\x00""",
+  "n_number_U+FF11_fullwidth_digit_one": """[1]""",
+  "n_number_with_alpha_char": """[1.8011670033376514H-308]""",
+  "n_number_with_alpha": """[1.2a-3]""",
+  "n_number_with_leading_zero": """[012]""",
+  "n_object_bad_value": """["x", truth]""",
+  "n_object_bracket_key": """{[: "x"}""",
+  "n_object_comma_instead_of_colon": """{"x", null}""",
+  "n_object_double_colon": """{"x"::"b"}""",
+  "n_object_emoji": """{🇨🇭}""",
+  "n_object_garbage_at_end": """{"a":"a" 123}""",
+  "n_object_key_with_single_quotes": """{key: 'value'}""",
+  "n_object_missing_colon": """{"a" b}""",
+  "n_object_missing_key": """{:"b"}""",
+  "n_object_missing_semicolon": """{"a" "b"}""",
+  "n_object_missing_value": """{"a":""",
+  "n_object_no-colon": """{"a"""",
+  "n_object_non_string_key_but_huge_number_instead": """{9999E9999:1}""",
+  "n_object_non_string_key": """{1:1}""",
+  "n_object_pi_in_key_and_trailing_comma": """{"":"0",}""",
+  "n_object_repeated_null_null": """{null:null,null:null}""",
+  "n_object_several_trailing_commas": """{"id":0,,,,,}""",
+  "n_object_single_quote": """{'a':0}""",
+  "n_object_trailing_comma": """{"id":0,}""",
+  "n_object_trailing_comment": """{"a":"b"}/**/""",
+  "n_object_trailing_comment_open": """{"a":"b"}/**//""",
+  "n_object_trailing_comment_slash_open_incomplete": """{"a":"b"}/""",
+  "n_object_trailing_comment_slash_open": """{"a":"b"}//""",
+  "n_object_two_commas_in_a_row": """{"a":"b",,"c":"d"}""",
+  "n_object_unquoted_key": """{a: "b"}""",
+  "n_object_unterminated-value": """{"a":"a""",
+  "n_object_with_single_string": """{ "foo" : "bar", "a" }""",
+  "n_object_with_trailing_garbage": """{"a":"b"}#""",
+  "n_single_space": """ """,
+  "n_string_1_surrogate_then_escape": """["\uD800\"]""",
+  "n_string_1_surrogate_then_escape u1": """["\uD800\u1"]""",
+  "n_string_1_surrogate_then_escape u1x": """["\uD800\u1x"]""",
+  "n_string_1_surrogate_then_escape u": """["\uD800\u"]""",
+  "n_string_accentuated_char_no_quotes": """[é]""",
+  "n_string_backslash_00": """["\\x00"]""",
+  "n_string_escaped_backslash_bad": """["\\\"]""",
+  "n_string_escaped_ctrl_char_tab": """["\	"]""",
+  "n_string_escaped_emoji": """["\🌀"]""",
+  "n_string_escape_x": """["\x00"]""",
+  "n_string_incomplete_escaped_character": """["\u00A"]""",
+  "n_string_incomplete_escape": """["\"]""",
+  "n_string_incomplete_surrogate_escape_invalid": """["\uD800\uD800\x"]""",
+  "n_string_invalid_backslash_esc": """["\a"]""",
+  "n_string_invalid_unicode_escape": """["\uqqqq"]""",
+  "n_string_invalid_utf8_after_escape": """["\"]""",
+  "n_string_invalid-utf-8-in-escape": """["\u"]""",
+  "n_string_invalid_utf-8": """[""]""",
+  "n_string_iso_latin_1": """[""]""",
+  "n_string_leading_uescaped_thinspace": """[\u0020"asd"]""",
+  "n_string_lone_utf8_continuation_byte": """[""]""",
+  "n_string_no_quotes_with_bad_escape": """[\n]""",
+  "n_string_overlong_sequence_2_bytes": """[""]""",
+  "n_string_overlong_sequence_6_bytes": """[""]""",
+  "n_string_overlong_sequence_6_bytes_null": """[""]""",
+  "n_string_single_doublequote": """"""",
+  "n_string_single_quote": """['single quote']""",
+  "n_string_single_string_no_double_quotes": """abc""",
+  "n_string_start_escape_unclosed": """["\""",
+  "n_string_unescaped_ctrl_char": """["a\x00a"]""",
+  "n_string_unescaped_newline": """["new
+line"]""",
+  "n_string_unescaped_tab": """["	"]""",
+  "n_string_unicode_CapitalU": """"\UA66D"""",
+  "n_string_UTF-16_incomplete_surrogate": """["\uD834\uDd"]""",
+  "n_string_UTF8_surrogate_U+D800": """[""]""",
+  "n_string_with_trailing_garbage": """""x""",
+  "n_structure_array_trailing_garbage": """[1]x""",
+  "n_structure_array_with_extra_array_close": """[1]]""",
+  "n_structure_array_with_unclosed_string": """["asd]""",
+  "n_structure_ascii-unicode-identifier": """aå""",
+  "n_structure_capitalized_True": """[True]""",
+  "n_structure_close_unopened_array": """1]""",
+  "n_structure_comma_instead_of_closing_brace": """{"x": true,""",
+  "n_structure_double_array": """[][]""",
+  "n_structure_end_array": """]""",
+  "n_structure_incomplete_UTF8_BOM": """{}""",
+  "n_structure_<.>": """<.>""",
+  "n_structure_lone-invalid-utf-8": """""",
+  "n_structure_lone-open-bracket": """[""",
+  "n_structure_null-byte-outside-string": """[\00]""",
+  "n_structure_<null>": """[<null>]""",
+  "n_structure_number_with_trailing_garbage": """2@""",
+  "n_structure_object_followed_by_closing_object": """{}}""",
+  "n_structure_object_unclosed_no_value": """{"":""",
+  "n_structure_object_with_comment": """{"a":/*comment*/"b"}""",
+  "n_structure_object_with_trailing_garbage": """{"a": true} "x"""",
+  "n_structure_open_array_apostrophe": """['""",
+  "n_structure_open_array_comma": """[,""",
+  "n_structure_open_array_open_object": """[{""",
+  "n_structure_open_array_open_string": """["a""",
+  "n_structure_open_array_string": """["a"""",
+  "n_structure_open_object_close_array": """{]""",
+  "n_structure_open_object_comma": """{,""",
+  "n_structure_open_object": """{""",
+  "n_structure_open_object_open_array": """{[""",
+  "n_structure_open_object_open_string": """{"a""",
+  "n_structure_open_object_string_with_apostrophes": """{'a'""",
+  "n_structure_open_open": """["\{["\{["\{["\{""",
+  "n_structure_single_point": """""",
+  "n_structure_single_star": """*""",
+  "n_structure_trailing_#": """{"a":"b"}#{}""",
+  "n_structure_U+2060_word_joined": """[⁠]""",
+  "n_structure_uescaped_LF_before_string": """[\u000A""]""",
+  "n_structure_unclosed_array": """[1""",
+  "n_structure_unclosed_array_partial_null": """[ false, nul""",
+  "n_structure_unclosed_array_unfinished_false": """[ true, fals""",
+  "n_structure_unclosed_array_unfinished_true": """[ false, tru""",
+  "n_structure_unclosed_object": """{"asd":"asd"""",
+  "n_structure_unicode-identifier": """å""",
+  "n_structure_UTF8_BOM_no_data": """""",
+  "n_structure_whitespace_formfeed": """[]""",
+  "n_structure_whitespace_U+2060_word_joiner": """[⁠]""",
+  "y_array_arraysWithSpaces": """[[]   ]""",
+  "y_array_empty": """[]""",
+  "y_array_empty-string": """[""]""",
+  "y_array_ending_with_newline": """["a"]""",
+  "y_array_false": """[false]""",
+  "y_array_heterogeneous": """[null, 1, "1", {}]""",
+  "y_array_null": """[null]""",
+  "y_array_with_1_and_newline": """[1
+]""",
+  "y_array_with_leading_space": """ [1]""",
+  "y_array_with_several_null": """[1,null,null,null,2]""",
+  "y_array_with_trailing_space": """[2] """,
+  "y_number_0e+1": """[0e+1]""",
+  "y_number_0e1": """[0e1]""",
+  "y_number_after_space": """[ 4]""",
+  "y_number_double_close_to_zero": """[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]""",
+  "y_number_double_huge_neg_exp": """[123.456e-789]""",
+  "y_number_huge_exp": """[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]""",
+  "y_number_int_with_exp": """[20e1]""",
+  "y_number": """[123e65]""",
+  "y_number_minus_zero": """[-0]""",
+  "y_number_negative_int": """[-123]""",
+  "y_number_negative_one": """[-1]""",
+  "y_number_negative_zero": """[-0]""",
+  "y_number_real_capital_e": """[1E22]""",
+  "y_number_real_capital_e_neg_exp": """[1E-2]""",
+  "y_number_real_capital_e_pos_exp": """[1E+2]""",
+  "y_number_real_exponent": """[123e45]""",
+  "y_number_real_fraction_exponent": """[123.456e78]""",
+  "y_number_real_neg_exp": """[1e-2]""",
+  "y_number_real_neg_overflow": """[-123123e100000]""",
+  "y_number_real_pos_exponent": """[1e+2]""",
+  "y_number_real_pos_overflow": """[123123e100000]""",
+  "y_number_real_underflow": """[123e-10000000]""",
+  "y_number_simple_int": """[123]""",
+  "y_number_simple_real": """[123.456789]""",
+  "y_number_too_big_neg_int": """[-123123123123123123123123123123]""",
+  "y_number_too_big_pos_int": """[100000000000000000000]""",
+  "y_number_very_big_negative_int": """[-237462374673276894279832749832423479823246327846]""",
+  "y_object_basic": """{"asd":"sdf"}""",
+  "y_object_duplicated_key_and_value": """{"a":"b","a":"b"}""",
+  "y_object_duplicated_key": """{"a":"b","a":"c"}""",
+  "y_object_empty": """{}""",
+  "y_object_empty_key": """{"":0}""",
+  "y_object_escaped_null_in_key": """{"foo\u0000bar": 42}""",
+  "y_object_extreme_numbers": """{ "min": -1.0e+28, "max": 1.0e+28 }""",
+  "y_object": """{"asd":"sdf", "dfg":"fgh"}""",
+  "y_object_long_strings": """{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}""",
+  "y_object_simple": """{"a":[]}""",
+  "y_object_string_unicode": """{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" }""",
+  "y_object_with_newlines": """{
+"a": "b"
+}""",
+  "y_string_1_2_3_bytes_UTF-8_sequences": """["\u0060\u012a\u12AB"]""",
+  "y_string_accepted_surrogate_pair": """["\uD801\udc37"]""",
+  "y_string_accepted_surrogate_pairs": """["\ud83d\ude39\ud83d\udc8d"]""",
+  "y_string_allowed_escapes": """["\"\\\/\b\f\n\r\t"]""",
+  "y_string_backslash_and_u_escaped_zero": """["\\u0000"]""",
+  "y_string_backslash_doublequotes": """["\""]""",
+  "y_string_comments": """["a/*b*/c/*d//e"]""",
+  "y_string_double_escape_a": """["\\a"]""",
+  "y_string_double_escape_n": """["\\n"]""",
+  "y_string_escaped_control_character": """["\u0012"]""",
+  "y_string_escaped_noncharacter": """["\uFFFF"]""",
+  "y_string_in_array": """["asd"]""",
+  "y_string_in_array_with_leading_space": """[ "asd"]""",
+  "y_string_last_surrogates_1_and_2": """["\uDBFF\uDFFF"]""",
+  "y_string_newline_uescaped": """["new\u00A0line"]""",
+  "y_string_nonCharacterInUTF-8_U+10FFFF": """["􏿿"]""",
+  "y_string_nonCharacterInUTF-8_U+1FFFF": """["𛿿"]""",
+  "y_string_nonCharacterInUTF-8_U+FFFF": """["￿"]""",
+  "y_string_null_escape": """["\u0000"]""",
+  "y_string_one-byte-utf-8": """["\u002c"]""",
+  "y_string_pi": """["π"]""",
+  "y_string_simple_ascii": """["asd "]""",
+  "y_string_space": """" """",
+  "y_string_three-byte-utf-8": """["\u0821"]""",
+  "y_string_two-byte-utf-8": """["\u0123"]""",
+  "y_string_u+2028_line_sep": """["
"]""",
+  "y_string_u+2029_par_sep": """["
"]""",
+  "y_string_uEscape": """["\u0061\u30af\u30EA\u30b9"]""",
+  "y_string_unescaped_char_delete": """[""]""",
+  "y_string_unicode_2": """["⍂㈴⍂"]""",
+  "y_string_unicodeEscapedBackslash": """["\u005C"]""",
+  "y_string_unicode_escaped_double_quote": """["\u0022"]""",
+  "y_string_unicode": """["\uA66D"]""",
+  "y_string_unicode_U+200B_ZERO_WIDTH_SPACE": """["\u200B"]""",
+  "y_string_unicode_U+2064_invisible_plus": """["\u2064"]""",
+  "y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF": """["\uD834\uDd1e"]""",
+  "y_string_utf8": """["€𝄞"]""",
+  "y_string_with_del_character": """["aa"]""",
+  "y_structure_lonely_false": """false""",
+  "y_structure_lonely_int": """42""",
+  "y_structure_lonely_negative_real": """-0.1""",
+  "y_structure_lonely_null": """null""",
+  "y_structure_lonely_string": """"asd"""",
+  "y_structure_lonely_true": """true""",
+  "y_structure_string_empty": """""""",
+  "y_structure_trailing_newline": """["a"]""",
+  "y_structure_true_in_array": """[true]""",
+  "y_structure_whitespace_array": """ [] """,
+}
+
+
+suite "JSON":
+
+  test "Multiple parsing tests":
+    var test_is_failed = false
+    for test_item in parsing_testdata:
+
+      let name = test_item[0]
+      let data = test_item[1]
+      var
+        parsed_successfully = false
+        parsed: JsonNode
+        exception_while_parsing = ""
+        exception_while_rendering = ""
+
+      try:
+        parsed = parseJson(data)
+        parsed_successfully = true
+      except:
+        exception_while_parsing = getCurrentExceptionMsg()
+
+
+      proc echo_summary(msg: string) =
+        var rendered = ""
+        var render_successfully = false
+        if parsed_successfully:
+          try:
+            rendered = $parsed
+            render_successfully = true
+          except:
+            rendered = "[Fail to render:<$#>]" % getCurrentExceptionMsg()
+        else:
+          rendered = "<$#>" % exception_while_parsing
+
+        echo name, repeat(' ', 60 - name.len), "[$#]" % msg, " ", rendered
+
+      case name[0]
+      of 'y':
+        # Tests starting with y_ must parse
+        if not parsed_successfully:
+          echo_summary "Failed to parse"
+          test_is_failed = true
+      of 'n':
+        # Tests starting with n_ should not parse
+        if parsed_successfully:
+          echo_summary "Failed to raise exception"
+      of 'i':
+        if parsed_successfully:
+          echo_summary "OK"
+        else:
+          echo_summary "Not parsed"
+
+      else: discard
+
+    # FIXME: temporarily disabled until "y_" tests will succeed
+    # if test_is_failed: fail()
diff --git a/tests/testament/specs.nim b/tests/testament/specs.nim
index 91e8b2ec7..ab24acc70 100644
--- a/tests/testament/specs.nim
+++ b/tests/testament/specs.nim
@@ -9,8 +9,11 @@
 
 import parseutils, strutils, os, osproc, streams, parsecfg
 
-const
-  cmdTemplate* = r"compiler" / "nim $target --lib:lib --hints:on -d:testing $options $file"
+
+var compilerPrefix* = "compiler" / "nim "
+
+proc cmdTemplate*(): string =
+  compilerPrefix & "$target --lib:lib --hints:on -d:testing $options $file"
 
 type
   TTestAction* = enum
@@ -100,7 +103,7 @@ proc specDefaults*(result: var TSpec) =
   result.outp = ""
   result.nimout = ""
   result.ccodeCheck = ""
-  result.cmd = cmdTemplate
+  result.cmd = cmdTemplate()
   result.line = 0
   result.column = 0
   result.tfile = ""
@@ -173,7 +176,7 @@ proc parseSpec*(filename: string): TSpec =
         raise newException(ValueError, "cannot interpret as a bool: " & e.value)
     of "cmd":
       if e.value.startsWith("nim "):
-        result.cmd = "compiler" / e.value
+        result.cmd = compilerPrefix & e.value[4..^1]
       else:
         result.cmd = e.value
     of "ccodecheck": result.ccodeCheck = e.value
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index 2d758ef0d..0f74de013 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -34,6 +34,7 @@ Options:
   --failing                 only show failing/ignored tests
   --pedantic                return non-zero status code if there are failures
   --targets:"c c++ js objc" run tests for specified targets (default: all)
+  --nim:path                use a particular nim executable (default: compiler/nim)
 """ % resultsFile
 
 type
@@ -367,7 +368,7 @@ proc testNoSpec(r: var TResults, test: TTest) =
   # does not extract the spec because the file is not supposed to have any
   #let tname = test.name.addFileExt(".nim")
   inc(r.total)
-  let given = callCompiler(cmdTemplate, test.name, test.options, test.target)
+  let given = callCompiler(cmdTemplate(), test.name, test.options, test.target)
   r.addResult(test, "", given.msg, given.err)
   if given.err == reSuccess: inc(r.passed)
 
@@ -376,7 +377,7 @@ proc testC(r: var TResults, test: TTest) =
   let tname = test.name.addFileExt(".c")
   inc(r.total)
   styledEcho "Processing ", fgCyan, extractFilename(tname)
-  var given = callCCompiler(cmdTemplate, test.name & ".c", test.options, test.target)
+  var given = callCCompiler(cmdTemplate(), test.name & ".c", test.options, test.target)
   if given.err != reSuccess:
     r.addResult(test, "", given.msg, given.err)
   elif test.action == actionRun:
@@ -424,6 +425,7 @@ proc main() =
     of "failing": optFailing = true
     of "pedantic": optPedantic = true
     of "targets": targets = parseTargets(p.val.string)
+    of "nim": compilerPrefix = p.val.string
     else: quit Usage
     p.next()
   if p.kind != cmdArgument: quit Usage
diff --git a/tools/detect/detect.nim b/tools/detect/detect.nim
index 3afe8ee67..1b016cef9 100644
--- a/tools/detect/detect.nim
+++ b/tools/detect/detect.nim
@@ -119,10 +119,14 @@ proc v(name: string, typ = "cint", no_other = false) =
     addf(tl,
       "#ifdef $3\n  fprintf(f, \"const $1* = $2(%ld)\\n\", $3);\n#endif\n",
       n, t, name)
-  else:
+  of "cint", "cshort", "InAddrScalar", "TSa_Family":
     addf(tl,
       "#ifdef $3\n  fprintf(f, \"const $1* = $2(%d)\\n\", $3);\n#endif\n",
       n, t, name)
+  else:
+    addf(tl,
+      "#ifdef $3\n  fprintf(f, \"const $1* = cast[$2](%d)\\n\", $3);\n#endif\n",
+      n, t, name)
 
 
 header("<aio.h>")
@@ -544,6 +548,11 @@ v("SS_DISABLE")
 v("MINSIGSTKSZ")
 v("SIGSTKSZ")
 
+v("SIG_HOLD", "Sighandler")
+v("SIG_DFL", "Sighandler")
+v("SIG_ERR", "Sighandler")
+v("SIG_IGN", "Sighandler")
+
 header("<sys/ipc.h>")
 v("IPC_CREAT")
 v("IPC_EXCL")
diff --git a/web/news/e031_version_0_16_2.rst b/web/news/e031_version_0_16_2.rst
index 63884700f..3458ac83e 100644
--- a/web/news/e031_version_0_16_2.rst
+++ b/web/news/e031_version_0_16_2.rst
@@ -45,6 +45,8 @@ Changes affecting backwards compatibility
   AST that is the same as what is used to define an enum.  Previously the AST
   returned had a repeated ``EnumTy`` node and was missing the initial pragma
   node (which is currently empty for an enum).
+- ``macros.getTypeImpl`` now correctly returns the implementation for a symbol
+  of type ``tyGenericBody``.
 - If the dispatcher parameter's value used in multi method is ``nil``,
   a ``NilError`` exception is raised. The old behavior was that the method
   would be a ``nop`` then.
@@ -61,6 +63,10 @@ Changes affecting backwards compatibility
   compile-time value.
 - On posix, the results of `waitForExit`, `peekExitCode`, `execCmd` will return
   128 + signal number if the application terminates via signal.
+- ``ospaths.getConfigDir`` now conforms to the XDG Base Directory specification
+  on non-Windows OSs. It returns the value of the XDG_CONFIG_DIR environment
+  variable if it is set, and returns the default configuration directory,
+  "~/.config/", otherwise.
 
 Library Additions
 -----------------
@@ -198,3 +204,122 @@ via a commit, for a full list see
 - Fixed "await inside array/dict literal produces invalid code"
   (`#5314 <https://github.com/nim-lang/Nim/issues/5314>`_)
 
+- Fixed "asyncdispatch.accept() can raise exception inside poll() instead of failing future on Windows"
+  (`#5279 <https://github.com/nim-lang/Nim/issues/5279>`_)
+- Fixed "VM: A crash report should be more informative"
+  (`#5352 <https://github.com/nim-lang/Nim/issues/5352>`_)
+- Fixed "IO routines are poor at handling errors"
+  (`#5349 <https://github.com/nim-lang/Nim/issues/5349>`_)
+- Fixed "new import syntax doesn't work?"
+  (`#5185 <https://github.com/nim-lang/Nim/issues/5185>`_)
+- Fixed "Seq of object literals skips unmentioned fields"
+  (`#5339 <https://github.com/nim-lang/Nim/issues/5339>`_)
+- Fixed "``sym is not accessible`` in compile time"
+  (`#5354 <https://github.com/nim-lang/Nim/issues/5354>`_)
+- Fixed "the matching is broken in re.nim"
+  (`#5382 <https://github.com/nim-lang/Nim/issues/5382>`_)
+- Fixed "development branch breaks in my c wrapper"
+  (`#5392 <https://github.com/nim-lang/Nim/issues/5392>`_)
+- Fixed "Bad codegen: toSeq + tuples + generics"
+  (`#5383 <https://github.com/nim-lang/Nim/issues/5383>`_)
+- Fixed "Bad codegen: toSeq + tuples + generics"
+  (`#5383 <https://github.com/nim-lang/Nim/issues/5383>`_)
+- Fixed "Codegen error when using container of containers"
+  (`#5402 <https://github.com/nim-lang/Nim/issues/5402>`_)
+- Fixed "sizeof(RangeType) is not available in static context"
+  (`#5399 <https://github.com/nim-lang/Nim/issues/5399>`_)
+- Fixed "Regression: ICE: expr: var not init ex_263713"
+  (`#5405 <https://github.com/nim-lang/Nim/issues/5405>`_)
+- Fixed "Stack trace is wrong when assignment operator fails with template"
+  (`#5400 <https://github.com/nim-lang/Nim/issues/5400>`_)
+- Fixed "SIGSEGV in compiler"
+  (`#5391 <https://github.com/nim-lang/Nim/issues/5391>`_)
+- Fixed "Compiler regression with struct member names"
+  (`#5404 <https://github.com/nim-lang/Nim/issues/5404>`_)
+- Fixed "Regression: compiler segfault"
+  (`#5419 <https://github.com/nim-lang/Nim/issues/5419>`_)
+- Fixed "The compilation of jester routes is broken on devel"
+  (`#5417 <https://github.com/nim-lang/Nim/issues/5417>`_)
+- Fixed "Non-generic return type produces "method is not a base""
+  (`#5432 <https://github.com/nim-lang/Nim/issues/5432>`_)
+- Fixed "Confusing error behavior when calling slice[T].random"
+  (`#5430 <https://github.com/nim-lang/Nim/issues/5430>`_)
+- Fixed "Wrong method called"
+  (`#5439 <https://github.com/nim-lang/Nim/issues/5439>`_)
+- Fixed "Attempt to document the strscans.scansp macro"
+  (`#5154 <https://github.com/nim-lang/Nim/issues/5154>`_)
+- Fixed "[Regression] Invalid C code for _ symbol inside jester routes"
+  (`#5452 <https://github.com/nim-lang/Nim/issues/5452>`_)
+- Fixed "StdLib base64 encodeInternal crashes with out of bound exception"
+  (`#5457 <https://github.com/nim-lang/Nim/issues/5457>`_)
+- Fixed "Nim hangs forever in infinite loop in nre library"
+  (`#5444 <https://github.com/nim-lang/Nim/issues/5444>`_)
+
+- Fixed "Tester passes test although individual test in suite fails"
+  (`#5472 <https://github.com/nim-lang/Nim/issues/5472>`_)
+- Fixed "terminal.nim documentation"
+  (`#5483 <https://github.com/nim-lang/Nim/issues/5483>`_)
+- Fixed "Codegen error - expected identifier before ')' token (probably regression)"
+  (`#5481 <https://github.com/nim-lang/Nim/issues/5481>`_)
+- Fixed "mixin not works inside generic proc generated by template"
+  (`#5478 <https://github.com/nim-lang/Nim/issues/5478>`_)
+- Fixed "var not init (converter + template + macro)"
+  (`#5467 <https://github.com/nim-lang/Nim/issues/5467>`_)
+- Fixed "`==` for OrderedTable should consider equal content but different size as equal."
+  (`#5487 <https://github.com/nim-lang/Nim/issues/5487>`_)
+- Fixed "Fixed tests/tester.nim"
+  (`#45 <https://github.com/nim-lang/Nim/issues/45>`_)
+- Fixed "template instanciation crashes compiler"
+  (`#5428 <https://github.com/nim-lang/Nim/issues/5428>`_)
+- Fixed "Internal compiler error in handleGenericInvocation"
+  (`#5167 <https://github.com/nim-lang/Nim/issues/5167>`_)
+- Fixed "compiler crash in forwarding template"
+  (`#5455 <https://github.com/nim-lang/Nim/issues/5455>`_)
+- Fixed "Doc query re public/private + suggestion re deprecated"
+  (`#5529 <https://github.com/nim-lang/Nim/issues/5529>`_)
+- Fixed "inheritance not work for generic object whose parent is parameterized"
+  (`#5264 <https://github.com/nim-lang/Nim/issues/5264>`_)
+- Fixed "weird inheritance rule restriction"
+  (`#5231 <https://github.com/nim-lang/Nim/issues/5231>`_)
+- Fixed "Enum with holes broken in JS"
+  (`#5062 <https://github.com/nim-lang/Nim/issues/5062>`_)
+- Fixed "enum type and aliased enum type inequality when tested with operator `is` involving template"
+  (`#5360 <https://github.com/nim-lang/Nim/issues/5360>`_)
+- Fixed "logging: problem with console logger caused by the latest changes in sysio"
+  (`#5546 <https://github.com/nim-lang/Nim/issues/5546>`_)
+- Fixed "Crash if proc and caller doesn't define seq type - HEAD"
+  (`#4756 <https://github.com/nim-lang/Nim/issues/4756>`_)
+- Fixed "`path` config option doesn't work when compilation is invoked from a different directory"
+  (`#5228 <https://github.com/nim-lang/Nim/issues/5228>`_)
+- Fixed "segfaults module doesn't compile with C++ backend"
+  (`#5550 <https://github.com/nim-lang/Nim/issues/5550>`_)
+- Fixed "Improve `joinThreads` for windows"
+  (`#4972 <https://github.com/nim-lang/Nim/issues/4972>`_)
+- Fixed "Compiling in release mode prevents valid code execution."
+  (`#5296 <https://github.com/nim-lang/Nim/issues/5296>`_)
+- Fixed "Forward declaration of generic procs or iterators doesn't work"
+  (`#4104 <https://github.com/nim-lang/Nim/issues/4104>`_)
+- Fixed "cant create thread after join"
+  (`#4719 <https://github.com/nim-lang/Nim/issues/4719>`_)
+- Fixed "can't compile with var name "near" and --threads:on"
+  (`#5598 <https://github.com/nim-lang/Nim/issues/5598>`_)
+- Fixed "inconsistent behavior when calling parent's proc of generic object"
+  (`#5241 <https://github.com/nim-lang/Nim/issues/5241>`_)
+- Fixed "The problem with import order of asyncdispatch and unittest modules"
+  (`#5597 <https://github.com/nim-lang/Nim/issues/5597>`_)
+- Fixed "Generic code fails to compile in unexpected ways"
+  (`#976 <https://github.com/nim-lang/Nim/issues/976>`_)
+- Fixed "Another 'User defined type class' issue"
+  (`#1128 <https://github.com/nim-lang/Nim/issues/1128>`_)
+- Fixed "compiler fails to compile user defined typeclass"
+  (`#1147 <https://github.com/nim-lang/Nim/issues/1147>`_)
+- Fixed "Type class membership testing doesn't work on instances of generic object types"
+  (`#1570 <https://github.com/nim-lang/Nim/issues/1570>`_)
+- Fixed "Strange overload resolution behavior for procedures with typeclass arguments"
+  (`#1991 <https://github.com/nim-lang/Nim/issues/1991>`_)
+- Fixed "The same UDTC can't constrain two type parameters in the same procedure"
+  (`#2018 <https://github.com/nim-lang/Nim/issues/2018>`_)
+- Fixed "More trait/concept issues"
+  (`#2423 <https://github.com/nim-lang/Nim/issues/2423>`_)
+- Fixed "Bugs with concepts?"
+  (`#2882 <https://github.com/nim-lang/Nim/issues/2882>`_)
\ No newline at end of file