summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDominik Picheta <dominikpicheta@googlemail.com>2014-09-14 13:11:35 +0100
committerDominik Picheta <dominikpicheta@googlemail.com>2014-09-14 13:11:35 +0100
commit59e5f3533bdb3f02d20a2b402fad92c2d56d50d8 (patch)
treeb20773283e3a99eb3eb20f88247bfa3b15fdd1de
parent8b8841a6c1bbabebdfa8394f5fd3bd5f36202017 (diff)
parentd330a72a4565353bd3ad54ade0580d53cd9d5a5d (diff)
downloadNim-59e5f3533bdb3f02d20a2b402fad92c2d56d50d8.tar.gz
Merge branch 'bigbreak' of github.com:Araq/Nimrod into bigbreak
-rw-r--r--compiler/lambdalifting.nim2
-rw-r--r--compiler/lowerings.nim1
-rw-r--r--compiler/msgs.nim2
-rw-r--r--compiler/options.nim5
-rw-r--r--compiler/pretty.nim6
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--compiler/vm.nim4
-rw-r--r--compiler/vmdeps.nim2
-rw-r--r--compiler/vmgen.nim1
-rw-r--r--doc/basicopt.txt2
-rw-r--r--doc/koch.txt7
-rw-r--r--doc/manual.txt21
-rw-r--r--examples/0mq/client.nim14
-rw-r--r--examples/0mq/server.nim11
-rw-r--r--lib/pure/cookies.nim20
-rw-r--r--lib/pure/strutils.nim35
-rw-r--r--lib/pure/times.nim2
-rw-r--r--lib/pure/xmltree.nim4
-rw-r--r--lib/system/sysio.nim14
-rw-r--r--lib/system/threads.nim1
-rw-r--r--tools/nimweb.nim57
21 files changed, 145 insertions, 68 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index b0595a7a7..194396ddd 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -949,7 +949,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
       discard transformOuterProcBody(o, body, initIter(fn))
       result = ex
     finishEnvironments(o)
-    #if fn.name.s == "cbOuter":
+    #if fn.name.s == "parseLong":
     #  echo rendertree(result, {renderIds})
 
 proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index e90ef9376..8e5ffd48a 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -56,6 +56,7 @@ proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode =
   
   result.add newAsgnStmt(newSymNode(temp), value)
   for i in 0 .. n.len-3:
+    if n.sons[i].kind == nkSym: v.addVar(n.sons[i])
     result.add newAsgnStmt(n.sons[i], newTupleAccess(value, i))
 
 proc createObj*(owner: PSym, info: TLineInfo): PType =
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 622c64359..da2fe122d 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -442,7 +442,7 @@ type
   TNoteKinds* = set[TNoteKind]
 
   TFileInfo*{.final.} = object 
-    fullPath*: string          # This is a canonical full filesystem path
+    fullPath: string           # This is a canonical full filesystem path
     projPath*: string          # This is relative to the project's root
     shortName*: string         # short name of the module
     quotedName*: PRope         # cached quoted short name for codegen
diff --git a/compiler/options.nim b/compiler/options.nim
index 69067b7c4..9d7df2f2b 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -188,8 +188,9 @@ proc getPrefixDir*(): string =
   result = splitPath(getAppDir()).head
 
 proc canonicalizePath*(path: string): string =
-  result = path.expandFilename
-  when not FileSystemCaseSensitive: result = result.toLower
+  #result = path.expandFilename
+  when not FileSystemCaseSensitive: result = path.toLower
+  else: result = path
 
 proc shortenDir*(dir: string): string = 
   ## returns the interesting part of a dir
diff --git a/compiler/pretty.nim b/compiler/pretty.nim
index 9f2074a0b..ec9322309 100644
--- a/compiler/pretty.nim
+++ b/compiler/pretty.nim
@@ -110,7 +110,7 @@ template styleCheckDef*(info: TLineInfo; s: PSym) =
 template styleCheckDef*(s: PSym) =
   styleCheckDef(s.info, s, s.kind)
 
-proc styleCheckUse*(info: TLineInfo; s: PSym) =
+proc styleCheckUseImpl(info: TLineInfo; s: PSym) =
   if info.fileIndex < 0: return
   # we simply convert it to what it looks like in the definition
   # for consistency
@@ -138,3 +138,7 @@ proc styleCheckUse*(info: TLineInfo; s: PSym) =
     system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
     gSourceFiles[info.fileIndex].dirty = true
     #if newName == "File": writeStackTrace()
+
+template styleCheckUse*(info: TLineInfo; s: PSym) =
+  when defined(nimfix):
+    if gStyleCheck != StyleCheck.None: styleCheckUseImpl(info, s)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index aaddc84d0..5cb2eabf8 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -354,7 +354,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
       def = semExprWithType(c, a.sons[length-1], {efAllowDestructor})
       if typ != nil:
         if typ.isMetaType:
-          def = inferWithMetaType(c, typ, def)
+          def = inferWithMetatype(c, typ, def)
           typ = def.typ
         else:
           # BUGFIX: ``fitNode`` is needed here!
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 5ef4576ec..f74f2e0d7 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1135,14 +1135,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcParseExprToAst:
       decodeB(rkNode)
       # c.debug[pc].line.int - countLines(regs[rb].strVal) ?
-      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
+      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath,
                             c.debug[pc].line.int)
       if sonsLen(ast) != 1:
         globalError(c.debug[pc], errExprExpected, "multiple statements")
       regs[ra].node = ast.sons[0]
     of opcParseStmtToAst:
       decodeB(rkNode)
-      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
+      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath,
                             c.debug[pc].line.int)
       regs[ra].node = ast
     of opcCallSite:
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index acf5277c6..6673d0bd2 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -12,11 +12,11 @@ import ast, types, msgs, osproc, streams, options
 proc readOutput(p: Process): string =
   result = ""
   var output = p.outputStream
-  discard p.waitForExit
   while not output.atEnd:
     result.add(output.readLine)
     result.add("\n")
   result.setLen(result.len - "\n".len)
+  discard p.waitForExit
 
 proc opGorge*(cmd, input: string): string =
   var p = startCmd(cmd)
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 3921a69fe..e7f7ad742 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -46,7 +46,6 @@ proc debugInfo(info: TLineInfo): string =
 proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
   # first iteration: compute all necessary labels:
   var jumpTargets = initIntSet()
-
   let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1)
   for i in start..last:
     let x = c.code[i]
diff --git a/doc/basicopt.txt b/doc/basicopt.txt
index 8080e380e..e8aaa2e4c 100644
--- a/doc/basicopt.txt
+++ b/doc/basicopt.txt
@@ -35,3 +35,5 @@ Options:
   -r, --run                 run the compiled program with given arguments
   --advanced                show advanced command line switches
   -h, --help                show this help
+
+Note: Even single letter options require the colon: -p:PATH.
diff --git a/doc/koch.txt b/doc/koch.txt
index a3b7f0df8..7da137458 100644
--- a/doc/koch.txt
+++ b/doc/koch.txt
@@ -138,6 +138,13 @@ from rst to HTML. It also repeats the same operation but places the result in
 the ``web/upload`` which can be used to update the website at
 http://nim-lang.org.
 
+By default the documentation will be built in parallel using the number of
+available CPU cores. If any documentation build sub commands fail, they will
+be rerun in serial fashion so that meaninful error output can be gathered for
+inspection. The ``--parallelBuild:n`` switch or configuration option can be
+used to force a specific number of parallel jobs or run everything serially
+from the start (``n == 1``).
+
 zip command
 -----------
 
diff --git a/doc/manual.txt b/doc/manual.txt
index f0f50e373..3d14ef488 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -596,7 +596,7 @@ Ordinal types
 Ordinal types have the following characteristics:
 
 - Ordinal types are countable and ordered. This property allows
-  the operation of functions as ``Inc``, ``Ord``, ``Dec`` on ordinal types to
+  the operation of functions as ``inc``, ``ord``, ``dec`` on ordinal types to
   be defined.
 - Ordinal values have a smallest possible value. Trying to count further
   down than the smallest value gives a checked runtime or static error.
@@ -699,11 +699,11 @@ lowest and highest value of the type:
 
 .. code-block:: nim
   type
-    TSubrange = range[0..5]
+    Subrange = range[0..5]
 
 
-``TSubrange`` is a subrange of an integer which can only hold the values 0
-to 5. Assigning any other value to a variable of type ``TSubrange`` is a
+``Subrange`` is a subrange of an integer which can only hold the values 0
+to 5. Assigning any other value to a variable of type ``Subrange`` is a
 checked runtime error (or static error if it can be statically
 determined). Assignments from the base type to one of its subrange types
 (and vice versa) are allowed.
@@ -791,6 +791,10 @@ turned off as default.
 The only operations that are affected by the ``floatChecks`` pragma are
 the ``+``, ``-``, ``*``, ``/`` operators for floating point types.
 
+An implementation should always use the maximum precision available to evaluate
+floating pointer values at compile time; this means expressions like
+``0.09'f32 + 0.01'f32 == 0.09'f64 + 0.01'f64`` are true.
+
 
 Boolean type
 ------------
@@ -3675,10 +3679,11 @@ Future versions of Nim may also support overloading based on the return type
 of the overloads. In such settings, the expected result type at call sites may 
 also influence the inferred return type.
 
-Likewise, if a type class is used in another position where Nim expects a
-concrete type (e.g. a variable declaration or a type coercion), Nim will try to
-infer the concrete type by applying the sane matching algorithm also used in
-overload resolution.
+..
+  Likewise, if a type class is used in another position where Nim expects a
+  concrete type (e.g. a variable declaration or a type coercion), Nim will try
+  to infer the concrete type by applying the matching algorithm that also used
+  in overload resolution.
 
 
 Symbol lookup in generics
diff --git a/examples/0mq/client.nim b/examples/0mq/client.nim
deleted file mode 100644
index e75e5c7a2..000000000
--- a/examples/0mq/client.nim
+++ /dev/null
@@ -1,14 +0,0 @@
-import zmq
-
-var connection = zmq.open("tcp://localhost:5555", server=false)
-
-echo("Connecting...")
-
-for i in 0..10:
-  echo("Sending hello...", i)
-  send(connection, "Hello")
-  
-  var reply = receive(connection)
-  echo("Received ...", reply)
-
-close(connection)
diff --git a/examples/0mq/server.nim b/examples/0mq/server.nim
deleted file mode 100644
index 0fadf8b97..000000000
--- a/examples/0mq/server.nim
+++ /dev/null
@@ -1,11 +0,0 @@
-import zmq
-
-var connection = zmq.open("tcp://*:5555", server=true)
-
-while True:
-  var request = receive(connection)
-  echo("Received: ", request)
-  send(connection, "World")
-  
-close(connection)
-
diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim
index c85f60915..6247efed2 100644
--- a/lib/pure/cookies.nim
+++ b/lib/pure/cookies.nim
@@ -28,8 +28,9 @@ proc parseCookies*(s: string): StringTableRef =
     if s[i] == '\0': break
     inc(i) # skip ';'
 
-proc setCookie*(key, value: string, domain = "", path = "", 
-                expires = "", noName = false): string =
+proc setCookie*(key, value: string, domain = "", path = "",
+                expires = "", noName = false,
+                secure = false, httpOnly = false): string =
   ## Creates a command in the format of 
   ## ``Set-Cookie: key=value; Domain=...; ...``
   result = ""
@@ -38,22 +39,23 @@ proc setCookie*(key, value: string, domain = "", path = "",
   if domain != "": result.add("; Domain=" & domain)
   if path != "": result.add("; Path=" & path)
   if expires != "": result.add("; Expires=" & expires)
+  if secure: result.add("; secure")
+  if httpOnly: result.add("; HttpOnly")
 
 proc setCookie*(key, value: string, expires: TimeInfo,
-                domain = "", path = "", noName = false): string =
+                domain = "", path = "", noName = false,
+                secure = false, httpOnly = false): string =
   ## Creates a command in the format of 
   ## ``Set-Cookie: key=value; Domain=...; ...``
   ##
-  ## **Note:** UTC is assumed as the timezone for ``expires``.
-  
+  ## **Note:** UTC is assumed as the timezone for ``expires``.  
   return setCookie(key, value, domain, path,
-            format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), noName)
-  
+                   format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"),
+                   noname, secure, httpOnly)
+
 when isMainModule:
   var tim = Time(int(getTime()) + 76 * (60 * 60 * 24))
 
   echo(setCookie("test", "value", tim.getGMTime()))
   
   echo parseCookies("uid=1; kp=2")
-  
-                
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 2fdf72011..55a204b4c 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -803,6 +803,36 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} =
     if result != -1: return
   return -1
 
+proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect,
+  rtl, extern: "nsuCountString".} =
+  ## Count the occurences of a substring `sub` in the string `s`.
+  ## Overlapping occurences of `sub` only count when `overlapping`
+  ## is set to true.
+  var i = 0
+  while true:
+    i = s.find(sub, i)
+    if i < 0:
+      break
+    if overlapping:
+      inc i
+    else:
+      i += sub.len
+    inc result
+
+proc count*(s: string, sub: char): int {.noSideEffect,
+  rtl, extern: "nsuCountChar".} =
+  ## Count the occurences of the character `sub` in the string `s`.
+  for c in s:
+    if c == sub:
+      inc result
+
+proc count*(s: string, subs: set[char]): int {.noSideEffect,
+  rtl, extern: "nsuCountCharSet".} =
+  ## Count the occurences of the group of character `subs` in the string `s`.
+  for c in s:
+    if c in subs:
+      inc result
+
 proc quoteIfContainsWhite*(s: string): string {.deprecated.} =
   ## Returns ``'"' & s & '"'`` if `s` contains a space and does not
   ## start with a quote, else returns `s`.
@@ -1356,3 +1386,8 @@ when isMainModule:
   doAssert parseEnum[MyEnum]("enu_D") == enuD
 
   doAssert parseEnum("invalid enum value", enC) == enC
+
+  doAssert count("foofoofoo", "foofoo") == 1
+  doAssert count("foofoofoo", "foofoo", overlapping = true) == 2
+  doAssert count("foofoofoo", 'f') == 3
+  doAssert count("foofoofoobar", {'f','b'}) == 4
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index dcc5617fd..1cabd381b 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -514,7 +514,7 @@ elif defined(JS):
     result.setFullYear(timeInfo.year)
     result.setDate(timeInfo.monthday)
   
-  proc `$`(timeInfo: TimeInfo): string = return $(TimeInfoToTIme(timeInfo))
+  proc `$`(timeInfo: TimeInfo): string = return $(timeInfoToTime(timeInfo))
   proc `$`(time: Time): string = return $time.toLocaleString()
     
   proc `-` (a, b: Time): int64 = 
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 37f591f1e..b84da9586 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -154,6 +154,8 @@ proc addEscaped*(result: var string, s: string) =
     of '>': result.add("&gt;")
     of '&': result.add("&amp;")
     of '"': result.add("&quot;")
+    of '\'': result.add("&#x27;")
+    of '/': result.add("&#x2F;")
     else: result.add(c)
 
 proc escape*(s: string): string = 
@@ -167,6 +169,8 @@ proc escape*(s: string): string =
   ##  ``>``          ``&gt;``
   ##  ``&``          ``&amp;``
   ##  ``"``          ``&quot;``
+  ##  ``'``          ``&#x27;``
+  ##  ``/``          ``&#x2F;``
   ## ------------    -------------------
   result = newStringOfCap(s.len)
   addEscaped(result, s)
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 56de5e6e8..7908fbe4d 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -215,13 +215,13 @@ proc open(f: var File, filename: string,
           mode: FileMode = fmRead,
           bufSize: int = -1): bool =
   var p: pointer = fopen(filename, FormatOpen[mode])
-  result = (p != nil)
-  f = cast[File](p)
-  if bufSize > 0 and bufSize <= high(cint).int:
-    if setvbuf(f, nil, IOFBF, bufSize.cint) != 0'i32:
-      sysFatal(OutOfMemError, "out of memory")
-  elif bufSize == 0:
-    discard setvbuf(f, nil, IONBF, 0)
+  if p != nil:
+    result = true
+    f = cast[File](p)
+    if bufSize > 0 and bufSize <= high(cint).int:
+      discard setvbuf(f, nil, IOFBF, bufSize.cint)
+    elif bufSize == 0:
+      discard setvbuf(f, nil, IONBF, 0)
 
 proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool = 
   var p: pointer = freopen(filename, FormatOpen[mode], f)
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 95fa353dd..7dac9d9aa 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -354,7 +354,6 @@ when hostOS == "windows":
                          addr(t), 0'i32, dummyThreadId)
     if t.sys <= 0:
       raise newException(ResourceExhaustedError, "cannot create thread")
-
 else:
   proc createThread*[TArg](t: var TThread[TArg], 
                            tp: proc (arg: TArg) {.thread.}, 
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index 1a5721075..c6602d884 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -21,6 +21,7 @@ type
     nimrodArgs: string
     gitCommit: string
     quotations: TTable[string, tuple[quote, author: string]]
+    numProcessors: int # Set by parallelBuild:n, only works for values > 0.
   TRssItem = object
     year, month, day, title: string
 
@@ -42,6 +43,7 @@ proc initConfigData(c: var TConfigData) =
   c.ticker = ""
   c.vars = newStringTable(modeStyleInsensitive)
   c.gitCommit = "master"
+  c.numProcessors = countProcessors()
   # Attempts to obtain the git current commit.
   let (output, code) = execCmdEx("git log -n 1 --format=%H")
   if code == 0 and output.strip.len == 40:
@@ -121,6 +123,12 @@ proc parseCmdLine(c: var TConfigData) =
         stdout.write(version & "\n")
         quit(0)
       of "o", "output": c.outdir = val
+      of "parallelbuild":
+        try:
+          let num = parseInt(val)
+          if num != 0: c.numProcessors = num
+        except EInvalidValue:
+          quit("invalid numeric value for --parallelBuild")
       of "var":
         var idx = val.find('=')
         if idx < 0: quit("invalid command line")
@@ -187,6 +195,12 @@ proc parseIniFile(c: var TConfigData) =
           of "srcdoc": addFiles(c.srcdoc, "lib", ".nim", split(v, {';'}))
           of "srcdoc2": addFiles(c.srcdoc2, "lib", ".nim", split(v, {';'}))
           of "webdoc": addFiles(c.webdoc, "lib", ".nim", split(v, {';'}))
+          of "parallelbuild":
+            try:
+              let num = parseInt(v)
+              if num != 0: c.numProcessors = num
+            except EInvalidValue:
+              quit("invalid numeric value for --parallelBuild in config")
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "quotations":
           let vSplit = v.split('-')
@@ -215,6 +229,20 @@ proc exec(cmd: string) =
   echo(cmd)
   if os.execShellCmd(cmd) != 0: quit("external program failed")
 
+proc sexec(cmds: openarray[string]) =
+  ## Serial queue wrapper around exec.
+  for cmd in cmds: exec(cmd)
+
+proc mexec(cmds: openarray[string], processors: int) =
+  ## Multiprocessor version of exec
+  if processors < 2:
+    sexec(cmds)
+    return
+
+  if 0 != execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}):
+    echo "external program failed, retrying serial work queue for logs!"
+    sexec(cmds)
+
 proc buildDocSamples(c: var TConfigData, destPath: string) =
   ## Special case documentation sample proc.
   ##
@@ -229,18 +257,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
 
 proc buildDoc(c: var TConfigData, destPath: string) =
   # call nim for the documentation:
+  var
+    commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2))
+    i = 0
   for d in items(c.doc):
-    exec("nim rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
+    commands[i] = "nim rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(d).name, "html"), d]
+    i.inc
   for d in items(c.srcdoc):
-    exec("nim doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
+    commands[i] = "nim doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(d).name, "html"), d]
+    i.inc
   for d in items(c.srcdoc2):
-    exec("nim doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
+    commands[i] = "nim doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(d).name, "html"), d]
+    i.inc
+
+  mexec(commands, c.numProcessors)
   exec("nim buildIndex -o:$1/theindex.html $1" % [destPath])
 
 proc buildPdfDoc(c: var TConfigData, destPath: string) =
@@ -264,10 +300,17 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
 
 proc buildAddDoc(c: var TConfigData, destPath: string) =
   # build additional documentation (without the index):
+<<<<<<< HEAD
+  var commands = newSeq[string](c.webdoc.len)
+  for i, doc in pairs(c.webdoc):
+    commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" %
+=======
   for d in items(c.webdoc):
     exec("nim doc $# --docSeeSrcUrl:$# -o:$# $#" %
+>>>>>>> 0047172274a73c681f619f5cd60aaad7109f694d
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(doc).name, "html"), doc]
+  mexec(commands, c.numProcessors)
 
 proc parseNewsTitles(inputFilename: string): seq[TRssItem] =
   # parses the file for titles and returns them as TRssItem blocks.