summary refs log tree commit diff stats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/ci_testresults.nim24
-rw-r--r--tools/dochack/dochack.nim45
-rw-r--r--tools/dochack/karax.nim344
-rw-r--r--tools/finish.nim25
-rw-r--r--tools/kochdocs.nim39
-rw-r--r--tools/nim-gdb.py25
-rw-r--r--tools/nimgrep.nim4
-rw-r--r--tools/vccexe/vccenv.nim6
-rw-r--r--tools/vccexe/vccexe.nim25
-rw-r--r--tools/vccexe/vcvarsall.nim6
10 files changed, 150 insertions, 393 deletions
diff --git a/tools/ci_testresults.nim b/tools/ci_testresults.nim
new file mode 100644
index 000000000..3201606d7
--- /dev/null
+++ b/tools/ci_testresults.nim
@@ -0,0 +1,24 @@
+## Print summary of failed tests for CI
+
+import os, json, sets, strformat
+
+const skip = toSet(["reDisabled", "reIgnored", "reSuccess", "reJoined"])
+
+when isMainModule:
+  for fn in walkFiles("testresults/*.json"):
+    let entries = fn.readFile().parseJson()
+    for j in entries:
+      let res = j["result"].getStr()
+      if skip.contains(res):
+        continue
+      echo fmt """
+Category: {j["category"].getStr()}
+Name: {j["name"].getStr()}
+Action: {j["action"].getStr()}
+Result: {res}
+-------- Expected -------
+{j["expected"].getStr()}
+--------- Given  --------
+{j["given"].getStr()}
+-------------------------
+"""
diff --git a/tools/dochack/dochack.nim b/tools/dochack/dochack.nim
index 61c61225d..2f8465a63 100644
--- a/tools/dochack/dochack.nim
+++ b/tools/dochack/dochack.nim
@@ -1,6 +1,38 @@
-import karax
+import dom
 import fuzzysearch
 
+proc textContent(e: Element): cstring {.
+  importcpp: "#.textContent", nodecl.}
+
+proc textContent(e: Node): cstring {.
+  importcpp: "#.textContent", nodecl.}
+
+proc tree(tag: string; kids: varargs[Element]): Element =
+  result = document.createElement tag
+  for k in kids:
+    result.appendChild k
+
+proc add(parent, kid: Element) =
+  if parent.nodeName == cstring"TR" and (
+      kid.nodeName == cstring"TD" or kid.nodeName == cstring"TH"):
+    let k = document.createElement("TD")
+    appendChild(k, kid)
+    appendChild(parent, k)
+  else:
+    appendChild(parent, kid)
+
+proc setClass(e: Element; value: string) =
+  e.setAttribute("class", value)
+proc text(s: string): Element = cast[Element](document.createTextNode(s))
+proc text(s: cstring): Element = cast[Element](document.createTextNode(s))
+
+proc getElementById(id: cstring): Element {.importc: "document.getElementById", nodecl.}
+
+proc replaceById(id: cstring; newTree: Node) =
+  let x = getElementById(id)
+  x.parentNode.replaceChild(newTree, x)
+  newTree.id = id
+
 proc findNodeWith(x: Element; tag, content: cstring): Element =
   if x.nodeName == tag and x.textContent == content:
     return x
@@ -182,7 +214,7 @@ proc buildToc(orig: TocEntry; types, procs: seq[Element]): TocEntry =
     t.markElement()
     for p in procs:
       if not isMarked(p):
-        let xx = karax.getElementsByClass(p.parent, cstring"attachedType")
+        let xx = getElementsByClass(p.parent, cstring"attachedType")
         if xx.len == 1 and xx[0].textContent == t.textContent:
           #kout(cstring"found ", p.nodeName)
           let q = tree("A", text(p.title))
@@ -230,7 +262,7 @@ proc groupBy*(value: cstring) {.exportc.} =
   togglevis(getElementById"toc-list")
 
 var
-  db: seq[Element]
+  db: seq[Node]
   contents: seq[cstring]
 
 template normalize(x: cstring): cstring = x.toLower.replace("_", "")
@@ -258,7 +290,7 @@ proc dosearch(value: cstring): Element =
   let ul = tree("UL")
   result = tree("DIV")
   result.setClass"search_results"
-  var matches: seq[(Element, int)] = @[]
+  var matches: seq[(Node, int)] = @[]
   for i in 0..<db.len:
     let c = contents[i]
     if c == cstring"Examples" or c == cstring"PEG construction":
@@ -270,11 +302,10 @@ proc dosearch(value: cstring): Element =
     if matched:
       matches.add((db[i], score))
 
-  matches.sort do (a, b: auto) -> int:
-    b[1] - a[1]
+  matches.sort(proc(a, b: auto): int = b[1] - a[1])
   for i in 0 ..< min(matches.len, 19):
     matches[i][0].innerHTML = matches[i][0].getAttribute("data-doc-search-tag")
-    ul.add(tree("LI", matches[i][0]))
+    ul.add(tree("LI", cast[Element](matches[i][0])))
   if ul.len == 0:
     result.add tree("B", text"no search results")
   else:
diff --git a/tools/dochack/karax.nim b/tools/dochack/karax.nim
deleted file mode 100644
index 020fd37d1..000000000
--- a/tools/dochack/karax.nim
+++ /dev/null
@@ -1,344 +0,0 @@
-# Simple lib to write JS UIs
-
-import dom
-
-export dom.Element, dom.Event, dom.cloneNode, dom
-
-proc kout*[T](x: T) {.importc: "console.log", varargs.}
-  ## the preferred way of debugging karax applications.
-
-proc id*(e: Node): cstring {.importcpp: "#.id", nodecl.}
-proc `id=`*(e: Node; x: cstring) {.importcpp: "#.id = #", nodecl.}
-proc className*(e: Node): cstring {.importcpp: "#.className", nodecl.}
-proc `className=`*(e: Node; v: cstring) {.importcpp: "#.className = #", nodecl.}
-
-proc value*(e: Element): cstring {.importcpp: "#.value", nodecl.}
-proc `value=`*(e: Element; v: cstring) {.importcpp: "#.value = #", nodecl.}
-
-proc getElementsByClass*(e: Element; name: cstring): seq[Element] {.importcpp: "#.getElementsByClassName(#)", nodecl.}
-
-proc toLower*(x: cstring): cstring {.
-  importcpp: "#.toLowerCase()", nodecl.}
-proc replace*(x: cstring; search, by: cstring): cstring {.
-  importcpp: "#.replace(#, #)", nodecl.}
-
-type
-  EventHandler* = proc(ev: Event)
-  EventHandlerId* = proc(ev: Event; id: int)
-
-  Timeout* = ref object
-
-var document* {.importc.}: Document
-
-var
-  dorender: proc (): Element {.closure.}
-  drawTimeout: Timeout
-  currentTree: Element
-
-proc setRenderer*(renderer: proc (): Element) =
-  dorender = renderer
-
-proc setTimeout*(action: proc(); ms: int): Timeout {.importc, nodecl.}
-proc clearTimeout*(t: Timeout) {.importc, nodecl.}
-proc targetElem*(e: Event): Element = cast[Element](e.target)
-
-proc getElementById*(id: cstring): Element {.importc: "document.getElementById", nodecl.}
-
-proc getElementsByClassName*(cls: cstring): seq[Element] {.importc:
-  "document.getElementsByClassName", nodecl.}
-
-proc textContent*(e: Element): cstring {.
-  importcpp: "#.textContent", nodecl.}
-
-proc replaceById*(id: cstring; newTree: Node) =
-  let x = getElementById(id)
-  x.parentNode.replaceChild(newTree, x)
-  newTree.id = id
-
-proc equals(a, b: Node): bool =
-  if a.nodeType != b.nodeType: return false
-  if a.id != b.id: return false
-  if a.nodeName != b.nodeName: return false
-  if a.nodeType == TextNode:
-    if a.data != b.data: return false
-  elif a.childNodes.len != b.childNodes.len:
-    return false
-  if a.className != b.className:
-    # style differences are updated in place and we pretend
-    # it's still the same node
-    a.className = b.className
-    #return false
-  return true
-
-proc diffTree(parent, a, b: Node) =
-  if equals(a, b):
-    if a.nodeType != TextNode:
-      # we need to do this correctly in the presence of asyncronous
-      # DOM updates:
-      var i = 0
-      while i < a.childNodes.len and a.childNodes.len == b.childNodes.len:
-        diffTree(a, a.childNodes[i], b.childNodes[i])
-        inc i
-  elif parent == nil:
-    replaceById("ROOT", b)
-  else:
-    parent.replaceChild(b, a)
-
-proc dodraw() =
-  let newtree = dorender()
-  newtree.id = "ROOT"
-  if currentTree == nil:
-    currentTree = newtree
-    replaceById("ROOT", currentTree)
-  else:
-    diffTree(nil, currentTree, newtree)
-
-proc redraw*() =
-  # we buffer redraw requests:
-  if drawTimeout != nil:
-    clearTimeout(drawTimeout)
-  drawTimeout = setTimeout(dodraw, 30)
-
-proc tree*(tag: string; kids: varargs[Element]): Element =
-  result = document.createElement tag
-  for k in kids:
-    result.appendChild k
-
-proc tree*(tag: string; attrs: openarray[(string, string)];
-           kids: varargs[Element]): Element =
-  result = tree(tag, kids)
-  for a in attrs: result.setAttribute(a[0], a[1])
-
-proc text*(s: string): Element = cast[Element](document.createTextNode(s))
-proc text*(s: cstring): Element = cast[Element](document.createTextNode(s))
-proc add*(parent, kid: Element) =
-  if parent.nodeName == cstring"TR" and (
-      kid.nodeName == cstring"TD" or kid.nodeName == cstring"TH"):
-    let k = document.createElement("TD")
-    appendChild(k, kid)
-    appendChild(parent, k)
-  else:
-    appendChild(parent, kid)
-
-proc len*(x: Element): int {.importcpp: "#.childNodes.length".}
-proc `[]`*(x: Element; idx: int): Element {.importcpp: "#.childNodes[#]".}
-
-proc isInt*(s: cstring): bool {.asmNoStackFrame.} =
-  asm """
-    return s.match(/^[0-9]+$/);
-  """
-
-var
-  linkCounter: int
-
-proc link*(id: int): Element =
-  result = document.createElement("a")
-  result.setAttribute("href", "#")
-  inc linkCounter
-  result.setAttribute("id", $linkCounter & ":" & $id)
-
-proc link*(action: EventHandler): Element =
-  result = document.createElement("a")
-  result.setAttribute("href", "#")
-  addEventListener(result, "click", action)
-
-proc parseInt*(s: cstring): int {.importc, nodecl.}
-proc parseFloat*(s: cstring): float {.importc, nodecl.}
-proc split*(s, sep: cstring): seq[cstring] {.importcpp, nodecl.}
-
-proc startsWith*(a, b: cstring): bool {.importcpp: "startsWith", nodecl.}
-proc contains*(a, b: cstring): bool {.importcpp: "(#.indexOf(#)>=0)", nodecl.}
-proc substr*(s: cstring; start: int): cstring {.importcpp: "substr", nodecl.}
-proc substr*(s: cstring; start, length: int): cstring {.importcpp: "substr", nodecl.}
-
-#proc len*(s: cstring): int {.importcpp: "#.length", nodecl.}
-proc `&`*(a, b: cstring): cstring {.importcpp: "(# + #)", nodecl.}
-proc toCstr*(s: int): cstring {.importcpp: "((#)+'')", nodecl.}
-
-proc suffix*(s, prefix: cstring): cstring =
-  if s.startsWith(prefix):
-    result = s.substr(prefix.len)
-  else:
-    kout(cstring"bug! " & s & cstring" does not start with " & prefix)
-
-proc valueAsInt*(e: Element): int = parseInt(e.value)
-proc suffixAsInt*(s, prefix: cstring): int = parseInt(suffix(s, prefix))
-
-proc scrollTop*(e: Element): int {.importcpp: "#.scrollTop", nodecl.}
-proc offsetHeight*(e: Element): int {.importcpp: "#.offsetHeight", nodecl.}
-proc offsetTop*(e: Element): int {.importcpp: "#.offsetTop", nodecl.}
-
-template onImpl(s) {.dirty} =
-  proc wrapper(ev: Event) =
-    action(ev)
-    redraw()
-  addEventListener(e, s, wrapper)
-
-proc setOnclick*(e: Element; action: proc(ev: Event)) =
-  onImpl "click"
-
-proc setOnclick*(e: Element; action: proc(ev: Event; id: int)) =
-  proc wrapper(ev: Event) =
-    let id = ev.target.id
-    let a = id.split(":")
-    if a.len == 2:
-      action(ev, parseInt(a[1]))
-      redraw()
-    else:
-      kout(cstring("cannot deal with id "), id)
-  addEventListener(e, "click", wrapper)
-
-proc setOnfocuslost*(e: Element; action: EventHandler) =
-  onImpl "blur"
-
-proc setOnchanged*(e: Element; action: EventHandler) =
-  onImpl "change"
-
-proc setOnscroll*(e: Element; action: EventHandler) =
-  onImpl "scroll"
-
-proc select*(choices: openarray[string]): Element =
-  result = document.createElement("select")
-  var i = 0
-  for c in choices:
-    result.add tree("option", [("value", $i)], text(c))
-    inc i
-
-proc select*(choices: openarray[(int, string)]): Element =
-  result = document.createElement("select")
-  for c in choices:
-    result.add tree("option", [("value", $c[0])], text(c[1]))
-
-var radioCounter: int
-
-proc radio*(choices: openarray[(int, string)]): Element =
-  result = document.createElement("fieldset")
-  var i = 0
-  inc radioCounter
-  for c in choices:
-    let id = "radio_" & c[1] & $i
-    var kid = tree("input", [("type", "radio"),
-      ("id", id), ("name", "radio" & $radioCounter),
-      ("value", $c[0])])
-    if i == 0:
-      kid.setAttribute("checked", "checked")
-    var lab = tree("label", [("for", id)], text(c[1]))
-    kid.add lab
-    result.add kid
-    inc i
-
-proc tag*(name: string; id="", class=""): Element =
-  result = document.createElement(name)
-  if id.len > 0:
-    result.setAttribute("id", id)
-  if class.len > 0:
-    result.setAttribute("class", class)
-
-proc tdiv*(id="", class=""): Element = tag("div", id, class)
-proc span*(id="", class=""): Element = tag("span", id, class)
-
-proc th*(s: string): Element =
-  result = tag("th")
-  result.add text(s)
-
-proc td*(s: string): Element =
-  result = tag("td")
-  result.add text(s)
-
-proc td*(s: Element): Element =
-  result = tag("td")
-  result.add s
-
-proc td*(class: string; s: Element): Element =
-  result = tag("td")
-  result.add s
-  result.setAttribute("class", class)
-
-proc table*(class="", kids: varargs[Element]): Element =
-  result = tag("table", "", class)
-  for k in kids: result.add k
-
-proc tr*(kids: varargs[Element]): Element =
-  result = tag("tr")
-  for k in kids:
-    if k.nodeName == cstring"TD" or k.nodeName == cstring"TH":
-      result.add k
-    else:
-      result.add td(k)
-
-proc setClass*(e: Element; value: string) =
-  e.setAttribute("class", value)
-
-proc setAttr*(e: Element; key, value: cstring) =
-  e.setAttribute(key, value)
-
-proc getAttr*(e: Element; key: cstring): cstring {.
-  importcpp: "#.getAttribute(#)", nodecl.}
-
-proc realtimeInput*(id, val: string; changed: proc(value: cstring)): Element =
-  let oldElem = getElementById(id)
-  #if oldElem != nil: return oldElem
-  let newVal = if oldElem.isNil: val else: $oldElem.value
-  var timer: Timeout
-  proc wrapper() =
-    changed(getElementById(id).value)
-    redraw()
-  proc onkeyup(ev: Event) =
-    if timer != nil: clearTimeout(timer)
-    timer = setTimeout(wrapper, 400)
-  result = tree("input", [("type", "text"),
-    ("value", newVal),
-    ("id", id)])
-  result.addEventListener("keyup", onkeyup)
-
-proc ajax(meth, url: cstring; headers: openarray[(string, string)];
-          data: cstring;
-          cont: proc (httpStatus: int; response: cstring)) =
-  proc setRequestHeader(a, b: cstring) {.importc: "ajax.setRequestHeader".}
-  {.emit: """
-  var ajax = new XMLHttpRequest();
-  ajax.open(`meth`,`url`,true);""".}
-  for a, b in items(headers):
-    setRequestHeader(a, b)
-  {.emit: """
-  ajax.onreadystatechange = function(){
-    if(this.readyState == 4){
-      if(this.status == 200){
-        `cont`(this.status, this.responseText);
-      } else {
-        `cont`(this.status, this.statusText);
-      }
-    }
-  }
-  ajax.send(`data`);
-  """.}
-
-proc ajaxPut*(url: string; headers: openarray[(string, string)];
-          data: cstring;
-          cont: proc (httpStatus: int, response: cstring)) =
-  ajax("PUT", url, headers, data, cont)
-
-proc ajaxGet*(url: string; headers: openarray[(string, string)];
-          cont: proc (httpStatus: int, response: cstring)) =
-  ajax("GET", url, headers, nil, cont)
-
-{.push stackTrace:off.}
-
-proc setupErrorHandler*(useAlert=false) =
-  ## Installs an error handler that transforms native JS unhandled
-  ## exceptions into Nim based stack traces. If `useAlert` is false,
-  ## the error message it put into the console, otherwise `alert`
-  ## is called.
-  proc stackTraceAsCstring(): cstring = cstring(getStackTrace())
-  {.emit: """
-  window.onerror = function(msg, url, line, col, error) {
-    var x = "Error: " + msg + "\n" + `stackTraceAsCstring`()
-    if (`useAlert`)
-      alert(x);
-    else
-      console.log(x);
-    var suppressErrorAlert = true;
-    return suppressErrorAlert;
-  };""".}
-
-{.pop.}
diff --git a/tools/finish.nim b/tools/finish.nim
index 4f2c72595..815b99a12 100644
--- a/tools/finish.nim
+++ b/tools/finish.nim
@@ -8,6 +8,9 @@ const
   mingw = "mingw$1-6.3.0.7z" % arch
   url = r"https://nim-lang.org/download/" & mingw
 
+var
+  interactive = true
+
 type
   DownloadResult = enum
     Failure,
@@ -38,19 +41,28 @@ proc downloadMingw(): DownloadResult =
   if cmd.len > 0:
     if execShellCmd(cmd) != 0:
       echo "download failed! ", cmd
-      openDefaultBrowser(url)
-      result = Manual
+      if interactive:
+        openDefaultBrowser(url)
+        result = Manual
+      else:
+        result = Failure
     else:
       if unzip(): result = Success
   else:
-    openDefaultBrowser(url)
-    result = Manual
+    if interactive:
+      openDefaultBrowser(url)
+      result = Manual
+    else:
+      result = Failure
 
 when defined(windows):
   import registry
 
   proc askBool(m: string): bool =
     stdout.write m
+    if not interactive:
+      stdout.writeLine "y (non-interactive mode)"
+      return true
     while true:
       try:
         let answer = stdin.readLine().normalize
@@ -67,6 +79,9 @@ when defined(windows):
   proc askNumber(m: string; a, b: int): int =
     stdout.write m
     stdout.write " [" & $a & ".." & $b & "] "
+    if not interactive:
+      stdout.writeLine $a & " (non-interactive mode)"
+      return a
     while true:
       let answer = stdin.readLine()
       try:
@@ -291,4 +306,6 @@ when isMainModule:
   when defined(testdownload):
     discard downloadMingw()
   else:
+    if "-y" in commandLineParams():
+      interactive = false
     main()
diff --git a/tools/kochdocs.nim b/tools/kochdocs.nim
index 658b9ead7..f109cbbab 100644
--- a/tools/kochdocs.nim
+++ b/tools/kochdocs.nim
@@ -25,7 +25,6 @@ proc findNim*(): string =
   # assume there is a symlink to the exe or something:
   return nim
 
-
 proc exec*(cmd: string, errorcode: int = QuitFailure, additionalPath = "") =
   let prevPath = getEnv("PATH")
   if additionalPath.len > 0:
@@ -38,6 +37,21 @@ proc exec*(cmd: string, errorcode: int = QuitFailure, additionalPath = "") =
   if execShellCmd(cmd) != 0: quit("FAILURE", errorcode)
   putEnv("PATH", prevPath)
 
+template inFold*(desc, body) =
+  if existsEnv("TRAVIS"):
+    echo "travis_fold:start:" & desc.replace(" ", "_")
+
+  body
+
+  if existsEnv("TRAVIS"):
+    echo "travis_fold:end:" & desc.replace(" ", "_")
+
+proc execFold*(desc, cmd: string, errorcode: int = QuitFailure, additionalPath = "") =
+  ## Execute shell command. Add log folding on Travis CI.
+  # https://github.com/travis-ci/travis-ci/issues/2285#issuecomment-42724719
+  inFold(desc):
+    exec(cmd, errorcode, additionalPath)
+
 proc execCleanPath*(cmd: string,
                    additionalPath = ""; errorcode: int = QuitFailure) =
   # simulate a poor man's virtual environment
@@ -56,14 +70,15 @@ proc nimexec*(cmd: string) =
   exec findNim() & " " & cmd
 
 proc nimCompile*(input: string, outputDir = "bin", mode = "c", options = "") =
-  # TODO: simplify pending https://github.com/nim-lang/Nim/issues/9513
-  var cmd = findNim() & " " & mode
   let output = outputDir / input.splitFile.name.exe
-  cmd.add " -o:" & output
-  cmd.add " " & options
-  cmd.add " " & input
+  let cmd = findNim() & " " & mode & " -o:" & output & " " & options & " " & input
   exec cmd
 
+proc nimCompileFold*(desc, input: string, outputDir = "bin", mode = "c", options = "") =
+  let output = outputDir / input.splitFile.name.exe
+  let cmd = findNim() & " " & mode & " -o:" & output & " " & options & " " & input
+  execFold(desc, cmd)
+
 const
   pdf = """
 doc/manual.rst
@@ -101,11 +116,13 @@ doc/nep1.rst
 doc/nims.rst
 doc/contributing.rst
 doc/codeowners.rst
+doc/packaging.rst
 doc/manual/var_t_return.rst
 """.splitWhitespace()
 
   doc = """
 lib/system.nim
+lib/system/io.nim
 lib/system/nimscript.nim
 lib/deprecated/pure/ospaths.nim
 lib/pure/parsejson.nim
@@ -126,7 +143,6 @@ lib/js/asyncjs.nim
 lib/pure/os.nim
 lib/pure/strutils.nim
 lib/pure/math.nim
-lib/pure/matchers.nim
 lib/std/editdistance.nim
 lib/std/wordwrap.nim
 lib/experimental/diff.nim
@@ -161,10 +177,8 @@ lib/impure/db_mysql.nim
 lib/impure/db_sqlite.nim
 lib/impure/db_odbc.nim
 lib/pure/db_common.nim
-lib/pure/httpserver.nim
 lib/pure/httpclient.nim
 lib/pure/smtp.nim
-lib/impure/ssl.nim
 lib/pure/ropes.nim
 lib/pure/unidecode/unidecode.nim
 lib/pure/xmlparser.nim
@@ -174,25 +188,20 @@ lib/pure/colors.nim
 lib/pure/mimetypes.nim
 lib/pure/json.nim
 lib/pure/base64.nim
-lib/pure/scgi.nim
 lib/impure/nre.nim
 lib/impure/nre/private/util.nim
-lib/deprecated/pure/sockets.nim
-lib/deprecated/pure/asyncio.nim
 lib/pure/collections/tables.nim
 lib/pure/collections/sets.nim
 lib/pure/collections/lists.nim
 lib/pure/collections/sharedlist.nim
 lib/pure/collections/sharedtables.nim
 lib/pure/collections/intsets.nim
-lib/pure/collections/queues.nim
 lib/pure/collections/deques.nim
 lib/pure/encodings.nim
 lib/pure/collections/sequtils.nim
 lib/pure/collections/rtarrays.nim
 lib/pure/cookies.nim
 lib/pure/memfiles.nim
-lib/pure/subexes.nim
 lib/pure/collections/critbits.nim
 lib/core/locks.nim
 lib/core/rlocks.nim
@@ -218,7 +227,6 @@ lib/pure/selectors.nim
 lib/pure/sugar.nim
 lib/pure/collections/chains.nim
 lib/pure/asyncfile.nim
-lib/deprecated/pure/ftpclient.nim
 lib/pure/asyncftpclient.nim
 lib/pure/lenientops.nim
 lib/pure/md5.nim
@@ -229,6 +237,7 @@ lib/pure/collections/heapqueue.nim
 lib/pure/fenv.nim
 lib/std/sha1.nim
 lib/std/varints.nim
+lib/std/time_t.nim
 lib/impure/rdstdin.nim
 lib/wrappers/linenoise/linenoise.nim
 lib/pure/strformat.nim
diff --git a/tools/nim-gdb.py b/tools/nim-gdb.py
index 1a0d89fcb..2abaf6926 100644
--- a/tools/nim-gdb.py
+++ b/tools/nim-gdb.py
@@ -1,4 +1,3 @@
-
 import gdb
 import re
 import sys
@@ -16,8 +15,6 @@ def printErrorOnce(id, message):
     errorSet.add(id)
     gdb.write(message, gdb.STDERR)
 
-nimobjfile = gdb.current_objfile() or gdb.objfiles()[0]
-nimobjfile.type_printers = []
 
 ################################################################################
 #####  Type pretty printers
@@ -121,9 +118,6 @@ class NimTypePrinter:
   def instantiate(self):
     return NimTypeRecognizer()
 
-
-nimobjfile.type_printers = [NimTypePrinter()]
-
 ################################################################################
 #####  GDB Function, equivalent of Nim's $ operator
 ################################################################################
@@ -528,5 +522,20 @@ def makematcher(klass):
       printErrorOnce(typeName, "No matcher for type '" + typeName + "': " + str(e) + "\n")
   return matcher
 
-nimobjfile.pretty_printers = []
-nimobjfile.pretty_printers.extend([makematcher(var) for var in list(vars().values()) if hasattr(var, 'pattern')])
+def register_nim_pretty_printers_for_object(objfile):
+  nimMainSym = gdb.lookup_global_symbol("NimMain", gdb.SYMBOL_FUNCTIONS_DOMAIN)
+  if nimMainSym and nimMainSym.symtab.objfile == objfile:
+    print("set Nim pretty printers for ", objfile.filename)
+
+    objfile.type_printers = [NimTypePrinter()]
+    objfile.pretty_printers = [makematcher(var) for var in list(globals().values()) if hasattr(var, 'pattern')]
+
+# Register pretty printers for all objfiles that are already loaded.
+for old_objfile in gdb.objfiles():
+  register_nim_pretty_printers_for_object(old_objfile)
+
+# Register an event handler to register nim pretty printers for all future objfiles.
+def new_object_handler(event):
+  register_nim_pretty_printers_for_object(event.new_objfile)
+
+gdb.events.new_objfile.connect(new_object_handler)
diff --git a/tools/nimgrep.nim b/tools/nimgrep.nim
index 8c6353e31..0a835b038 100644
--- a/tools/nimgrep.nim
+++ b/tools/nimgrep.nim
@@ -160,7 +160,7 @@ proc processFile(pattern; filename: string; counter: var int) =
   var reallyReplace = true
   while i < buffer.len:
     let t = findBounds(buffer, pattern, matches, i)
-    if t.first < 0: break
+    if t.first < 0 or t.last < t.first: break
     inc(line, countLines(buffer, i, t.first-1))
 
     var wholeMatch = buffer.substr(t.first, t.last)
@@ -336,7 +336,7 @@ else:
     for f in items(filenames):
       walker(pegp, f, counter)
   else:
-    var reflags = {reStudy, reExtended}
+    var reflags = {reStudy}
     if optIgnoreStyle in options:
       pattern = styleInsensitive(pattern)
     if optWord in options:
diff --git a/tools/vccexe/vccenv.nim b/tools/vccexe/vccenv.nim
index 6ddf2e29a..12a6e6b3d 100644
--- a/tools/vccexe/vccenv.nim
+++ b/tools/vccexe/vccenv.nim
@@ -16,7 +16,7 @@ type
     vs140 = (140, "VS140COMNTOOLS")  ## Visual Studio 2015
 
 const
-  vcvarsallRelativePath = joinPath("..", "..", "VC", "vcvarsall") ## Relative path from the COMNTOOLS path to the vcvarsall file.
+  vcvarsallRelativePath = joinPath("..", "..", "VC", "vcvarsall.bat") ## Relative path from the COMNTOOLS path to the vcvarsall file.
 
 proc vccEnvVcVarsAllPath*(version: VccEnvVersion = vsUndefined): string = 
   ## Returns the path to the VCC Developer Command Prompt executable for the specified VCC version.
@@ -39,9 +39,9 @@ proc vccEnvVcVarsAllPath*(version: VccEnvVersion = vsUndefined): string =
     for tryVersion in [vs140, vs120, vs110, vs100, vs90]:
       let tryPath = vccEnvVcVarsAllPath(tryVersion)
       if tryPath.len > 0:
-        result = tryPath
+        return tryPath
   else: # Specific version requested
     let key = $version
     let val = getEnv key
     if val.len > 0:
-      result = expandFilename(val & vcvarsallRelativePath)
+      result = try: expandFilename(joinPath(val, vcvarsallRelativePath)) except OSError: ""
diff --git a/tools/vccexe/vccexe.nim b/tools/vccexe/vccexe.nim
index f794885f2..28d9e4173 100644
--- a/tools/vccexe/vccexe.nim
+++ b/tools/vccexe/vccexe.nim
@@ -46,6 +46,8 @@ const
   sdktypeSepIdx = sdktypePrefix.len
   sdkversionSepIdx = sdkversionPrefix.len
   
+  vcvarsallDefaultPath = "vcvarsall.bat"
+
   helpText = """
 +-----------------------------------------------------------------+
 |         Microsoft C/C++ compiler wrapper for Nim                |
@@ -158,6 +160,10 @@ when isMainModule:
     vccversionValue = vccUndefined
     vcvarsallArg = discoverVccVcVarsAllPath()
 
+  if vcvarsallArg == "":
+    # Assume that default executable is in current directory or in PATH
+    vcvarsallArg = findExe(vcvarsallDefaultPath)
+
   if printPathArg:
     var head = $vccversionValue
     if head.len < 1:
@@ -180,9 +186,16 @@ when isMainModule:
 
   if not noCommandArg:
     # Run VCC command with the VCC process environment
-    let vccProcess = startProcess(
-        commandArg,
-        args = clArgs,
-        options = vccOptions
-      )
-    quit vccProcess.waitForExit()
+    try:
+      let vccProcess = startProcess(
+          commandArg,
+          args = clArgs,
+          options = vccOptions
+        )
+      quit vccProcess.waitForExit()
+    except:
+      if vcvarsallArg.len != 0:
+        echo "Hint: using " & vcvarsallArg
+      else:
+        echo "Hint: vcvarsall.bat was not found"
+      raise
diff --git a/tools/vccexe/vcvarsall.nim b/tools/vccexe/vcvarsall.nim
index defcf687f..81b0fb42b 100644
--- a/tools/vccexe/vcvarsall.nim
+++ b/tools/vccexe/vcvarsall.nim
@@ -10,7 +10,6 @@ import strtabs, strutils, os, osproc
 const
   comSpecEnvKey = "ComSpec" ## Environment Variable that specifies the command-line application path in Windows
                             ## Usually set to cmd.exe
-  vcvarsallDefaultPath = "vcvarsall.bat"
 
 type
   VccArch* = enum ## The VCC compile target architectures
@@ -48,11 +47,10 @@ proc vccVarsAll*(path: string, arch: VccArch = vccarchUnspecified, platform_type
   ## verbose
   ##   Echo the command-line passed on to the system to load the VCC environment. Defaults to `false`.
 
-  var vccvarsallpath = path
-  # Assume that default executable is in current directory or in PATH
   if path == "":
-    vccvarsallpath = vcvarsallDefaultPath
+    return nil
   
+  let vccvarsallpath = path
   var args: seq[string] = @[]
   
   let archStr: string = $arch