summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorKonstantin Molchanov <kmolchanov@machinezone.com>2016-05-31 12:34:09 +0400
committerKonstantin Molchanov <kmolchanov@machinezone.com>2016-05-31 12:34:09 +0400
commitbea2af7ba2eed9b7c67c5db6586458493c94492b (patch)
treef3b7342c6375ee738582563ea1e21779e8bc97ed /lib
parent33f053856611483f52dfaf07c062ca1e646d1083 (diff)
parentf3fdad0eda8664f71e265b7ecc41477a7490331c (diff)
downloadNim-bea2af7ba2eed9b7c67c5db6586458493c94492b.tar.gz
Merge branch 'devel' of github.com:nim-lang/Nim into devel
Diffstat (limited to 'lib')
-rw-r--r--lib/core/macros.nim2
-rw-r--r--lib/impure/re.nim2
-rw-r--r--lib/packages/docutils/rst.nim13
-rw-r--r--lib/pure/asynchttpserver.nim26
-rw-r--r--lib/pure/collections/sequtils.nim2
-rw-r--r--lib/pure/concurrency/cpuload.nim2
-rw-r--r--lib/pure/future.nim8
-rw-r--r--lib/pure/httpclient.nim3
-rw-r--r--lib/pure/math.nim110
-rw-r--r--lib/pure/net.nim23
-rw-r--r--lib/pure/parsecfg.nim26
-rw-r--r--lib/pure/parsexml.nim4
-rw-r--r--lib/pure/pegs.nim2
-rw-r--r--lib/pure/random.nim129
-rw-r--r--lib/pure/subexes.nim2
-rw-r--r--lib/pure/times.nim107
-rw-r--r--lib/pure/unittest.nim2
-rw-r--r--lib/system.nim2
18 files changed, 268 insertions, 197 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index bfda6b938..16a954611 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -12,7 +12,7 @@ include "system/inclrtl"
 ## This module contains the interface to the compiler's abstract syntax
 ## tree (`AST`:idx:). Macros operate on this tree.
 
-## .. include:: ../doc/astspec.txt
+## .. include:: ../../doc/astspec.txt
 
 type
   NimNodeKind* = enum
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index 60bb6c77f..d49c6d1c1 100644
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -22,7 +22,7 @@
 ## though.
 ## PRCE's licence follows:
 ##
-## .. include:: ../doc/regexprs.txt
+## .. include:: ../../doc/regexprs.txt
 ##
 
 import
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index e1d5f902e..ebe6fa19b 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -323,6 +323,11 @@ proc newSharedState(options: RstParseOptions,
   result.msgHandler = if not isNil(msgHandler): msgHandler else: defaultMsgHandler
   result.findFile = if not isNil(findFile): findFile else: defaultFindFile
 
+proc findRelativeFile(p: RstParser; filename: string): string =
+  result = p.filename.splitFile.dir / filename
+  if not existsFile(result):
+    result = p.s.findFile(filename)
+
 proc rstMessage(p: RstParser, msgKind: MsgKind, arg: string) =
   p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line,
                              p.col + p.tok[p.idx].col, msgKind, arg)
@@ -1500,7 +1505,7 @@ proc dirInclude(p: var RstParser): PRstNode =
   result = nil
   var n = parseDirective(p, {hasArg, argIsFile, hasOptions}, nil)
   var filename = strip(addNodes(n.sons[0]))
-  var path = p.s.findFile(filename)
+  var path = p.findRelativeFile(filename)
   if path == "":
     rstMessage(p, meCannotOpenFile, filename)
   else:
@@ -1511,7 +1516,7 @@ proc dirInclude(p: var RstParser): PRstNode =
     else:
       var q: RstParser
       initParser(q, p.s)
-      q.filename = filename
+      q.filename = path
       q.col += getTokens(readFile(path), false, q.tok)
       # workaround a GCC bug; more like the interior pointer bug?
       #if find(q.tok[high(q.tok)].symbol, "\0\x01\x02") > 0:
@@ -1538,7 +1543,7 @@ proc dirCodeBlock(p: var RstParser, nimExtension = false): PRstNode =
   result = parseDirective(p, {hasArg, hasOptions}, parseLiteralBlock)
   var filename = strip(getFieldValue(result, "file"))
   if filename != "":
-    var path = p.s.findFile(filename)
+    var path = p.findRelativeFile(filename)
     if path == "": rstMessage(p, meCannotOpenFile, filename)
     var n = newRstNode(rnLiteralBlock)
     add(n, newRstNode(rnLeaf, readFile(path)))
@@ -1590,7 +1595,7 @@ proc dirRawAux(p: var RstParser, result: var PRstNode, kind: RstNodeKind,
                contentParser: SectionParser) =
   var filename = getFieldValue(result, "file")
   if filename.len > 0:
-    var path = p.s.findFile(filename)
+    var path = p.findRelativeFile(filename)
     if path.len == 0:
       rstMessage(p, meCannotOpenFile, filename)
     else:
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index 865b14c75..88c3399b0 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -219,20 +219,20 @@ proc processClient(client: AsyncSocket, address: string,
         else:
           await client.sendStatus("417 Expectation Failed")
 
-      # Read the body
-      # - Check for Content-length header
-      if request.headers.hasKey("Content-Length"):
-        var contentLength = 0
-        if parseInt(request.headers.getOrDefault("Content-Length"),
-                    contentLength) == 0:
-          await request.respond(Http400, "Bad Request. Invalid Content-Length.")
-          continue
-        else:
-          request.body = await client.recv(contentLength)
-          assert request.body.len == contentLength
-      else:
-        await request.respond(Http400, "Bad Request. No Content-Length.")
+    # Read the body
+    # - Check for Content-length header
+    if request.headers.hasKey("Content-Length"):
+      var contentLength = 0
+      if parseInt(request.headers.getOrDefault("Content-Length"),
+                  contentLength) == 0:
+        await request.respond(Http400, "Bad Request. Invalid Content-Length.")
         continue
+      else:
+        request.body = await client.recv(contentLength)
+        assert request.body.len == contentLength
+    else:
+      await request.respond(Http400, "Bad Request. No Content-Length.")
+      continue
 
     case request.reqMethod
     of "get", "post", "head", "put", "delete", "trace", "options",
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index 0e3824a81..0817b38a3 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -657,7 +657,7 @@ template newSeqWith*(len: int, init: expr): expr =
   ##   seq2D[1][0] = true
   ##   seq2D[0][1] = true
   ##
-  ##   import math
+  ##   import random
   ##   var seqRand = newSeqWith(20, random(10))
   ##   echo seqRand
   var result {.gensym.} = newSeq[type(init)](len)
diff --git a/lib/pure/concurrency/cpuload.nim b/lib/pure/concurrency/cpuload.nim
index 22598b5c9..b0fd002ed 100644
--- a/lib/pure/concurrency/cpuload.nim
+++ b/lib/pure/concurrency/cpuload.nim
@@ -79,6 +79,8 @@ proc advice*(s: var ThreadPoolState): ThreadPoolAdvice =
   inc s.calls
 
 when not defined(testing) and isMainModule:
+  import random
+
   proc busyLoop() =
     while true:
       discard random(80)
diff --git a/lib/pure/future.nim b/lib/pure/future.nim
index 3793edc8b..4e2c1d893 100644
--- a/lib/pure/future.nim
+++ b/lib/pure/future.nim
@@ -29,21 +29,17 @@ proc createProcType(p, b: NimNode): NimNode {.compileTime.} =
       of nnkExprColonExpr:
         identDefs.add ident[0]
         identDefs.add ident[1]
-      of nnkIdent:
+      else:
         identDefs.add newIdentNode("i" & $i)
         identDefs.add(ident)
-      else:
-        error("Incorrect type list in proc type declaration.")
       identDefs.add newEmptyNode()
       formalParams.add identDefs
-  of nnkIdent:
+  else:
     var identDefs = newNimNode(nnkIdentDefs)
     identDefs.add newIdentNode("i0")
     identDefs.add(p)
     identDefs.add newEmptyNode()
     formalParams.add identDefs
-  else:
-    error("Incorrect type list in proc type declaration.")
 
   result.add formalParams
   result.add newEmptyNode()
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 040ce10da..d59b8ecfe 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -79,7 +79,8 @@
 ## constructor should be used for this purpose. However,
 ## currently only basic authentication is supported.
 
-import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math
+import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes,
+  math, random
 import asyncnet, asyncdispatch
 import nativesockets
 
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 2feaef097..ce418d72c 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -39,8 +39,6 @@ proc fac*(n: int): int {.noSideEffect.} =
 
 when defined(Posix) and not defined(haiku):
   {.passl: "-lm".}
-when not defined(js) and not defined(nimscript):
-  import times
 
 const
   PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number)
@@ -119,30 +117,6 @@ proc sum*[T](x: openArray[T]): T {.noSideEffect.} =
   ## If `x` is empty, 0 is returned.
   for i in items(x): result = result + i
 
-proc random*(max: int): int {.benign.}
-  ## Returns a random number in the range 0..max-1. The sequence of
-  ## random number is always the same, unless `randomize` is called
-  ## which initializes the random number generator with a "random"
-  ## number, i.e. a tickcount.
-
-proc random*(max: float): float {.benign.}
-  ## Returns a random number in the range 0..<max. The sequence of
-  ## random number is always the same, unless `randomize` is called
-  ## which initializes the random number generator with a "random"
-  ## number, i.e. a tickcount. This has a 16-bit resolution on windows
-  ## and a 48-bit resolution on other platforms.
-
-when not defined(nimscript):
-  proc randomize*() {.benign.}
-    ## Initializes the random number generator with a "random"
-    ## number, i.e. a tickcount. Note: Does nothing for the JavaScript target,
-    ## as JavaScript does not support this. Nor does it work for NimScript.
-
-proc randomize*(seed: int) {.benign.}
-  ## Initializes the random number generator with a specific seed.
-  ## Note: Does nothing for the JavaScript target,
-  ## as JavaScript does not support this.
-
 {.push noSideEffect.}
 when not defined(JS):
   proc sqrt*(x: float32): float32 {.importc: "sqrtf", header: "<math.h>".}
@@ -239,57 +213,6 @@ when not defined(JS):
   proc tgamma*(x: float64): float64 {.importc: "tgamma", header: "<math.h>".}
     ## The gamma function
 
-  # C procs:
-  when defined(vcc) and false:
-    # The "secure" random, available from Windows XP
-    # https://msdn.microsoft.com/en-us/library/sxtz2fa8.aspx
-    # Present in some variants of MinGW but not enough to justify
-    # `when defined(windows)` yet
-    proc rand_s(val: var cuint) {.importc: "rand_s", header: "<stdlib.h>".}
-    # To behave like the normal version
-    proc rand(): cuint = rand_s(result)
-  else:
-    proc srand(seed: cint) {.importc: "srand", header: "<stdlib.h>".}
-    proc rand(): cint {.importc: "rand", header: "<stdlib.h>".}
-
-  when not defined(windows):
-    proc srand48(seed: clong) {.importc: "srand48", header: "<stdlib.h>".}
-    proc drand48(): float {.importc: "drand48", header: "<stdlib.h>".}
-    proc random(max: float): float =
-      result = drand48() * max
-  else:
-    when defined(vcc): # Windows with Visual C
-      proc random(max: float): float =
-        # we are hardcoding this because
-        # importc-ing macros is extremely problematic
-        # and because the value is publicly documented
-        # on MSDN and very unlikely to change
-        # See https://msdn.microsoft.com/en-us/library/296az74e.aspx
-        const rand_max = 4294967295 # UINT_MAX
-        result = (float(rand()) / float(rand_max)) * max
-      proc randomize() = discard
-      proc randomize(seed: int) = discard
-    else: # Windows with another compiler
-      proc random(max: float): float =
-        # we are hardcoding this because
-        # importc-ing macros is extremely problematic
-        # and because the value is publicly documented
-        # on MSDN and very unlikely to change
-        const rand_max = 32767
-        result = (float(rand()) / float(rand_max)) * max
-
-  when not defined(vcc): # the above code for vcc uses `discard` instead
-    # this is either not Windows or is Windows without vcc
-    when not defined(nimscript):
-      proc randomize() =
-        randomize(cast[int](epochTime()))
-    proc randomize(seed: int) =
-      srand(cint(seed)) # rand_s doesn't use srand
-      when declared(srand48): srand48(seed)
-
-  proc random(max: int): int =
-    result = int(rand()) mod max
-
   proc trunc*(x: float32): float32 {.importc: "truncf", header: "<math.h>".}
   proc trunc*(x: float64): float64 {.importc: "trunc", header: "<math.h>".}
     ## Truncates `x` to the decimal point
@@ -319,17 +242,10 @@ when not defined(JS):
     ##  echo fmod(-2.5, 0.3) ## -0.1
 
 else:
-  proc mathrandom(): float {.importc: "Math.random", nodecl.}
   proc floor*(x: float32): float32 {.importc: "Math.floor", nodecl.}
   proc floor*(x: float64): float64 {.importc: "Math.floor", nodecl.}
   proc ceil*(x: float32): float32 {.importc: "Math.ceil", nodecl.}
   proc ceil*(x: float64): float64 {.importc: "Math.ceil", nodecl.}
-  proc random(max: int): int =
-    result = int(floor(mathrandom() * float(max)))
-  proc random(max: float): float =
-    result = float(mathrandom() * float(max))
-  proc randomize() = discard
-  proc randomize(seed: int) = discard
 
   proc sqrt*(x: float32): float32 {.importc: "Math.sqrt", nodecl.}
   proc sqrt*(x: float64): float64 {.importc: "Math.sqrt", nodecl.}
@@ -398,14 +314,6 @@ proc `mod`*[T: float32|float64](x, y: T): T =
   ##  echo (4.0 mod -3.1) # -2.2
   result = if y == 0.0: x else: x - y * (x/y).floor
 
-proc random*[T](x: Slice[T]): T =
-  ## For a slice `a .. b` returns a value in the range `a .. b-1`.
-  result = random(x.b - x.a) + x.a
-
-proc random*[T](a: openArray[T]): T =
-  ## returns a random element from the openarray `a`.
-  result = a[random(a.low..a.len)]
-
 {.pop.}
 {.pop.}
 
@@ -440,24 +348,6 @@ proc lcm*[T](x, y: T): T =
   x div gcd(x, y) * y
 
 when isMainModule and not defined(JS):
-  proc gettime(dummy: ptr cint): cint {.importc: "time", header: "<time.h>".}
-
-  # Verifies random seed initialization.
-  let seed = gettime(nil)
-  randomize(seed)
-  const SIZE = 10
-  var buf : array[0..SIZE, int]
-  # Fill the buffer with random values
-  for i in 0..SIZE-1:
-    buf[i] = random(high(int))
-  # Check that the second random calls are the same for each position.
-  randomize(seed)
-  for i in 0..SIZE-1:
-    assert buf[i] == random(high(int)), "non deterministic random seeding"
-
-  when not defined(testing):
-    echo "random values equal after reseeding"
-
   # Check for no side effect annotation
   proc mySqrt(num: float): float {.noSideEffect.} =
     return sqrt(num)
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index c734fe893..cb8cea720 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -606,28 +606,31 @@ 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)
 
-when defined(posix) or defined(nimdoc):
+when defined(posix) and not defined(nimdoc):
   proc makeUnixAddr(path: string): Sockaddr_un =
     result.sun_family = AF_UNIX.toInt
     if path.len >= Sockaddr_un_path_length:
       raise newException(ValueError, "socket path too long")
     copyMem(addr result.sun_path, path.cstring, path.len + 1)
 
+when defined(posix):
   proc connectUnix*(socket: Socket, path: string) =
     ## Connects to Unix socket on `path`.
     ## This only works on Unix-style systems: Mac OS X, BSD and Linux
-    var socketAddr = makeUnixAddr(path)
-    if socket.fd.connect(cast[ptr SockAddr](addr socketAddr),
-                      sizeof(socketAddr).Socklen) != 0'i32:
-      raiseOSError(osLastError())
+    when not defined(nimdoc):
+      var socketAddr = makeUnixAddr(path)
+      if socket.fd.connect(cast[ptr SockAddr](addr socketAddr),
+                        sizeof(socketAddr).Socklen) != 0'i32:
+        raiseOSError(osLastError())
 
   proc bindUnix*(socket: Socket, path: string) =
     ## Binds Unix socket to `path`.
     ## This only works on Unix-style systems: Mac OS X, BSD and Linux
-    var socketAddr = makeUnixAddr(path)
-    if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr),
-                          sizeof(socketAddr).Socklen) != 0'i32:
-      raiseOSError(osLastError())
+    when not defined(nimdoc):
+      var socketAddr = makeUnixAddr(path)
+      if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr),
+                            sizeof(socketAddr).Socklen) != 0'i32:
+        raiseOSError(osLastError())
 
 when defined(ssl):
   proc handshake*(socket: Socket): bool
@@ -1399,7 +1402,7 @@ proc connect*(socket: Socket, address: string, port = Port(0),
   if selectWrite(s, timeout) != 1:
     raise newException(TimeoutError, "Call to 'connect' timed out.")
   else:
-    when defineSsl:
+    when defineSsl and not defined(nimdoc):
       if socket.isSSL:
         socket.fd.setBlocking(true)
         {.warning[Deprecated]: off.}
diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim
index bf19d5540..25879d2b7 100644
--- a/lib/pure/parsecfg.nim
+++ b/lib/pure/parsecfg.nim
@@ -15,21 +15,21 @@
 
 ## This is an example of how a configuration file may look like:
 ##
-## .. include:: doc/mytest.cfg
+## .. include:: ../../doc/mytest.cfg
 ##     :literal:
 ## The file ``examples/parsecfgex.nim`` demonstrates how to use the
 ## configuration file parser:
 ##
 ## .. code-block:: nim
-##     :file: examples/parsecfgex.nim
-## 
+##     :file: ../../examples/parsecfgex.nim
+##
 ## Examples
 ## --------
 ##
 ## This is an example of a configuration file.
-## 
-## .. include:: config.ini
-## 
+##
+## ::
+##
 ##     charset = "utf-8"
 ##     [Package]
 ##     name = "hello"
@@ -38,11 +38,11 @@
 ##     name = "lihf8515"
 ##     qq = "10214028"
 ##     email = "lihaifeng@wxm.com"
-## 
+##
 ## Creating a configuration file.
 ## ==============================
 ## .. code-block:: nim
-## 
+##
 ##     import parsecfg
 ##     var dict=newConfig()
 ##     dict.setSectionKey("","charset","utf-8")
@@ -52,7 +52,7 @@
 ##     dict.setSectionKey("Author","qq","10214028")
 ##     dict.setSectionKey("Author","email","lihaifeng@wxm.com")
 ##     dict.writeConfig("config.ini")
-## 
+##
 ## Reading a configuration file.
 ## =============================
 ## .. code-block:: nim
@@ -66,11 +66,11 @@
 ##     var qq = dict.getSectionValue("Author","qq")
 ##     var email = dict.getSectionValue("Author","email")
 ##     echo pname & "\n" & name & "\n" & qq & "\n" & email
-## 
+##
 ## Modifying a configuration file.
 ## ===============================
 ## .. code-block:: nim
-## 
+##
 ##     import parsecfg
 ##     var dict = loadConfig("config.ini")
 ##     dict.setSectionKey("Author","name","lhf")
@@ -79,7 +79,7 @@
 ## Deleting a section key in a configuration file.
 ## ===============================================
 ## .. code-block:: nim
-## 
+##
 ##     import parsecfg
 ##     var dict = loadConfig("config.ini")
 ##     dict.delSectionKey("Author","email")
@@ -434,7 +434,7 @@ proc loadConfig*(filename: string): Config =
   ## Load the specified configuration file into a new Config instance.
   var dict = newOrderedTable[string, OrderedTableRef[string, string]]()
   var curSection = "" ## Current section,
-                      ## the default value of the current section is "", 
+                      ## the default value of the current section is "",
                       ## which means that the current section is a common
   var p: CfgParser
   var fileStream = newFileStream(filename, fmRead)
diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim
index f8b2c3d8d..06daa3782 100644
--- a/lib/pure/parsexml.nim
+++ b/lib/pure/parsexml.nim
@@ -34,7 +34,7 @@
 ## document.
 ##
 ## .. code-block:: nim
-##     :file: examples/htmltitle.nim
+##     :file: ../../examples/htmltitle.nim
 ##
 ##
 ## Example 2: Retrieve all HTML links
@@ -45,7 +45,7 @@
 ## an HTML document contains.
 ##
 ## .. code-block:: nim
-##     :file: examples/htmlrefs.nim
+##     :file: ../../examples/htmlrefs.nim
 ##
 
 import
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index eea20a62c..7e1f50266 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -12,7 +12,7 @@
 ## Matching performance is hopefully competitive with optimized regular
 ## expression engines.
 ##
-## .. include:: ../doc/pegdocs.txt
+## .. include:: ../../doc/pegdocs.txt
 ##
 
 include "system/inclrtl"
diff --git a/lib/pure/random.nim b/lib/pure/random.nim
new file mode 100644
index 000000000..c73f403eb
--- /dev/null
+++ b/lib/pure/random.nim
@@ -0,0 +1,129 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2016 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+##[Nim's standard random number generator. Based on
+
+| `http://xoroshiro.di.unimi.it/`_
+| `http://xoroshiro.di.unimi.it/xoroshiro128plus.c`_
+]##
+
+include "system/inclrtl"
+{.push debugger:off.}
+
+# XXX Expose RandomGenState
+when defined(JS):
+  type ui = uint32
+else:
+  type ui = uint64
+
+type
+  RandomGenState = object
+    a0, a1: ui
+
+when defined(JS):
+  var state = RandomGenState(
+    a0: 0x69B4C98Cu32,
+    a1: 0xFED1DD30u32) # global for backwards compatibility
+else:
+  # racy for multi-threading but good enough for now:
+  var state = RandomGenState(
+    a0: 0x69B4C98CB8530805u64,
+    a1: 0xFED1DD3004688D67CAu64) # global for backwards compatibility
+
+proc rotl(x, k: ui): ui =
+  result = (x shl k) or (x shr (ui(64) - k))
+
+proc next(s: var RandomGenState): uint64 =
+  let s0 = s.a0
+  var s1 = s.a1
+  result = s0 + s1
+  s1 = s1 xor s0
+  s.a0 = rotl(s0, 55) xor s1 xor (s1 shl 14) # a, b
+  s.a1 = rotl(s1, 36) # c
+
+proc skipRandomNumbers(s: var RandomGenState) =
+  ## This is the jump function for the generator. It is equivalent
+  ## to 2^64 calls to next(); it can be used to generate 2^64
+  ## non-overlapping subsequences for parallel computations.
+  when defined(JS):
+    const helper = [0xbeac0467u32, 0xd86b048bu32]
+  else:
+    const helper = [0xbeac0467eba5facbu64, 0xd86b048b86aa9922u64]
+  var
+    s0 = ui 0
+    s1 = ui 0
+  for i in 0..high(helper):
+    for b in 0..< 64:
+      if (helper[i] and (ui(1) shl ui(b))) != 0:
+        s0 = s0 xor s.a0
+        s1 = s1 xor s.a1
+      discard next(s)
+  s.a0 = s0
+  s.a1 = s1
+
+proc random*(max: int): int {.benign.} =
+  ## Returns a random number in the range 0..max-1. The sequence of
+  ## random number is always the same, unless `randomize` is called
+  ## which initializes the random number generator with a "random"
+  ## number, i.e. a tickcount.
+  result = int(next(state) mod uint64(max))
+
+proc random*(max: float): float {.benign.} =
+  ## Returns a random number in the range 0..<max. The sequence of
+  ## random number is always the same, unless `randomize` is called
+  ## which initializes the random number generator with a "random"
+  ## number, i.e. a tickcount.
+  let x = next(state)
+  when defined(JS):
+    result = (float(x) / float(high(uint32))) * max
+  else:
+    let u = (0x3FFu64 shl 52u64) or (x shr 12u64)
+    result = (cast[float](u) - 1.0) * max
+
+proc random*[T](x: Slice[T]): T =
+  ## For a slice `a .. b` returns a value in the range `a .. b-1`.
+  result = random(x.b - x.a) + x.a
+
+proc random*[T](a: openArray[T]): T =
+  ## returns a random element from the openarray `a`.
+  result = a[random(a.low..a.len)]
+
+proc randomize*(seed: int) {.benign.} =
+  ## Initializes the random number generator with a specific seed.
+  state.a0 = ui(seed shr 16)
+  state.a1 = ui(seed and 0xffff)
+
+when not defined(nimscript):
+  import times
+
+  proc randomize*() {.benign.} =
+    ## Initializes the random number generator with a "random"
+    ## number, i.e. a tickcount. Note: Does not work for NimScript.
+    when defined(JS):
+      proc getMil(t: Time): int {.importcpp: "getTime", nodecl.}
+      randomize(getMil times.getTime())
+    else:
+      randomize(int times.getTime())
+
+{.pop.}
+
+when isMainModule:
+  proc main =
+    var occur: array[1000, int]
+
+    var x = 8234
+    for i in 0..100_000:
+      x = random(len(occur)) # myrand(x)
+      inc occur[x]
+    for i, oc in occur:
+      if oc < 69:
+        doAssert false, "too few occurances of " & $i
+      elif oc > 130:
+        doAssert false, "too many occurances of " & $i
+  main()
diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim
index 22f29b77c..351b3c086 100644
--- a/lib/pure/subexes.nim
+++ b/lib/pure/subexes.nim
@@ -9,7 +9,7 @@
 
 ## Nim support for `substitution expressions`:idx: (`subex`:idx:).
 ##
-## .. include:: ../doc/subexes.txt
+## .. include:: ../../doc/subexes.txt
 ##
 
 {.push debugger:off .} # the user does not want to trace a part
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index e0ee884a8..f9d341e32 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -64,8 +64,9 @@ when defined(posix) and not defined(JS):
   proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {.
     importc: "gettimeofday", header: "<sys/time.h>".}
 
-  var
-    timezone {.importc, header: "<time.h>".}: int
+  when not defined(freebsd) and not defined(netbsd) and not defined(openbsd):
+    var timezone {.importc, header: "<time.h>".}: int
+  var  
     tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
   # we also need tzset() to make sure that tzname is initialized
   proc tzset() {.importc, header: "<time.h>".}
@@ -416,18 +417,32 @@ when not defined(JS):
 
 when not defined(JS):
   # C wrapper:
+  when defined(freebsd) or defined(netbsd) or defined(openbsd):
+    type
+      StructTM {.importc: "struct tm", final.} = object
+        second {.importc: "tm_sec".},
+          minute {.importc: "tm_min".},
+          hour {.importc: "tm_hour".},
+          monthday {.importc: "tm_mday".},
+          month {.importc: "tm_mon".},
+          year {.importc: "tm_year".},
+          weekday {.importc: "tm_wday".},
+          yearday {.importc: "tm_yday".},
+          isdst {.importc: "tm_isdst".}: cint
+        gmtoff {.importc: "tm_gmtoff".}: clong
+  else:
+    type
+      StructTM {.importc: "struct tm", final.} = object
+        second {.importc: "tm_sec".},
+          minute {.importc: "tm_min".},
+          hour {.importc: "tm_hour".},
+          monthday {.importc: "tm_mday".},
+          month {.importc: "tm_mon".},
+          year {.importc: "tm_year".},
+          weekday {.importc: "tm_wday".},
+          yearday {.importc: "tm_yday".},
+          isdst {.importc: "tm_isdst".}: cint
   type
-    StructTM {.importc: "struct tm", final.} = object
-      second {.importc: "tm_sec".},
-        minute {.importc: "tm_min".},
-        hour {.importc: "tm_hour".},
-        monthday {.importc: "tm_mday".},
-        month {.importc: "tm_mon".},
-        year {.importc: "tm_year".},
-        weekday {.importc: "tm_wday".},
-        yearday {.importc: "tm_yday".},
-        isdst {.importc: "tm_isdst".}: cint
-
     TimeInfoPtr = ptr StructTM
     Clock {.importc: "clock_t".} = distinct int
 
@@ -457,24 +472,47 @@ when not defined(JS):
     const
       weekDays: array [0..6, WeekDay] = [
         dSun, dMon, dTue, dWed, dThu, dFri, dSat]
-    TimeInfo(second: int(tm.second),
-      minute: int(tm.minute),
-      hour: int(tm.hour),
-      monthday: int(tm.monthday),
-      month: Month(tm.month),
-      year: tm.year + 1900'i32,
-      weekday: weekDays[int(tm.weekday)],
-      yearday: int(tm.yearday),
-      isDST: tm.isdst > 0,
-      tzname: if local:
-          if tm.isdst > 0:
-            getTzname().DST
+    when defined(freebsd) or defined(netbsd) or defined(openbsd):
+      TimeInfo(second: int(tm.second),
+        minute: int(tm.minute),
+        hour: int(tm.hour),
+        monthday: int(tm.monthday),
+        month: Month(tm.month),
+        year: tm.year + 1900'i32,
+        weekday: weekDays[int(tm.weekday)],
+        yearday: int(tm.yearday),
+        isDST: tm.isdst > 0,
+        tzname: if local:
+            if tm.isdst > 0:
+              getTzname().DST
+            else:
+              getTzname().nonDST
           else:
-            getTzname().nonDST
-        else:
-          "UTC",
-      timezone: if local: getTimezone() else: 0
-    )
+            "UTC",
+        # BSD stores in `gmtoff` offset east of UTC in seconds,
+        # but posix systems using west of UTC in seconds
+        timezone: if local: -(tm.gmtoff) else: 0
+      )
+    else:
+      TimeInfo(second: int(tm.second),
+        minute: int(tm.minute),
+        hour: int(tm.hour),
+        monthday: int(tm.monthday),
+        month: Month(tm.month),
+        year: tm.year + 1900'i32,
+        weekday: weekDays[int(tm.weekday)],
+        yearday: int(tm.yearday),
+        isDST: tm.isdst > 0,
+        tzname: if local:
+            if tm.isdst > 0:
+              getTzname().DST
+            else:
+              getTzname().nonDST
+          else:
+            "UTC",
+        timezone: if local: getTimezone() else: 0
+      )
+
 
   proc timeInfoToTM(t: TimeInfo): StructTM =
     const
@@ -564,7 +602,14 @@ when not defined(JS):
     return ($tzname[0], $tzname[1])
 
   proc getTimezone(): int =
-    return timezone
+    when defined(freebsd) or defined(netbsd) or defined(openbsd):
+      var a = timec(nil)
+      let lt = localtime(addr(a))
+      # BSD stores in `gmtoff` offset east of UTC in seconds,
+      # but posix systems using west of UTC in seconds
+      return -(lt.gmtoff)
+    else:
+      return timezone
 
   proc fromSeconds(since1970: float): Time = Time(since1970)
 
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index aca9d51e2..b83ec44ca 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -310,7 +310,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
   ##
   ## .. code-block:: nim
   ##
-  ##  import math
+  ##  import math, random
   ##  proc defectiveRobot() =
   ##    randomize()
   ##    case random(1..4)
diff --git a/lib/system.nim b/lib/system.nim
index c224535f0..8180f27cd 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2514,7 +2514,7 @@ template newException*(exceptn: typedesc, message: string): expr =
   e
 
 when hostOS == "standalone":
-  include panicoverride
+  include "$projectpath/panicoverride"
 
 when not declared(sysFatal):
   when hostOS == "standalone":