summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules3
-rwxr-xr-xbootstrap.sh (renamed from build.sh)2
-rw-r--r--compiler/installer.ini6
m---------csources0
-rw-r--r--koch.nim11
-rw-r--r--lib/pure/json.nim29
-rw-r--r--lib/pure/logging.nim2
-rw-r--r--lib/pure/optionals.nim160
-rw-r--r--lib/pure/streams.nim104
-rw-r--r--lib/pure/xmltree.nim3
-rw-r--r--lib/system/mmdisp.nim3
-rw-r--r--tests/testament/tester.nim7
-rw-r--r--tools/niminst/niminst.nim18
14 files changed, 249 insertions, 100 deletions
diff --git a/.gitignore b/.gitignore
index 462df4efc..1971a23cb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,4 @@ xcuserdata/
 /testresults.html
 /testresults.json
 testament.db
+/csources
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 26f35d82c..000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "csources"]
-	path = csources
-	url = ../../nim-lang/csources.git
diff --git a/build.sh b/bootstrap.sh
index 91e169241..ade74a9aa 100755
--- a/build.sh
+++ b/bootstrap.sh
@@ -3,7 +3,7 @@ set -e
 set -x
 
 if [ ! -e csources/.git ]; then
-	git submodule update --init --depth 1
+	git clone --depth 1 git://github.com/nim-lang/csources.git csources
 fi
 
 cd "csources"
diff --git a/compiler/installer.ini b/compiler/installer.ini
index fff82cb5b..821309a34 100644
--- a/compiler/installer.ini
+++ b/compiler/installer.ini
@@ -203,7 +203,11 @@ Files: "tests/stdlib/*.nim"
 Files: "tests/system/*.nim"
 Files: "tests/template/*.nim"
 Files: "tests/testament/*.nim"
-Files: "tests/testdata/*.nim"
+Files: "tests/testdata/*.csv"
+Files: "tests/testdata/*.html"
+Files: "tests/testdata/*.json"
+Files: "tests/testdata/*.txt"
+Files: "tests/testdata/*.xml"
 Files: "tests/threads/*.nim"
 Files: "tests/threads/*.cfg"
 Files: "tests/trmacros/*.nim"
diff --git a/csources b/csources
deleted file mode 160000
-Subproject 15724e2e1f3e7749d508dfcd995e84fea285080
diff --git a/koch.nim b/koch.nim
index 55019b544..fc292401a 100644
--- a/koch.nim
+++ b/koch.nim
@@ -47,6 +47,7 @@ Possible Commands:
   csource [options]        builds the C sources for installation
   pdf                      builds the PDF documentation
   zip                      builds the installation ZIP package
+  xz                       builds the installation XZ package
   nsis [options]           builds the NSIS Setup installer (for Windows)
   tests [options]          run the testsuite
   update                   updates nim to the latest version from github
@@ -106,10 +107,10 @@ proc zip(args: string) =
   exec("$# --var:version=$# --var:mingw=none --main:compiler/nim.nim zip compiler/installer.ini" %
        ["tools/niminst/niminst".exe, VersionAsString])
 
-proc targz(args: string) =
+proc xz(args: string) =
   exec("$3 cc -r $2 --var:version=$1 --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" %
        [VersionAsString, compileNimInst, findNim()])
-  exec("$# --var:version=$# --var:mingw=none --main:compiler/nim.nim targz compiler/installer.ini" %
+  exec("$# --var:version=$# --var:mingw=none --main:compiler/nim.nim xz compiler/installer.ini" %
        ["tools" / "niminst" / "niminst".exe, VersionAsString])
 
 proc buildTool(toolname, args: string) =
@@ -333,8 +334,10 @@ proc tests(args: string) =
   # taint mode test :-)
   exec "nim cc --taintMode:on tests/testament/tester"
   let tester = quoteShell(getCurrentDir() / "tests/testament/tester".exe)
-  exec tester & " " & (args|"all")
+  let success = tryExec tester & " " & (args|"all")
   exec tester & " html"
+  if not success:
+    quit("tests failed", QuitFailure)
 
 proc temp(args: string) =
   var output = "compiler" / "nim".exe
@@ -365,7 +368,7 @@ of cmdArgument:
   of "pdf": pdf()
   of "csource", "csources": csource(op.cmdLineRest)
   of "zip": zip(op.cmdLineRest)
-  of "targz": targz(op.cmdLineRest)
+  of "xz": xz(op.cmdLineRest)
   of "nsis": nsis(op.cmdLineRest)
   of "install": install(op.cmdLineRest)
   of "test", "tests": tests(op.cmdLineRest)
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 518572be3..0959bb221 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -1187,24 +1187,13 @@ when false:
 # To get that we shall use, obj["json"]
 
 when isMainModule:
-  #var node = parse("{ \"test\": null }")
-  #echo(node.existsKey("test56"))
-
   var parsed = parseFile("tests/testdata/jsontest.json")
   var parsed2 = parseFile("tests/testdata/jsontest2.json")
 
-  when not defined(testing):
-    echo(parsed)
-    echo()
-    echo(pretty(parsed, 2))
-    echo()
-    echo(parsed["keyÄÖöoßß"])
-    echo()
-    echo(pretty(parsed2))
-    try:
-      echo(parsed["key2"][12123])
-      raise newException(ValueError, "That line was expected to fail")
-    except IndexError: echo()
+  try:
+    discard parsed["key2"][12123]
+    assert(false)
+  except IndexError: assert(true)
 
   let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd" }"""
   # nil passthrough
@@ -1271,13 +1260,3 @@ when isMainModule:
       }
     ]
   assert j3 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
-
-  when not defined(testing):
-    discard """
-    while true:
-      var json = stdin.readLine()
-      var node = parse(json)
-      echo(node)
-      echo()
-      echo()
-    """
diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim
index a2ea53472..cc5340211 100644
--- a/lib/pure/logging.nim
+++ b/lib/pure/logging.nim
@@ -66,7 +66,7 @@ type
   Logger* = ref object of RootObj ## abstract logger; the base type of all loggers
     levelThreshold*: Level    ## only messages of level >= levelThreshold
                               ## should be processed
-    fmtStr: string ## = defaultFmtStr by default, see substituteLog for $date etc.
+    fmtStr*: string ## = defaultFmtStr by default, see substituteLog for $date etc.
 
   ConsoleLogger* = ref object of Logger ## logger that writes the messages to the
                                         ## console
diff --git a/lib/pure/optionals.nim b/lib/pure/optionals.nim
new file mode 100644
index 000000000..ef01e1260
--- /dev/null
+++ b/lib/pure/optionals.nim
@@ -0,0 +1,160 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Nim Contributors
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Abstract
+## ========
+##
+## This module implements types which encapsulate an optional value.
+##
+## A value of type ``Option[T]`` either contains a value `x` (represented as
+## ``some(x)``) or is empty (``none(T)``).
+##
+## This can be useful when you have a value that can be present or not.  The
+## absence of a value is often represented by ``nil``, but it is not always
+## available, nor is it always a good solution.
+##
+##
+## Tutorial
+## ========
+##
+## Let's start with an example: a procedure that finds the index of a character
+## in a string.
+##
+## .. code-block:: nim
+##
+##   import optionals
+##
+##   proc find(haystack: string, needle: char): Option[int] =
+##     for i, c in haystack:
+##       if c == needle:
+##         return some(i)
+##     return none(int)  # This line is actually optional,
+##                       # because the default is empty
+##
+## .. code-block:: nim
+##
+##   try:
+##     assert("abc".find('c').get() == 2)  # Immediately extract the value
+##   except UnpackError:  # If there is no value
+##     assert false  # This will not be reached, because the value is present
+##
+## The ``get`` operation demonstrated above returns the underlying value, or
+## raises ``UnpackError`` if there is no value. There is another option for
+## obtaining the value: ``unsafeGet``, but you must only use it when you are
+## absolutely sure the value is present (e.g. after checking ``isSome``). If
+## you do not care about the tiny overhead that ``get`` causes, you should
+## simply never use ``unsafeGet``.
+##
+## How to deal with an absence of a value:
+##
+## .. code-block:: nim
+##
+##   let result = "team".find('i')
+##
+##   # Nothing was found, so the result is `none`.
+##   assert(result == none(int))
+##   # It has no value:
+##   assert(result.isNone)
+##
+##   try:
+##     echo result.get()
+##     assert(false)  # This will not be reached
+##   except UnpackError:  # Because an exception is raised
+##     discard
+
+import typetraits
+
+
+type
+  Option*[T] = object
+    ## An optional type that stores its value and state separately in a boolean.
+    val: T
+    has: bool
+  UnpackError* = ref object of ValueError
+
+
+proc some*[T](val: T): Option[T] =
+  ## Returns a ``Option`` that has this value.
+  result.has = true
+  result.val = val
+
+proc none*(T: typedesc): Option[T] =
+  ## Returns a ``Option`` for this type that has no value.
+  result.has = false
+
+
+proc isSome*[T](self: Option[T]): bool =
+  self.has
+
+proc isNone*[T](self: Option[T]): bool =
+  not self.has
+
+
+proc unsafeGet*[T](self: Option[T]): T =
+  ## Returns the value of a ``some``. Behavior is undefined for ``none``.
+  assert self.isSome
+  self.val
+
+proc get*[T](self: Option[T]): T =
+  ## Returns contents of the Option. If it is none, then an exception is
+  ## thrown.
+  if self.isNone:
+    raise UnpackError(msg : "Can't obtain a value from a `none`")
+  self.val
+
+
+proc `==`*(a, b: Option): bool =
+  ## Returns ``true`` if both ``Option``s are ``none``,
+  ## or if they have equal values
+  (a.has and b.has and a.val == b.val) or (not a.has and not b.has)
+
+
+when isMainModule:
+  import unittest
+
+  suite "optionals":
+    # work around a bug in unittest
+    let intNone = none(int)
+    let stringNone = none(string)
+
+    test "example":
+      proc find(haystack: string, needle: char): Option[int] =
+        for i, c in haystack:
+          if c == needle:
+            return some i
+
+      check("abc".find('c').get() == 2)
+
+      let result = "team".find('i')
+
+      check result == intNone
+      check result.isNone
+
+    test "some":
+      check some(6).get() == 6
+      check some("a").unsafeGet() == "a"
+      check some(6).isSome
+      check some("a").isSome
+
+    test "none":
+      expect UnpackError:
+        discard none(int).get()
+      check(none(int).isNone)
+      check(not none(string).isSome)
+
+    test "equality":
+      check some("a") == some("a")
+      check some(7) != some(6)
+      check some("a") != stringNone
+      check intNone == intNone
+
+      when compiles(some("a") == some(5)):
+        check false
+      when compiles(none(string) == none(int)):
+        check false
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index 77698d329..c85a09bad 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -31,7 +31,7 @@ type
     getPositionImpl*: proc (s: Stream): int {.nimcall, tags: [], gcsafe.}
     readDataImpl*: proc (s: Stream, buffer: pointer,
                          bufLen: int): int {.nimcall, tags: [ReadIOEffect], gcsafe.}
-    peekDataImpl*: proc (s: Stream, buffer: pointer, 
+    peekDataImpl*: proc (s: Stream, buffer: pointer,
                          bufLen: int): int {.nimcall, tags: [ReadIOEffect], gcsafe.}
     writeDataImpl*: proc (s: Stream, buffer: pointer, bufLen: int) {.nimcall,
       tags: [WriteIOEffect], gcsafe.}
@@ -81,7 +81,7 @@ proc readData*(s: Stream, buffer: pointer, bufLen: int): int =
   ## low level proc that reads data into an untyped `buffer` of `bufLen` size.
   result = s.readDataImpl(s, buffer, bufLen)
 
-proc readData*(s, unused: Stream, buffer: pointer, 
+proc readData*(s, unused: Stream, buffer: pointer,
                bufLen: int): int {.deprecated.} =
   ## low level proc that reads data into an untyped `buffer` of `bufLen` size.
   result = s.readDataImpl(s, buffer, bufLen)
@@ -96,13 +96,13 @@ proc writeData*(s: Stream, buffer: pointer, bufLen: int) =
   ## to the stream `s`.
   s.writeDataImpl(s, buffer, bufLen)
 
-proc writeData*(s, unused: Stream, buffer: pointer, 
+proc writeData*(s, unused: Stream, buffer: pointer,
                 bufLen: int) {.deprecated.} =
   ## low level proc that writes an untyped `buffer` of `bufLen` size
   ## to the stream `s`.
   s.writeDataImpl(s, buffer, bufLen)
 
-proc write*[T](s: Stream, x: T) = 
+proc write*[T](s: Stream, x: T) =
   ## generic write procedure. Writes `x` to the stream `s`. Implementation:
   ##
   ## .. code-block:: Nim
@@ -112,8 +112,8 @@ proc write*[T](s: Stream, x: T) =
   shallowCopy(y, x)
   writeData(s, addr(y), sizeof(y))
 
-proc write*(s: Stream, x: string) = 
-  ## writes the string `x` to the the stream `s`. No length field or 
+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)
 
@@ -123,7 +123,7 @@ proc writeln*(s: Stream, args: varargs[string, `$`]) =
   for str in args: write(s, str)
   write(s, "\n")
 
-proc read[T](s: Stream, result: var T) = 
+proc read[T](s: Stream, result: var T) =
   ## generic read procedure. Reads `result` from the stream `s`.
   if readData(s, addr(result), sizeof(T)) != sizeof(T):
     raise newEIO("cannot read from stream")
@@ -143,7 +143,7 @@ proc peekChar*(s: Stream): char =
   ## Returns '\0' as an EOF marker.
   if peekData(s, addr(result), sizeof(result)) != 1: result = '\0'
 
-proc readBool*(s: Stream): bool = 
+proc readBool*(s: Stream): bool =
   ## reads a bool from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
@@ -151,7 +151,7 @@ proc peekBool*(s: Stream): bool =
   ## peeks a bool from the stream `s`. Raises `EIO` if an error occured.
   peek(s, result)
 
-proc readInt8*(s: Stream): int8 = 
+proc readInt8*(s: Stream): int8 =
   ## reads an int8 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
@@ -159,55 +159,55 @@ proc peekInt8*(s: Stream): int8 =
   ## peeks an int8 from the stream `s`. Raises `EIO` if an error occurred.
   peek(s, result)
 
-proc readInt16*(s: Stream): int16 = 
+proc readInt16*(s: Stream): int16 =
   ## reads an int16 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
-proc peekInt16*(s: Stream): int16 = 
+proc peekInt16*(s: Stream): int16 =
   ## peeks an int16 from the stream `s`. Raises `EIO` if an error occurred.
   peek(s, result)
 
-proc readInt32*(s: Stream): int32 = 
+proc readInt32*(s: Stream): int32 =
   ## reads an int32 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
-proc peekInt32*(s: Stream): int32 = 
+proc peekInt32*(s: Stream): int32 =
   ## peeks an int32 from the stream `s`. Raises `EIO` if an error occurred.
   peek(s, result)
 
-proc readInt64*(s: Stream): int64 = 
+proc readInt64*(s: Stream): int64 =
   ## reads an int64 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
-proc peekInt64*(s: Stream): int64 = 
+proc peekInt64*(s: Stream): int64 =
   ## peeks an int64 from the stream `s`. Raises `EIO` if an error occurred.
   peek(s, result)
 
-proc readFloat32*(s: Stream): float32 = 
+proc readFloat32*(s: Stream): float32 =
   ## reads a float32 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
-proc peekFloat32*(s: Stream): float32 = 
+proc peekFloat32*(s: Stream): float32 =
   ## peeks a float32 from the stream `s`. Raises `EIO` if an error occurred.
   peek(s, result)
 
-proc readFloat64*(s: Stream): float64 = 
+proc readFloat64*(s: Stream): float64 =
   ## reads a float64 from the stream `s`. Raises `EIO` if an error occurred.
   read(s, result)
 
-proc peekFloat64*(s: Stream): float64 = 
+proc peekFloat64*(s: Stream): float64 =
   ## peeks a float64 from the stream `s`. Raises `EIO` if an error occurred.
   peek(s, result)
 
-proc readStr*(s: Stream, length: int): TaintedString = 
-  ## reads a string of length `length` from the stream `s`. Raises `EIO` if 
+proc readStr*(s: Stream, length: int): TaintedString =
+  ## reads a string of length `length` from the stream `s`. Raises `EIO` if
   ## an error occurred.
   result = newString(length).TaintedString
   var L = readData(s, addr(string(result)[0]), length)
   if L != length: setLen(result.string, L)
 
-proc peekStr*(s: Stream, length: int): TaintedString = 
-  ## peeks a string of length `length` from the stream `s`. Raises `EIO` if 
+proc peekStr*(s: Stream, length: int): TaintedString =
+  ## peeks a string of length `length` from the stream `s`. Raises `EIO` if
   ## an error occurred.
   result = newString(length).TaintedString
   var L = peekData(s, addr(string(result)[0]), length)
@@ -223,7 +223,7 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
   line.string.setLen(0)
   while true:
     var c = readChar(s)
-    if c == '\c': 
+    if c == '\c':
       c = readChar(s)
       break
     elif c == '\L': break
@@ -242,15 +242,15 @@ proc peekLine*(s: Stream, line: var TaintedString): bool =
   ## otherwise. If ``false`` is returned `line` contains no new data.
   let pos = getPosition(s)
   defer: setPosition(s, pos)
-  readLine(s, line)
+  result = readLine(s, line)
 
 proc readLine*(s: Stream): TaintedString =
-  ## Reads a line from a stream `s`. Note: This is not very efficient. Raises 
+  ## Reads a line from a stream `s`. Note: This is not very efficient. Raises
   ## `EIO` if an error occurred.
   result = TaintedString""
   while true:
     var c = readChar(s)
-    if c == '\c': 
+    if c == '\c':
       c = readChar(s)
       break
     if c == '\L' or c == '\0':
@@ -259,11 +259,11 @@ proc readLine*(s: Stream): TaintedString =
       result.string.add(c)
 
 proc peekLine*(s: Stream): TaintedString =
-  ## Peeks a line from a stream `s`. Note: This is not very efficient. Raises 
+  ## Peeks a line from a stream `s`. Note: This is not very efficient. Raises
   ## `EIO` if an error occurred.
   let pos = getPosition(s)
   defer: setPosition(s, pos)
-  readLine(s)
+  result = readLine(s)
 
 type
   StringStream* = ref StringStreamObj ## a stream that encapsulates a string
@@ -276,8 +276,8 @@ type
 proc ssAtEnd(s: Stream): bool =
   var s = StringStream(s)
   return s.pos >= s.data.len
-    
-proc ssSetPosition(s: Stream, pos: int) = 
+
+proc ssSetPosition(s: Stream, pos: int) =
   var s = StringStream(s)
   s.pos = clamp(pos, 0, s.data.high)
 
@@ -288,17 +288,17 @@ proc ssGetPosition(s: Stream): int =
 proc ssReadData(s: Stream, buffer: pointer, bufLen: int): int =
   var s = StringStream(s)
   result = min(bufLen, s.data.len - s.pos)
-  if result > 0: 
+  if result > 0:
     copyMem(buffer, addr(s.data[s.pos]), result)
     inc(s.pos, result)
 
 proc ssPeekData(s: Stream, buffer: pointer, bufLen: int): int =
   var s = StringStream(s)
   result = min(bufLen, s.data.len - s.pos)
-  if result > 0: 
+  if result > 0:
     copyMem(buffer, addr(s.data[s.pos]), result)
 
-proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) = 
+proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) =
   var s = StringStream(s)
   if bufLen <= 0:
     return
@@ -311,7 +311,7 @@ proc ssClose(s: Stream) =
   var s = StringStream(s)
   s.data = nil
 
-proc newStringStream*(s: string = ""): StringStream = 
+proc newStringStream*(s: string = ""): StringStream =
   ## creates a new stream from the string `s`.
   new(result)
   result.data = s
@@ -343,7 +343,7 @@ when not defined(js):
 
   proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int =
     result = readBuffer(FileStream(s).f, buffer, bufLen)
-  
+
   proc fsPeekData(s: Stream, buffer: pointer, bufLen: int): int =
     let pos = fsGetPosition(s)
     defer: fsSetPosition(s, pos)
@@ -383,14 +383,14 @@ else:
       handle*: FileHandle
       pos: int
 
-  {.deprecated: [PFileHandleStream: FileHandleStream, 
+  {.deprecated: [PFileHandleStream: FileHandleStream,
      TFileHandleStream: FileHandleStreamObj].}
 
   proc newEOS(msg: string): ref OSError =
     new(result)
     result.msg = msg
 
-  proc hsGetPosition(s: FileHandleStream): int = 
+  proc hsGetPosition(s: FileHandleStream): int =
     return s.pos
 
   when defined(windows):
@@ -398,30 +398,30 @@ else:
     discard
   else:
     import posix
-    
-    proc hsSetPosition(s: FileHandleStream, pos: int) = 
+
+    proc hsSetPosition(s: FileHandleStream, pos: int) =
       discard lseek(s.handle, pos, SEEK_SET)
 
     proc hsClose(s: FileHandleStream) = discard close(s.handle)
-    proc hsAtEnd(s: FileHandleStream): bool = 
+    proc hsAtEnd(s: FileHandleStream): bool =
       var pos = hsGetPosition(s)
       var theEnd = lseek(s.handle, 0, SEEK_END)
       result = pos >= theEnd
       hsSetPosition(s, pos) # set position back
 
-    proc hsReadData(s: FileHandleStream, buffer: pointer, bufLen: int): int = 
+    proc hsReadData(s: FileHandleStream, buffer: pointer, bufLen: int): int =
       result = posix.read(s.handle, buffer, bufLen)
       inc(s.pos, result)
-    
+
     proc hsPeekData(s: FileHandleStream, buffer: pointer, bufLen: int): int =
       result = posix.read(s.handle, buffer, bufLen)
-      
-    proc hsWriteData(s: FileHandleStream, buffer: pointer, bufLen: int) = 
-      if posix.write(s.handle, buffer, bufLen) != bufLen: 
+
+    proc hsWriteData(s: FileHandleStream, buffer: pointer, bufLen: int) =
+      if posix.write(s.handle, buffer, bufLen) != bufLen:
         raise newEIO("cannot write to stream")
       inc(s.pos, bufLen)
 
-  proc newFileHandleStream*(handle: FileHandle): FileHandleStream = 
+  proc newFileHandleStream*(handle: FileHandle): FileHandleStream =
     new(result)
     result.handle = handle
     result.pos = 0
@@ -433,8 +433,8 @@ else:
     result.peekData = hsPeekData
     result.writeData = hsWriteData
 
-  proc newFileHandleStream*(filename: string, 
-                            mode: FileMode): FileHandleStream = 
+  proc newFileHandleStream*(filename: string,
+                            mode: FileMode): FileHandleStream =
     when defined(windows):
       discard
     else:
@@ -449,7 +449,7 @@ else:
       if handle < 0: raise newEOS("posix.open() call failed")
     result = newFileHandleStream(handle)
 
-when defined(testing):
+when isMainModule and defined(testing):
   var ss = newStringStream("The quick brown fox jumped over the lazy dog.\nThe lazy dog ran")
   assert(ss.getPosition == 0)
   assert(ss.peekStr(5) == "The q")
@@ -458,3 +458,7 @@ when defined(testing):
   assert(ss.getPosition == 5) # did move
   assert(ss.peekLine() == "uick brown fox jumped over the lazy dog.")
   assert(ss.getPosition == 5) # haven't moved
+  var str = newString(100)
+  assert(ss.peekLine(str))
+  assert(str == "uick brown fox jumped over the lazy dog.")
+  assert(ss.getPosition == 5) # haven't moved
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 7526a989a..bbe3c05b7 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -337,8 +337,7 @@ proc findAll*(n: XmlNode, tag: string, result: var seq[XmlNode]) =
       continue
     if child.tag == tag:
       result.add(child)
-    elif child.k == xnElement:
-      child.findAll(tag, result)
+    child.findAll(tag, result)
 
 proc findAll*(n: XmlNode, tag: string): seq[XmlNode] =
   ## Shortcut version to assign in let blocks. Example:
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index a378f86e7..bdbb3a95a 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -70,7 +70,7 @@ when defined(boehmgc):
   elif defined(macosx):
     const boehmLib = "libgc.dylib"
   else:
-    const boehmLib = "/usr/lib/libgc.so.1"
+    const boehmLib = "libgc.so.1"
 
   proc boehmGCinit {.importc: "GC_init", dynlib: boehmLib.}
   proc boehmGC_disable {.importc: "GC_disable", dynlib: boehmLib.}
@@ -335,4 +335,3 @@ else:
     include "system/gc"
 
 {.pop.}
-
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index 0308ce940..62dafee80 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -31,6 +31,7 @@ Arguments:
 Options:
   --print                   also print results to the console
   --failing                 only show failing/ignored tests
+  --pedantic                return non-zero status code if there are failures
 """ % resultsFile
 
 type
@@ -310,12 +311,14 @@ proc main() =
   backend.open()
   var optPrintResults = false
   var optFailing = false
+  var optPedantic = false
   var p = initOptParser()
   p.next()
   while p.kind == cmdLongoption:
     case p.key.string.normalize
     of "print", "verbose": optPrintResults = true
     of "failing": optFailing = true
+    of "pedantic": optPedantic = true
     else: quit Usage
     p.next()
   if p.kind != cmdArgument: quit Usage
@@ -348,8 +351,10 @@ proc main() =
     if action == "html": openDefaultBrowser(resultsFile)
     else: echo r, r.data
   backend.close()
+  if optPedantic:
+    var failed = r.total - r.passed - r.skipped
+    if failed > 0 : quit(QuitFailure)
 
 if paramCount() == 0:
   quit Usage
 main()
-
diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim
index f0ae45484..99befa92d 100644
--- a/tools/niminst/niminst.nim
+++ b/tools/niminst/niminst.nim
@@ -35,7 +35,7 @@ type
     actionNsis,   # action: create NSIS installer
     actionScripts # action: create install and deinstall scripts
     actionZip,    # action: create zip file
-    actionTargz,  # action: create targz file
+    actionXz,     # action: create xz file
     actionDeb     # action: prepare deb package
 
   FileCategory = enum
@@ -172,7 +172,7 @@ proc parseCmdLine(c: var ConfigData) =
           of "csource": incl(c.actions, actionCSource)
           of "scripts": incl(c.actions, actionScripts)
           of "zip": incl(c.actions, actionZip)
-          of "targz": incl(c.actions, actionTargz)
+          of "xz": incl(c.actions, actionXz)
           of "inno": incl(c.actions, actionInno)
           of "nsis": incl(c.actions, actionNsis)
           of "deb": incl(c.actions, actionDeb)
@@ -560,9 +560,9 @@ when haveZipLib:
     else:
       quit("Cannot open for writing: " & n)
 
-proc targzDist(c: var ConfigData) =
+proc xzDist(c: var ConfigData) =
   let proj = toLower(c.name) & "-" & c.version
-  var n = "$#.tar.gz" % proj
+  var n = "$#.tar.xz" % proj
   let tmpDir = if c.outdir.len == 0: "build" else: c.outdir
 
   template processFile(z, dest, src) =
@@ -571,7 +571,7 @@ proc targzDist(c: var ConfigData) =
     echo "Copying ", s, " to ", tmpDir / d
     let destdir = tmpdir / d.splitFile.dir
     if not dirExists(destdir): createDir(destdir)
-    copyFile(s, tmpDir / d)
+    copyFileWithPermissions(s, tmpDir / d)
 
   processFile(z, proj / buildBatFile32, "build" / buildBatFile32)
   processFile(z, proj / buildBatFile64, "build" / buildBatFile64)
@@ -593,9 +593,7 @@ proc targzDist(c: var ConfigData) =
   let oldDir = getCurrentDir()
   setCurrentDir(tmpDir)
   try:
-    #if execShellCmd("7z a -ttar $1.tar $1" % proj) != 0 or
-    #   execShellCmd("7z a -tgzip $1.tar.gz $1.tar" % proj) != 0 or
-    if execShellCmd("7z a -tzip $1.zip $1" % proj) != 0:
+    if execShellCmd("XZ_OPT=-9 tar Jcf $1.tar.xz $1" % proj) != 0:
       echo("External program failed")
   finally:
     setCurrentDir(oldDir)
@@ -666,7 +664,7 @@ if actionZip in c.actions:
     zipDist(c)
   else:
     quit("libzip is not installed")
-if actionTargz in c.actions:
-  targzDist(c)
+if actionXz in c.actions:
+  xzDist(c)
 if actionDeb in c.actions:
   debDist(c)