summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/alloc.nim15
-rw-r--r--lib/system/ansi_c.nim8
-rw-r--r--lib/system/assign.nim8
-rw-r--r--lib/system/debugger.nim6
-rw-r--r--lib/system/dyncalls.nim5
-rw-r--r--lib/system/endb.nim30
-rw-r--r--lib/system/excpt.nim8
-rw-r--r--lib/system/gc.nim23
-rw-r--r--lib/system/gc2.nim6
-rw-r--r--lib/system/gc_ms.nim4
-rw-r--r--lib/system/nimscript.nim2
-rw-r--r--lib/system/repr.nim21
-rw-r--r--lib/system/reprjs.nim36
-rw-r--r--lib/system/sysio.nim23
-rw-r--r--lib/system/sysspawn.nim2
-rw-r--r--lib/system/sysstr.nim33
-rw-r--r--lib/system/threads.nim2
17 files changed, 142 insertions, 90 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 78db96e77..19d27e7d2 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -301,13 +301,14 @@ proc pageAddr(p: pointer): PChunk {.inline.} =
   result = cast[PChunk](cast[ByteAddress](p) and not PageMask)
   #sysAssert(Contains(allocator.chunkStarts, pageIndex(result)))
 
-proc writeFreeList(a: MemRegion) =
-  var it = a.freeChunksList
-  c_fprintf(stdout, "freeChunksList: %p\n", it)
-  while it != nil:
-    c_fprintf(stdout, "it: %p, next: %p, prev: %p, size: %ld\n",
-              it, it.next, it.prev, it.size)
-    it = it.next
+when false:
+  proc writeFreeList(a: MemRegion) =
+    var it = a.freeChunksList
+    c_fprintf(stdout, "freeChunksList: %p\n", it)
+    while it != nil:
+      c_fprintf(stdout, "it: %p, next: %p, prev: %p, size: %ld\n",
+                it, it.next, it.prev, it.size)
+      it = it.next
 
 const nimMaxHeap {.intdefine.} = 0
 
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index b2f6d314f..0bac979e7 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -103,8 +103,12 @@ proc c_sprintf(buf, frmt: cstring): cint {.
   importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.}
   # we use it only in a way that cannot lead to security issues
 
-proc c_fileno(f: File): cint {.
-  importc: "fileno", header: "<fcntl.h>".}
+when defined(windows):
+  proc c_fileno(f: File): cint {.
+      importc: "_fileno", header: "<stdio.h>".}
+else:
+  proc c_fileno(f: File): cint {.
+      importc: "fileno", header: "<fcntl.h>".}
 
 proc c_malloc(size: csize): pointer {.
   importc: "malloc", header: "<stdlib.h>".}
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index 115df61a7..f061c89cf 100644
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -61,13 +61,17 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
       unsureAsgnRef(x, s2)
       return
     sysAssert(dest != nil, "genericAssignAux 3")
-    unsureAsgnRef(x, newSeq(mt, seq.len))
-    var dst = cast[ByteAddress](cast[PPointer](dest)[])
     if ntfNoRefs in mt.base.flags:
+      var ss = nimNewSeqOfCap(mt, seq.len)
+      cast[PGenericSeq](ss).len = seq.len
+      unsureAsgnRef(x, ss)
+      var dst = cast[ByteAddress](cast[PPointer](dest)[])
       copyMem(cast[pointer](dst +% GenericSeqSize),
               cast[pointer](cast[ByteAddress](s2) +% GenericSeqSize),
               seq.len * mt.base.size)
     else:
+      unsureAsgnRef(x, newSeq(mt, seq.len))
+      var dst = cast[ByteAddress](cast[PPointer](dest)[])
       for i in 0..seq.len-1:
         genericAssignAux(
           cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
diff --git a/lib/system/debugger.nim b/lib/system/debugger.nim
index cc6919d36..937c0d6f0 100644
--- a/lib/system/debugger.nim
+++ b/lib/system/debugger.nim
@@ -127,7 +127,7 @@ proc fileMatches(c, bp: cstring): bool =
 
 proc canonFilename*(filename: cstring): cstring =
   ## returns 'nil' if the filename cannot be found.
-  for i in 0 .. <dbgFilenameLen:
+  for i in 0 .. dbgFilenameLen-1:
     result = dbgFilenames[i]
     if fileMatches(result, filename): return result
   result = nil
@@ -261,7 +261,7 @@ proc genericHash(dest: pointer, mt: PNimType): int =
 proc dbgRegisterWatchpoint(address: pointer, name: cstring,
                            typ: PNimType) {.compilerproc.} =
   let L = watchPointsLen
-  for i in 0.. <L:
+  for i in 0 .. pred(L):
     if watchPoints[i].name == name:
       # address may have changed:
       watchPoints[i].address = address
@@ -288,7 +288,7 @@ var
 
 proc checkWatchpoints =
   let L = watchPointsLen
-  for i in 0.. <L:
+  for i in 0 .. pred(L):
     let newHash = genericHash(watchPoints[i].address, watchPoints[i].typ)
     if newHash != watchPoints[i].oldValue:
       dbgWatchpointHook(watchPoints[i].name)
diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim
index 2b86ddf25..c8e251d1e 100644
--- a/lib/system/dyncalls.nim
+++ b/lib/system/dyncalls.nim
@@ -142,7 +142,10 @@ elif defined(windows) or defined(dos):
         dec(m)
         k = k div 10
         if k == 0: break
-      result = getProcAddress(cast[THINSTANCE](lib), decorated)
+      when defined(nimNoArrayToCstringConversion):
+        result = getProcAddress(cast[THINSTANCE](lib), addr decorated)
+      else:
+        result = getProcAddress(cast[THINSTANCE](lib), decorated)
       if result != nil: return
     procAddrError(name)
 
diff --git a/lib/system/endb.nim b/lib/system/endb.nim
index d4d10a52c..35d8f25c4 100644
--- a/lib/system/endb.nim
+++ b/lib/system/endb.nim
@@ -76,10 +76,10 @@ proc `==`(a, b: StaticStr): bool =
     return true
 
 proc `==`(a: StaticStr, b: cstring): bool =
-  result = c_strcmp(a.data, b) == 0
+  result = c_strcmp(unsafeAddr a.data, b) == 0
 
 proc write(f: File, s: StaticStr) =
-  write(f, cstring(s.data))
+  write(f, cstring(unsafeAddr s.data))
 
 proc listBreakPoints() =
   write(stdout, EndbBeg)
@@ -260,8 +260,8 @@ proc parseBreakpoint(s: cstring, start: int): Breakpoint =
   if result.high == 0: result.high = result.low
   i = scanFilename(s, dbgTemp, i)
   if dbgTemp.len != 0:
-    if not hasExt(dbgTemp.data): add(dbgTemp, ".nim")
-    result.filename = canonFilename(dbgTemp.data.cstring)
+    if not hasExt(addr dbgTemp.data): add(dbgTemp, ".nim")
+    result.filename = canonFilename(addr dbgTemp.data)
     if result.filename.isNil:
       debugOut("[Warning] no breakpoint could be set; unknown filename ")
       return
@@ -292,12 +292,12 @@ proc dbgEvaluate(stream: File, s: cstring, start: int, f: PFrame) =
     i = scanAndAppendWord(s, dbgTemp, i)
     for i in 0 .. getGlobalLen()-1:
       let v = getGlobal(i)
-      if c_strcmp(v.name, dbgTemp.data) == 0:
+      if c_strcmp(v.name, addr dbgTemp.data) == 0:
         writeVariable(stream, v)
   else:
     for i in 0 .. f.len-1:
       let v = getLocal(f, i)
-      if c_strcmp(v.name, dbgTemp.data) == 0:
+      if c_strcmp(v.name, addr dbgTemp.data) == 0:
         writeVariable(stream, v)
 
 proc dbgOut(s: cstring, start: int, currFrame: PFrame) =
@@ -306,7 +306,7 @@ proc dbgOut(s: cstring, start: int, currFrame: PFrame) =
   if dbgTemp.len == 0:
     invalidCommand()
     return
-  var stream = openAppend(dbgTemp.data)
+  var stream = openAppend(addr dbgTemp.data)
   if stream == nil:
     debugOut("[Warning] could not open or create file ")
     return
@@ -320,7 +320,7 @@ proc dbgStackFrame(s: cstring, start: int, currFrame: PFrame) =
     # just write it to stdout:
     listFrame(stdout, currFrame)
   else:
-    var stream = openAppend(dbgTemp.data)
+    var stream = openAppend(addr dbgTemp.data)
     if stream == nil:
       debugOut("[Warning] could not open or create file ")
       return
@@ -369,7 +369,7 @@ proc commandPrompt() =
     if not readLine(stdin, dbgUser): break
     if dbgUser.len == 0: dbgUser.len = oldLen
     # now look what we have to do:
-    var i = scanWord(dbgUser.data, dbgTemp, 0)
+    var i = scanWord(addr dbgUser.data, dbgTemp, 0)
     template `?`(x: expr): expr = dbgTemp == cstring(x)
     if ?"s" or ?"step":
       dbgState = dbStepInto
@@ -400,13 +400,13 @@ proc commandPrompt() =
         prevState = dbgState
         prevSkipFrame = dbgSkipToFrame
       dbgState = dbSkipCurrent
-      dbgEvaluate(stdout, dbgUser.data, i, dbgFramePtr)
+      dbgEvaluate(stdout, addr dbgUser.data, i, dbgFramePtr)
       dbgState = prevState
       dbgSkipToFrame = prevSkipFrame
     elif ?"o" or ?"out":
-      dbgOut(dbgUser.data, i, dbgFramePtr)
+      dbgOut(addr dbgUser.data, i, dbgFramePtr)
     elif ?"stackframe":
-      dbgStackFrame(dbgUser.data, i, dbgFramePtr)
+      dbgStackFrame(addr dbgUser.data, i, dbgFramePtr)
     elif ?"w" or ?"where":
       dbgShowExecutionPoint()
     elif ?"l" or ?"locals":
@@ -444,16 +444,16 @@ proc commandPrompt() =
     elif ?"bt" or ?"backtrace":
       dbgWriteStackTrace(framePtr)
     elif ?"b" or ?"break":
-      createBreakPoint(dbgUser.data, i)
+      createBreakPoint(addr dbgUser.data, i)
     elif ?"breakpoints":
       listBreakPoints()
     elif ?"toggle":
-      breakpointToggle(dbgUser.data, i)
+      breakpointToggle(addr dbgUser.data, i)
     elif ?"filenames":
       listFilenames()
     elif ?"maxdisplay":
       var parsed: int
-      i = scanNumber(dbgUser.data, parsed, i)
+      i = scanNumber(addr dbgUser.data, parsed, i)
       if dbgUser.data[i-1] in {'0'..'9'}:
         if parsed == 0: maxDisplayRecDepth = -1
         else: maxDisplayRecDepth = parsed
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index db4d70613..f2b5997cc 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -306,8 +306,12 @@ proc raiseExceptionAux(e: ref Exception) =
         add(buf, " [")
         xadd(buf, e.name, e.name.len)
         add(buf, "]\n")
-        unhandled(buf):
-          showErrorMessage(buf)
+        when defined(nimNoArrayToCstringConversion):
+          template tbuf(): untyped = addr buf
+        else:
+          template tbuf(): untyped = buf
+        unhandled(tbuf()):
+          showErrorMessage(tbuf())
           quitOrDebug()
 
 proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index a2ff72a30..68bf5f6c2 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -155,14 +155,15 @@ template setColor(c, col) =
   else:
     c.refcount = c.refcount and not colorMask or col
 
-proc writeCell(msg: cstring, c: PCell) =
-  var kind = -1
-  var typName: cstring = "nil"
-  if c.typ != nil:
-    kind = ord(c.typ.kind)
-    when defined(nimTypeNames):
-      if not c.typ.name.isNil:
-        typName = c.typ.name
+when defined(logGC):
+  proc writeCell(msg: cstring, c: PCell) =
+    var kind = -1
+    var typName: cstring = "nil"
+    if c.typ != nil:
+      kind = ord(c.typ.kind)
+      when defined(nimTypeNames):
+        if not c.typ.name.isNil:
+          typName = c.typ.name
 
   when leakDetector:
     c_fprintf(stdout, "[GC] %s: %p %d %s rc=%ld from %s(%ld)\n",
@@ -642,9 +643,9 @@ when useMarkForDebug or useBackupGc:
         forAllChildren(d, waMarkPrecise)
 
   proc markGlobals(gch: var GcHeap) =
-    for i in 0 .. < globalMarkersLen: globalMarkers[i]()
+    for i in 0 .. globalMarkersLen-1: globalMarkers[i]()
     let d = gch.additionalRoots.d
-    for i in 0 .. < gch.additionalRoots.len: markS(gch, d[i])
+    for i in 0 .. gch.additionalRoots.len-1: markS(gch, d[i])
 
 when logGC:
   var
@@ -652,7 +653,7 @@ when logGC:
     cycleCheckALen = 0
 
   proc alreadySeen(c: PCell): bool =
-    for i in 0 .. <cycleCheckALen:
+    for i in 0 .. cycleCheckALen-1:
       if cycleCheckA[i] == c: return true
     if cycleCheckALen == len(cycleCheckA):
       gcAssert(false, "cycle detection overflow")
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index 6dffc323e..70bed8740 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -487,12 +487,12 @@ proc GC_dumpHeap*(file: File) =
   var spaceIter: ObjectSpaceIter
   when false:
     var d = gch.decStack.d
-    for i in 0 .. < gch.decStack.len:
+    for i in 0 .. gch.decStack.len-1:
       if isAllocatedPtr(gch.region, d[i]):
         c_fprintf(file, "onstack %p\n", d[i])
       else:
         c_fprintf(file, "onstack_invalid %p\n", d[i])
-  for i in 0 .. < globalMarkersLen: globalMarkers[i]()
+  for i in 0 .. globalMarkersLen-1: globalMarkers[i]()
   while true:
     let x = allObjectsAsProc(gch.region, addr spaceIter)
     if spaceIter.state < 0: break
@@ -579,7 +579,7 @@ proc markIncremental(gch: var GcHeap): bool =
   result = true
 
 proc markGlobals(gch: var GcHeap) =
-  for i in 0 .. < globalMarkersLen: globalMarkers[i]()
+  for i in 0 .. globalMarkersLen-1: globalMarkers[i]()
 
 proc doOperation(p: pointer, op: WalkOp) =
   if p == nil: return
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index cfc0dfa8a..272047bb7 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -450,9 +450,9 @@ when false:
           quit 1
 
 proc markGlobals(gch: var GcHeap) =
-  for i in 0 .. < globalMarkersLen: globalMarkers[i]()
+  for i in 0 .. globalMarkersLen-1: globalMarkers[i]()
   let d = gch.additionalRoots.d
-  for i in 0 .. < gch.additionalRoots.len: mark(gch, d[i])
+  for i in 0 .. gch.additionalRoots.len-1: mark(gch, d[i])
 
 proc gcMark(gch: var GcHeap, p: pointer) {.inline.} =
   # the addresses are not as cells on the stack, so turn them to cells:
diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim
index f5b9cf3ed..f91dae41e 100644
--- a/lib/system/nimscript.nim
+++ b/lib/system/nimscript.nim
@@ -106,7 +106,7 @@ proc cmpic*(a, b: string): int =
   ## Compares `a` and `b` ignoring case.
   cmpIgnoreCase(a, b)
 
-proc getEnv*(key: string): string {.tags: [ReadIOEffect].} =
+proc getEnv*(key: string; default = ""): string {.tags: [ReadIOEffect].} =
   ## Retrieves the environment variable of name `key`.
   builtin
 
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index ab02c58a2..982b07467 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -16,34 +16,39 @@ proc reprInt(x: int64): string {.compilerproc.} = return $x
 proc reprFloat(x: float): string {.compilerproc.} = return $x
 
 proc reprPointer(x: pointer): string {.compilerproc.} =
-  var buf: array[0..59, char]
-  discard c_sprintf(buf, "%p", x)
-  return $buf
+  when defined(nimNoArrayToCstringConversion):
+    result = newString(60)
+    let n = c_sprintf(addr result[0], "%p", x)
+    setLen(result, n)
+  else:
+    var buf: array[0..59, char]
+    discard c_sprintf(buf, "%p", x)
+    return $buf
 
 proc `$`(x: uint64): string =
   if x == 0:
     result = "0"
   else:
-    var buf: array[60, char]
+    result = newString(60)
     var i = 0
     var n = x
     while n != 0:
       let nn = n div 10'u64
-      buf[i] = char(n - 10'u64 * nn + ord('0'))
+      result[i] = char(n - 10'u64 * nn + ord('0'))
       inc i
       n = nn
+    result.setLen i
 
     let half = i div 2
     # Reverse
-    for t in 0 .. < half: swap(buf[t], buf[i-t-1])
-    result = $buf
+    for t in 0 .. half-1: swap(result[t], result[i-t-1])
 
 proc reprStrAux(result: var string, s: cstring; len: int) =
   if cast[pointer](s) == nil:
     add result, "nil"
     return
   add result, reprPointer(cast[pointer](s)) & "\""
-  for i in 0.. <len:
+  for i in 0 .. pred(len):
     let c = s[i]
     case c
     of '"': add result, "\\\""
diff --git a/lib/system/reprjs.nim b/lib/system/reprjs.nim
index 5c265a891..658220c11 100644
--- a/lib/system/reprjs.nim
+++ b/lib/system/reprjs.nim
@@ -9,13 +9,13 @@
 # The generic ``repr`` procedure for the javascript backend.
 
 proc reprInt(x: int64): string {.compilerproc.} = return $x
-proc reprFloat(x: float): string {.compilerproc.} = 
+proc reprFloat(x: float): string {.compilerproc.} =
   # Js toString doesn't differentiate between 1.0 and 1,
   # but we do.
   if $x == $(x.int): $x & ".0"
   else: $x
 
-proc reprPointer(p: pointer): string {.compilerproc.} = 
+proc reprPointer(p: pointer): string {.compilerproc.} =
   # Do we need to generate the full 8bytes ? In js a pointer is an int anyway
   var tmp: int
   {. emit: """
@@ -38,7 +38,7 @@ proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
     result = $typ.node.sons[e].name
   else:
     result = $e & " (invalid data!)"
-  
+
 proc reprChar(x: char): string {.compilerRtl.} =
   result = "\'"
   case x
@@ -50,7 +50,7 @@ proc reprChar(x: char): string {.compilerRtl.} =
 
 proc reprStrAux(result: var string, s: cstring, len: int) =
   add(result, "\"")
-  for i in 0 .. <len:
+  for i in 0 .. len-1:
     let c = s[i]
     case c
     of '"': add(result, "\\\"")
@@ -67,7 +67,7 @@ proc reprStr(s: string): string {.compilerRtl.} =
   if cast[pointer](s).isNil:
     # Handle nil strings here because they don't have a length field in js
     # TODO: check for null/undefined before generating call to length in js?
-    # Also: c backend repr of a nil string is <pointer>"", but repr of an 
+    # Also: c backend repr of a nil string is <pointer>"", but repr of an
     # array of string that is not initialized is [nil, nil, ...] ??
     add(result, "nil")
   else:
@@ -86,7 +86,7 @@ proc addSetElem(result: var string, elem: int, typ: PNimType) =
 
 iterator setKeys(s: int): int {.inline.} =
   # The type of s is a lie, but it's expected to be a set.
-  # Iterate over the JS object representing a set 
+  # Iterate over the JS object representing a set
   # and returns the keys as int.
   var len: int
   var yieldRes: int
@@ -124,16 +124,16 @@ proc initReprClosure(cl: var ReprClosure) =
   cl.recDepth = -1 # default is to display everything!
   cl.indent = 0
 
-proc reprAux(result: var string, p: pointer, typ: PNimType, cl: var ReprClosure) 
+proc reprAux(result: var string, p: pointer, typ: PNimType, cl: var ReprClosure)
 
-proc reprArray(a: pointer, typ: PNimType, 
+proc reprArray(a: pointer, typ: PNimType,
               cl: var ReprClosure): string {.compilerRtl.} =
   var isNilArrayOrSeq: bool
   # isnil is not enough here as it would try to deref `a` without knowing what's inside
   {. emit: """
-    if (`a` == null) { 
+    if (`a` == null) {
       `isNilArrayOrSeq` = true;
-    } else if (`a`[0] == null) { 
+    } else if (`a`[0] == null) {
       `isNilArrayOrSeq` = true;
     } else {
       `isNilArrayOrSeq` = false;
@@ -146,19 +146,19 @@ proc reprArray(a: pointer, typ: PNimType,
   result = if typ.kind == tySequence: "@[" else: "["
   var len: int = 0
   var i: int = 0
-    
+
   {. emit: "`len` = `a`.length;\n" .}
   var dereffed: pointer = a
-  for i in 0 .. < len:
+  for i in 0 .. len-1:
     if i > 0 :
       add(result, ", ")
     # advance pointer and point to element at index
     {. emit: """
-    `dereffed`_Idx = `i`; 
+    `dereffed`_Idx = `i`;
     `dereffed` = `a`[`dereffed`_Idx];
     """ .}
     reprAux(result, dereffed, typ.base, cl)
-  
+
   add(result, "]")
 
 proc isPointedToNil(p: pointer): bool {.inline.}=
@@ -181,7 +181,7 @@ proc reprRef(result: var string, p: pointer, typ: PNimType,
 
 proc reprRecordAux(result: var string, o: pointer, typ: PNimType, cl: var ReprClosure) =
   add(result, "[")
-  
+
   var first: bool = true
   var val: pointer = o
   if typ.node.len == 0:
@@ -192,7 +192,7 @@ proc reprRecordAux(result: var string, o: pointer, typ: PNimType, cl: var ReprCl
     reprAux(result, val, typ.node.typ, cl)
   else:
     # if the object has more than one field, sons is not nil and contains the fields.
-    for i in 0 .. <typ.node.len:
+    for i in 0 .. typ.node.len-1:
       if first: first = false
       else: add(result, ",\n")
 
@@ -214,11 +214,11 @@ proc reprJSONStringify(p: int): string {.compilerRtl.} =
   {. emit: "`tmp` = JSON.stringify(`p`);\n" .}
   result = $tmp
 
-proc reprAux(result: var string, p: pointer, typ: PNimType, 
+proc reprAux(result: var string, p: pointer, typ: PNimType,
             cl: var ReprClosure) =
   if cl.recDepth == 0:
     add(result, "...")
-    return 
+    return
   dec(cl.recDepth)
   case typ.kind
   of tyInt..tyInt64, tyUInt..tyUInt64:
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 7b6d93fe0..a40fcc67d 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -15,9 +15,12 @@
 {.push debugger:off .} # the user does not want to trace a part
                        # of the standard library!
 
-
-proc c_fdopen(filehandle: cint, mode: cstring): File {.
-  importc: "fdopen", header: "<stdio.h>".}
+when defined(windows):
+  proc c_fdopen(filehandle: cint, mode: cstring): File {.
+    importc: "_fdopen", header: "<stdio.h>".}
+else:
+  proc c_fdopen(filehandle: cint, mode: cstring): File {.
+    importc: "fdopen", header: "<stdio.h>".}
 proc c_fputs(c: cstring, f: File): cint {.
   importc: "fputs", header: "<stdio.h>", tags: [WriteIOEffect].}
 proc c_fgets(c: cstring, n: cint, f: File): cstring {.
@@ -401,4 +404,18 @@ proc setStdIoUnbuffered() =
   when declared(stdin):
     discard c_setvbuf(stdin, nil, IONBF, 0)
 
+when declared(stdout):
+  proc echoBinSafe(args: openArray[string]) {.compilerProc.} =
+    when not defined(windows):
+      proc flockfile(f: File) {.importc, noDecl.}
+      proc funlockfile(f: File) {.importc, noDecl.}
+      flockfile(stdout)
+    for s in args:
+      discard c_fwrite(s.cstring, s.len, 1, stdout)
+    const linefeed = "\n" # can be 1 or more chars
+    discard c_fwrite(linefeed.cstring, linefeed.len, 1, stdout)
+    discard c_fflush(stdout)
+    when not defined(windows):
+      funlockfile(stdout)
+
 {.pop.}
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index 7da45b4dd..a0d10c446 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -142,7 +142,7 @@ var
   workersData: array[NumThreads, Worker]
 
 proc setup() =
-  for i in 0.. <NumThreads:
+  for i in 0 ..< NumThreads:
     workersData[i].taskArrived = createCondVar()
     workersData[i].taskStarted = createFastCondVar()
     createThread(workers[i], slave, addr(workersData[i]))
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 90201202c..0627ef2fb 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -24,7 +24,10 @@ proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
   if a == b: return 0
   if a == nil: return -1
   if b == nil: return 1
-  return c_strcmp(a.data, b.data)
+  when defined(nimNoArrayToCstringConversion):
+    return c_strcmp(addr a.data, addr b.data)
+  else:
+    return c_strcmp(a.data, b.data)
 
 proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
   if a == b: return true
@@ -275,7 +278,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
                             GenericSeqSize +% (i*%elemSize)),
                             extGetCellType(result).base, waPush)
           let len1 = gch.tempStack.len
-          for i in len0 .. <len1:
+          for i in len0 ..< len1:
             doDecRef(gch.tempStack.d[i], LocalHeap, MaybeCyclic)
           gch.tempStack.len = len0
       else:
@@ -320,7 +323,10 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
 
 proc add*(result: var string; x: float) =
   var buf: array[0..64, char]
-  var n: int = c_sprintf(buf, "%.16g", x)
+  when defined(nimNoArrayToCstringConversion):
+    var n: int = c_sprintf(addr buf, "%.16g", x)
+  else:
+    var n: int = c_sprintf(buf, "%.16g", x)
   var hasDot = false
   for i in 0..n-1:
     if buf[i] == ',':
@@ -332,9 +338,10 @@ proc add*(result: var string; x: float) =
     buf[n] = '.'
     buf[n+1] = '0'
     buf[n+2] = '\0'
-  # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' are produced.
+  # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN'
+  # of '-1.#IND' are produced.
   # We want to get rid of these here:
-  if buf[n-1] in {'n', 'N'}:
+  if buf[n-1] in {'n', 'N', 'D', 'd'}:
     result.add "nan"
   elif buf[n-1] == 'F':
     if buf[0] == '-':
@@ -342,7 +349,10 @@ proc add*(result: var string; x: float) =
     else:
       result.add "inf"
   else:
-    result.add buf
+    var i = 0
+    while buf[i] != '\0':
+      result.add buf[i]
+      inc i
 
 proc nimFloatToStr(f: float): string {.compilerproc.} =
   result = newStringOfCap(8)
@@ -353,9 +363,9 @@ proc c_strtod(buf: cstring, endptr: ptr cstring): float64 {.
 
 const
   IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
-  powtens =   [ 1e0,   1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,  1e8,  1e9,
-                1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
-                1e20, 1e21, 1e22]
+  powtens =  [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+              1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+              1e20, 1e21, 1e22]
 
 proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
                           start = 0): int {.compilerProc.} =
@@ -507,7 +517,10 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
   t[ti-2] = ('0'.ord + abs_exponent mod 10).char; abs_exponent = abs_exponent div 10
   t[ti-3] = ('0'.ord + abs_exponent mod 10).char
 
-  number = c_strtod(t, nil)
+  when defined(nimNoArrayToCstringConversion):
+    number = c_strtod(addr t, nil)
+  else:
+    number = c_strtod(t, nil)
 
 proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
   result = newStringOfCap(sizeof(x)*4)
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 96c045e6b..016bf5822 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -398,7 +398,7 @@ template afterThreadRuns() =
     threadDestructionHandlers[i]()
 
 when not defined(boehmgc) and not hasSharedHeap and not defined(gogc) and not defined(gcRegions):
-  proc deallocOsPages()
+  proc deallocOsPages() {.rtl.}
 
 when defined(boehmgc):
   type GCStackBaseProc = proc(sb: pointer, t: pointer) {.noconv.}