summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/core/macros.nim2
-rw-r--r--lib/pure/asyncdispatch.nim15
-rw-r--r--lib/pure/asyncnet.nim2
-rw-r--r--lib/pure/distros.nim244
-rw-r--r--lib/pure/endians.nim113
-rw-r--r--lib/pure/math.nim2
-rw-r--r--lib/pure/os.nim2
-rw-r--r--lib/pure/times.nim2
-rw-r--r--lib/pure/xmldom.nim4
-rw-r--r--lib/system.nim82
-rw-r--r--lib/system/alloc.nim9
-rw-r--r--lib/system/nimscript.nim44
-rw-r--r--lib/upcoming/asyncdispatch.nim12
-rw-r--r--lib/windows/winlean.nim2
14 files changed, 438 insertions, 97 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index b0ef54397..3adf4670d 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -80,7 +80,7 @@ type
   NimNodeKinds* = set[NimNodeKind]
   NimTypeKind* = enum  # some types are no longer used, see ast.nim
     ntyNone, ntyBool, ntyChar, ntyEmpty,
-    ntyArrayConstr, ntyNil, ntyExpr, ntyStmt,
+    ntyAlias, ntyNil, ntyExpr, ntyStmt,
     ntyTypeDesc, ntyGenericInvocation, ntyGenericBody, ntyGenericInst,
     ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal,
     ntyArray, ntyObject, ntyTuple, ntySet,
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index 1367bc411..b72596060 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -254,8 +254,14 @@ when defined(windows) or defined(nimdoc):
         "Operation performed on a socket which has not been registered with" &
         " the dispatcher yet.")
 
+  proc hasPendingOperations*(): bool =
+    ## Returns `true` if the global dispatcher has pending operations.
+    let p = getGlobalDispatcher()
+    p.handles.len != 0 or p.timers.len != 0 or p.callbacks.len != 0
+
   proc poll*(timeout = 500) =
-    ## Waits for completion events and processes them.
+    ## Waits for completion events and processes them. Raises ``ValueError``
+    ## if there are no pending operations.
     let p = getGlobalDispatcher()
     if p.handles.len == 0 and p.timers.len == 0 and p.callbacks.len == 0:
       raise newException(ValueError,
@@ -1056,8 +1062,15 @@ else:
           newCBs.add(cb)
     callbacks = newCBs & callbacks
 
+  proc hasPendingOperations*(): bool =
+    let p = getGlobalDispatcher()
+    p.selector.len != 0 or p.timers.len != 0 or p.callbacks.len != 0
+
   proc poll*(timeout = 500) =
     let p = getGlobalDispatcher()
+    if p.selector.len == 0 and p.timers.len == 0 and p.callbacks.len == 0:
+      raise newException(ValueError,
+        "No handles or timers registered in dispatcher.")
 
     if p.selector.len > 0:
       for info in p.selector.select(p.adjustedTimeout(timeout)):
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index 3b64c278f..5ad3b5263 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -36,12 +36,14 @@
 ##   proc processClient(client: AsyncSocket) {.async.} =
 ##     while true:
 ##       let line = await client.recvLine()
+##       if line.len == 0: break
 ##       for c in clients:
 ##         await c.send(line & "\c\L")
 ##
 ##   proc serve() {.async.} =
 ##     clients = @[]
 ##     var server = newAsyncSocket()
+##     server.setSockOpt(OptReuseAddr, true)
 ##     server.bindAddr(Port(12345))
 ##     server.listen()
 ##
diff --git a/lib/pure/distros.nim b/lib/pure/distros.nim
new file mode 100644
index 000000000..ff30f6134
--- /dev/null
+++ b/lib/pure/distros.nim
@@ -0,0 +1,244 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2016 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements the basics for Linux distribution ("distro")
+## detection and the OS's native package manager. Its primary purpose is to
+## produce output for Nimble packages like::
+##
+##  To complete the installation, run:
+##
+##  sudo apt-get libblas-dev
+##  sudo apt-get libvoodoo
+##
+## The above output could be the result of a code snippet like:
+##
+## .. code-block:: nim
+##
+##   if detectOs(Ubuntu):
+##     foreignDep "lbiblas-dev"
+##     foreignDep "libvoodoo"
+##
+
+from strutils import contains, toLowerAscii
+
+when not defined(nimscript):
+  from osproc import execProcess
+
+type
+  Distribution* {.pure.} = enum ## the list of known distributions
+    Windows ## some version of Windows
+    Posix   ## some Posix system
+    MacOSX  ## some version of OSX
+    Linux   ## some version of Linux
+    Ubuntu
+    Debian
+    Gentoo
+    Fedora
+    RedHat
+
+    OpenSUSE
+    Manjaro
+    Elementary
+    Zorin
+    CentOS
+    Deepin
+    ArchLinux
+    Antergos
+    PCLinuxOS
+    Mageia
+    LXLE
+    Solus
+    Lite
+    Slackware
+    Androidx86
+    Puppy
+    Peppermint
+    Tails
+    AntiX
+    Kali
+    SparkyLinux
+    Apricity
+    BlackLab
+    Bodhi
+    TrueOS
+    ArchBang
+    KaOS
+    WattOS
+    Korora
+    Simplicity
+    RemixOS
+    OpenMandriva
+    Netrunner
+    Alpine
+    BlackArch
+    Ultimate
+    Gecko
+    Parrot
+    KNOPPIX
+    GhostBSD
+    Sabayon
+    Salix
+    Q4OS
+    ClearOS
+    Container
+    ROSA
+    Zenwalk
+    Parabola
+    ChaletOS
+    BackBox
+    MXLinux
+    Vector
+    Maui
+    Qubes
+    RancherOS
+    Oracle
+    TinyCore
+    Robolinux
+    Trisquel
+    Voyager
+    Clonezilla
+    SteamOS
+    Absolute
+    NixOS
+    AUSTRUMI
+    Arya
+    Porteus
+    AVLinux
+    Elive
+    Bluestar
+    SliTaz
+    Solaris
+    Chakra
+    Wifislax
+    Scientific
+    ExTiX
+    Rockstor
+    GoboLinux
+
+    BSD
+    FreeBSD
+    OpenBSD
+    DragonFlyBSD
+
+
+const
+  LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware,
+    Distribution.ArchLinux}
+
+var unameRes, releaseRes: string ## we cache the result of the 'uname -a'
+                                 ## execution for faster platform detections.
+
+template unameRelease(cmd, cache): untyped =
+  if cache.len == 0:
+    cache = (when defined(nimscript): gorge(cmd) else: execProcess(cmd))
+  cache
+
+template uname(): untyped = unameRelease("uname -a", unameRes)
+template release(): untyped = unameRelease("lsb_release -a", releaseRes)
+
+proc detectOsImpl(d: Distribution): bool =
+  case d
+  of Distribution.Windows: ## some version of Windows
+    result = defined(windows)
+  of Distribution.Posix: result = defined(posix)
+  of Distribution.MacOSX: result = defined(macosx)
+  of Distribution.Linux: result = defined(linux)
+  of Distribution.Ubuntu, Distribution.Gentoo, Distribution.FreeBSD,
+     Distribution.OpenBSD:
+    result = ("-" & $d & " ") in uname()
+  of Distribution.RedHat:
+    result = "Red Hat" in uname()
+  of Distribution.BSD: result = defined(bsd)
+  of Distribution.ArchLinux:
+    result = "arch" in toLowerAscii(uname())
+  of Distribution.OpenSUSE:
+    result = "suse" in toLowerAscii(uname())
+  of Distribution.GoboLinux:
+    result = "-Gobo " in uname()
+  of Distribution.OpenMandriva:
+    result = "mandriva" in toLowerAscii(uname())
+  of Distribution.Solaris:
+    let uname = toLowerAscii(uname())
+    result = ("sun" in uname) or ("solaris" in uname)
+  else:
+    let dd = toLowerAscii($d)
+    result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release())
+
+template detectOs*(d: untyped): bool =
+  ## Distro/OS detection. For convenience the
+  ## required ``Distribution.`` qualifier is added to the
+  ## enum value.
+  detectOsImpl(Distribution.d)
+
+when not defined(nimble):
+  var foreignDeps: seq[string] = @[]
+
+proc foreignCmd*(cmd: string; requiresSudo=false) =
+  ## Registers a foreign command to the intern list of commands
+  ## that can be queried later.
+  let c = (if requiresSudo: "sudo " else: "") & cmd
+  when defined(nimble):
+    nimscriptapi.foreignDeps.add(c)
+  else:
+    foreignDeps.add(c)
+
+proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) =
+  ## Returns the distro's native command line to install 'foreignPackageName'
+  ## and whether it requires root/admin rights.
+  let p = foreignPackageName
+  when defined(windows):
+    result = ("Chocolatey install " & p, false)
+  elif defined(bsd):
+    result = ("ports install " & p, true)
+  elif defined(linux):
+    if detectOs(Ubuntu) or detectOs(Elementary) or detectOs(Debian) or
+        detectOs(KNOPPIX) or detectOs(SteamOS):
+      result = ("apt-get install " & p, true)
+    elif detectOs(Gentoo):
+      result = ("emerge install " & p, true)
+    elif detectOs(Fedora):
+      result = ("yum install " & p, true)
+    elif detectOs(RedHat):
+      result = ("rpm install " & p, true)
+    elif detectOs(OpenSUSE):
+      result = ("yast -i " & p, true)
+    elif detectOs(Slackware):
+      result = ("installpkg " & p, true)
+    elif detectOs(OpenMandriva):
+      result = ("urpmi " & p, true)
+    elif detectOs(ZenWalk):
+      result = ("netpkg install " & p, true)
+    elif detectOs(NixOS):
+      result = ("nix-env -i " & p, false)
+    elif detectOs(Solaris):
+      result = ("pkg install " & p, true)
+    elif detectOs(PCLinuxOS):
+      result = ("rpm -ivh " & p, true)
+    elif detectOs(ArchLinux):
+      result = ("pacman -S " & p, true)
+    else:
+      result = ("<your package manager here> install " & p, true)
+  else:
+    result = ("brew install " & p, true)
+
+proc foreignDep*(foreignPackageName: string) =
+  ## Registers 'foreignPackageName' to the internal list of foreign deps.
+  ## It is your job to ensure the package name
+  let (installCmd, sudo) = foreignDepInstallCmd(foreignPackageName)
+  foreignCmd installCmd, sudo
+
+proc echoForeignDeps*() =
+  ## Writes the list of registered foreign deps to stdout.
+  for d in foreignDeps:
+    echo d
+
+when false:
+  foreignDep("libblas-dev")
+  foreignDep "libfoo"
+  echoForeignDeps()
diff --git a/lib/pure/endians.nim b/lib/pure/endians.nim
index 5a23169d4..6f80d56ef 100644
--- a/lib/pure/endians.nim
+++ b/lib/pure/endians.nim
@@ -10,38 +10,87 @@
 ## This module contains helpers that deal with different byte orders
 ## (`endian`:idx:).
 
-proc swapEndian64*(outp, inp: pointer) =
-  ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
-  ## contain at least 8 bytes.
-  var i = cast[cstring](inp)
-  var o = cast[cstring](outp)
-  o[0] = i[7]
-  o[1] = i[6]
-  o[2] = i[5]
-  o[3] = i[4]
-  o[4] = i[3]
-  o[5] = i[2]
-  o[6] = i[1]
-  o[7] = i[0]
-
-proc swapEndian32*(outp, inp: pointer) =
-  ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
-  ## contain at least 4 bytes.
-  var i = cast[cstring](inp)
-  var o = cast[cstring](outp)
-  o[0] = i[3]
-  o[1] = i[2]
-  o[2] = i[1]
-  o[3] = i[0]
-
-proc swapEndian16*(outp, inp: pointer) =
-  ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
-  ## contain at least 2 bytes.
-  var
-    i = cast[cstring](inp)
-    o = cast[cstring](outp)
-  o[0] = i[1]
-  o[1] = i[0]
+when defined(gcc) or defined(llvm_gcc) or defined(clang):
+  const useBuiltinSwap = true
+  proc builtin_bswap16(a: uint16): uint16 {.
+      importc: "__builtin_bswap16", nodecl, nosideeffect.}
+
+  proc builtin_bswap32(a: uint32): uint32 {.
+      importc: "__builtin_bswap32", nodecl, nosideeffect.}
+
+  proc builtin_bswap64(a: uint64): uint64 {.
+      importc: "__builtin_bswap64", nodecl, nosideeffect.}
+elif defined(icc):
+  const useBuiltinSwap = true
+  proc builtin_bswap16(a: uint16): uint16 {.
+      importc: "_bswap16", nodecl, nosideeffect.}
+
+  proc builtin_bswap32(a: uint32): uint32 {.
+      importc: "_bswap", nodecl, nosideeffect.}
+
+  proc builtin_bswap64(a: uint64): uint64 {.
+      importc: "_bswap64", nodecl, nosideeffect.}
+elif defined(vcc):
+  const useBuiltinSwap = true
+  proc builtin_bswap16(a: uint16): uint16 {.
+      importc: "_byteswap_ushort", nodecl, header: "<intrin.h>", nosideeffect.}
+
+  proc builtin_bswap32(a: uint32): uint32 {.
+      importc: "_byteswap_ulong", nodecl, header: "<intrin.h>", nosideeffect.}
+
+  proc builtin_bswap64(a: uint64): uint64 {.
+      importc: "_byteswap_uint64", nodecl, header: "<intrin.h>", nosideeffect.}
+else:
+  const useBuiltinSwap = false
+
+when useBuiltinSwap:
+  proc swapEndian64*(outp, inp: pointer) {.inline, nosideeffect.}=
+    var i = cast[ptr uint64](inp)
+    var o = cast[ptr uint64](outp)
+    o[] = builtin_bswap64(i[])
+
+  proc swapEndian32*(outp, inp: pointer) {.inline, nosideeffect.}=
+    var i = cast[ptr uint32](inp)
+    var o = cast[ptr uint32](outp)
+    o[] = builtin_bswap32(i[])
+
+  proc swapEndian16*(outp, inp: pointer) {.inline, nosideeffect.}=
+    var i = cast[ptr uint16](inp)
+    var o = cast[ptr uint16](outp)
+    o[] = builtin_bswap16(i[])
+
+else:
+  proc swapEndian64*(outp, inp: pointer) =
+    ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
+    ## contain at least 8 bytes.
+    var i = cast[cstring](inp)
+    var o = cast[cstring](outp)
+    o[0] = i[7]
+    o[1] = i[6]
+    o[2] = i[5]
+    o[3] = i[4]
+    o[4] = i[3]
+    o[5] = i[2]
+    o[6] = i[1]
+    o[7] = i[0]
+
+  proc swapEndian32*(outp, inp: pointer) =
+    ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
+    ## contain at least 4 bytes.
+    var i = cast[cstring](inp)
+    var o = cast[cstring](outp)
+    o[0] = i[3]
+    o[1] = i[2]
+    o[2] = i[1]
+    o[3] = i[0]
+
+  proc swapEndian16*(outp, inp: pointer) =
+    ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
+    ## contain at least 2 bytes.
+    var i = cast[cstring](inp)
+    var o = cast[cstring](outp)
+    o[0] = i[1]
+    o[1] = i[0]
 
 when system.cpuEndian == bigEndian:
   proc littleEndian64*(outp, inp: pointer) {.inline.} = swapEndian64(outp, inp)
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 4ef169b4f..a8432b6f0 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -213,7 +213,7 @@ when not defined(JS):
     ## .. code-block:: nim
     ##  echo ceil(-2.1) ## -2.0
 
-  when defined(windows) and defined(vcc):
+  when defined(windows) and (defined(vcc) or defined(bcc)):
     # MSVC 2010 don't have trunc/truncf
     # this implementation was inspired by Go-lang Math.Trunc
     proc truncImpl(f: float64): float64 =
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index f077e798a..8a5461567 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1427,7 +1427,7 @@ elif defined(windows):
     if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
     return TaintedString(ownArgv[i])
 
-elif not defined(createNimRtl):
+elif not defined(createNimRtl) and not(defined(posix) and appType == "lib"):
   # On Posix, there is no portable way to get the command line from a DLL.
   var
     cmdCount {.importc: "cmdCount".}: cint
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 99fdb5b0e..39d46c675 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -70,7 +70,7 @@ when defined(posix) and not defined(JS):
 elif defined(windows):
   import winlean
 
-  when defined(vcc):
+  when defined(vcc) or defined(bcc):
     # newest version of Visual C++ defines time_t to be of 64 bits
     type TimeImpl {.importc: "time_t", header: "<time.h>".} = int64
     # visual c's c runtime exposes these under a different name
diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim
index 559f45348..3c891c81b 100644
--- a/lib/pure/xmldom.nim
+++ b/lib/pure/xmldom.nim
@@ -890,7 +890,7 @@ proc tagName*(el: PElement): string =
   return el.fTagName
 
 # Procedures
-proc getAttribute*(el: PElement, name: string): string =
+proc getAttribute*(el: PNode, name: string): string =
   ## Retrieves an attribute value by ``name``
   if isNil(el.attributes):
     return nil
@@ -900,7 +900,7 @@ proc getAttribute*(el: PElement, name: string): string =
   else:
     return nil
 
-proc getAttributeNS*(el: PElement, namespaceURI: string, localName: string): string =
+proc getAttributeNS*(el: PNode, namespaceURI: string, localName: string): string =
   ## Retrieves an attribute value by ``localName`` and ``namespaceURI``
   if isNil(el.attributes):
     return nil
diff --git a/lib/system.nim b/lib/system.nim
index 8209dbc23..309df7f84 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -551,8 +551,6 @@ type
     ##
     ## See the full `exception hierarchy`_.
 
-  TResult* {.deprecated.} = enum Failure, Success
-
 {.deprecated: [TObject: RootObj, PObject: RootRef, TEffect: RootEffect,
   FTime: TimeEffect, FIO: IOEffect, FReadIO: ReadIOEffect,
   FWriteIO: WriteIOEffect, FExecIO: ExecIOEffect,
@@ -870,29 +868,43 @@ when defined(nimnomagic64):
 else:
   proc `mod` *(x, y: int64): int64 {.magic: "ModI64", noSideEffect.}
 
-proc `shr` *(x, y: int): int {.magic: "ShrI", noSideEffect.}
-proc `shr` *(x, y: int8): int8 {.magic: "ShrI", noSideEffect.}
-proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.}
-proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.}
-proc `shr` *(x, y: int64): int64 {.magic: "ShrI", noSideEffect.}
-  ## computes the `shift right` operation of `x` and `y`, filling
-  ## vacant bit positions with zeros.
-  ##
-  ## .. code-block:: Nim
-  ##   0b0001_0000'i8 shr 2 == 0b0000_0100'i8
-  ##   0b1000_0000'i8 shr 8 == 0b0000_0000'i8
-  ##   0b0000_0001'i8 shr 1 == 0b0000_0000'i8
-
-proc `shl` *(x, y: int): int {.magic: "ShlI", noSideEffect.}
-proc `shl` *(x, y: int8): int8 {.magic: "ShlI", noSideEffect.}
-proc `shl` *(x, y: int16): int16 {.magic: "ShlI", noSideEffect.}
-proc `shl` *(x, y: int32): int32 {.magic: "ShlI", noSideEffect.}
-proc `shl` *(x, y: int64): int64 {.magic: "ShlI", noSideEffect.}
-  ## computes the `shift left` operation of `x` and `y`.
-  ##
-  ## .. code-block:: Nim
-  ##  1'i32 shl 4 == 0x0000_0010
-  ##  1'i64 shl 4 == 0x0000_0000_0000_0010
+when defined(nimNewShiftOps):
+  proc `shr` *(x: int, y: SomeInteger): int {.magic: "ShrI", noSideEffect.}
+  proc `shr` *(x: int8, y: SomeInteger): int8 {.magic: "ShrI", noSideEffect.}
+  proc `shr` *(x: int16, y: SomeInteger): int16 {.magic: "ShrI", noSideEffect.}
+  proc `shr` *(x: int32, y: SomeInteger): int32 {.magic: "ShrI", noSideEffect.}
+  proc `shr` *(x: int64, y: SomeInteger): int64 {.magic: "ShrI", noSideEffect.}
+    ## computes the `shift right` operation of `x` and `y`, filling
+    ## vacant bit positions with zeros.
+    ##
+    ## .. code-block:: Nim
+    ##   0b0001_0000'i8 shr 2 == 0b0000_0100'i8
+    ##   0b1000_0000'i8 shr 8 == 0b0000_0000'i8
+    ##   0b0000_0001'i8 shr 1 == 0b0000_0000'i8
+
+
+  proc `shl` *(x: int, y: SomeInteger): int {.magic: "ShlI", noSideEffect.}
+  proc `shl` *(x: int8, y: SomeInteger): int8 {.magic: "ShlI", noSideEffect.}
+  proc `shl` *(x: int16, y: SomeInteger): int16 {.magic: "ShlI", noSideEffect.}
+  proc `shl` *(x: int32, y: SomeInteger): int32 {.magic: "ShlI", noSideEffect.}
+  proc `shl` *(x: int64, y: SomeInteger): int64 {.magic: "ShlI", noSideEffect.}
+    ## computes the `shift left` operation of `x` and `y`.
+    ##
+    ## .. code-block:: Nim
+    ##  1'i32 shl 4 == 0x0000_0010
+    ##  1'i64 shl 4 == 0x0000_0000_0000_0010
+else:
+  proc `shr` *(x, y: int): int {.magic: "ShrI", noSideEffect.}
+  proc `shr` *(x, y: int8): int8 {.magic: "ShrI", noSideEffect.}
+  proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.}
+  proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.}
+  proc `shr` *(x, y: int64): int64 {.magic: "ShrI", noSideEffect.}
+
+  proc `shl` *(x, y: int): int {.magic: "ShlI", noSideEffect.}
+  proc `shl` *(x, y: int8): int8 {.magic: "ShlI", noSideEffect.}
+  proc `shl` *(x, y: int16): int16 {.magic: "ShlI", noSideEffect.}
+  proc `shl` *(x, y: int32): int32 {.magic: "ShlI", noSideEffect.}
+  proc `shl` *(x, y: int64): int64 {.magic: "ShlI", noSideEffect.}
 
 proc `and` *(x, y: int): int {.magic: "BitandI", noSideEffect.}
 proc `and` *(x, y: int8): int8 {.magic: "BitandI", noSideEffect.}
@@ -993,11 +1005,18 @@ proc `<%` *(x, y: int64): bool {.magic: "LtU64", noSideEffect.}
 proc `not`*[T: SomeUnsignedInt](x: T): T {.magic: "BitnotI", noSideEffect.}
   ## computes the `bitwise complement` of the integer `x`.
 
-proc `shr`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShrI", noSideEffect.}
-  ## computes the `shift right` operation of `x` and `y`.
+when defined(nimNewShiftOps):
+  proc `shr`*[T: SomeUnsignedInt](x: T, y: SomeInteger): T {.magic: "ShrI", noSideEffect.}
+    ## computes the `shift right` operation of `x` and `y`.
+
+  proc `shl`*[T: SomeUnsignedInt](x: T, y: SomeInteger): T {.magic: "ShlI", noSideEffect.}
+    ## computes the `shift left` operation of `x` and `y`.
+else:
+  proc `shr`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShrI", noSideEffect.}
+    ## computes the `shift right` operation of `x` and `y`.
 
-proc `shl`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShlI", noSideEffect.}
-  ## computes the `shift left` operation of `x` and `y`.
+  proc `shl`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShlI", noSideEffect.}
+    ## computes the `shift left` operation of `x` and `y`.
 
 proc `and`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitandI", noSideEffect.}
   ## computes the `bitwise and` of numbers `x` and `y`.
@@ -2706,8 +2725,9 @@ when not defined(JS): #and not defined(nimscript):
     when defined(windows):
       # work-around C's sucking abstraction:
       # BUGFIX: stdin and stdout should be binary files!
-      proc c_setmode(handle, mode: cint) {.importc: "_setmode",
-                                           header: "<io.h>".}
+      proc c_setmode(handle, mode: cint) {.
+        importc: when defined(bcc): "setmode" else: "_setmode",
+        header: "<io.h>".}
       var
         O_BINARY {.importc: "O_BINARY", nodecl.}: cint
 
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 5b0955132..3b886b2fc 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -276,10 +276,11 @@ proc pageAddr(p: pointer): PChunk {.inline.} =
   #sysAssert(Contains(allocator.chunkStarts, pageIndex(result)))
 
 proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
-  if not a.blockChunkSizeIncrease:
-    a.nextChunkSize =
-      if a.currMem < 64 * 1024: PageSize*4
-      else: a.nextChunkSize*2
+  when not defined(emscripten):
+    if not a.blockChunkSizeIncrease:
+      a.nextChunkSize =
+        if a.currMem < 64 * 1024: PageSize*4
+        else: a.nextChunkSize*2
   var size = size
 
   if size > a.nextChunkSize:
diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim
index 29466c34d..f675a9472 100644
--- a/lib/system/nimscript.nim
+++ b/lib/system/nimscript.nim
@@ -293,26 +293,28 @@ template task*(name: untyped; description: string; body: untyped): untyped =
     setCommand "nop"
     `name Task`()
 
-var
-  packageName* = ""    ## Nimble support: Set this to the package name. It
-                       ## is usually not required to do that, nims' filename is
-                       ## the default.
-  version*: string     ## Nimble support: The package's version.
-  author*: string      ## Nimble support: The package's author.
-  description*: string ## Nimble support: The package's description.
-  license*: string     ## Nimble support: The package's license.
-  srcDir*: string      ## Nimble support: The package's source directory.
-  binDir*: string      ## Nimble support: The package's binary directory.
-  backend*: string     ## Nimble support: The package's backend.
-
-  skipDirs*, skipFiles*, skipExt*, installDirs*, installFiles*,
-    installExt*, bin*: seq[string] = @[] ## Nimble metadata.
-  requiresData*: seq[string] = @[] ## Exposes the list of requirements for read
-                                   ## and write accesses.
-
-proc requires*(deps: varargs[string]) =
-  ## Nimble support: Call this to set the list of requirements of your Nimble
-  ## package.
-  for d in deps: requiresData.add(d)
+when not defined(nimble):
+  # nimble has its own implementation for these things.
+  var
+    packageName* = ""    ## Nimble support: Set this to the package name. It
+                         ## is usually not required to do that, nims' filename is
+                         ## the default.
+    version*: string     ## Nimble support: The package's version.
+    author*: string      ## Nimble support: The package's author.
+    description*: string ## Nimble support: The package's description.
+    license*: string     ## Nimble support: The package's license.
+    srcDir*: string      ## Nimble support: The package's source directory.
+    binDir*: string      ## Nimble support: The package's binary directory.
+    backend*: string     ## Nimble support: The package's backend.
+
+    skipDirs*, skipFiles*, skipExt*, installDirs*, installFiles*,
+      installExt*, bin*: seq[string] = @[] ## Nimble metadata.
+    requiresData*: seq[string] = @[] ## Exposes the list of requirements for read
+                                     ## and write accesses.
+
+  proc requires*(deps: varargs[string]) =
+    ## Nimble support: Call this to set the list of requirements of your Nimble
+    ## package.
+    for d in deps: requiresData.add(d)
 
 {.pop.}
diff --git a/lib/upcoming/asyncdispatch.nim b/lib/upcoming/asyncdispatch.nim
index ca5c1f64c..78c7afffc 100644
--- a/lib/upcoming/asyncdispatch.nim
+++ b/lib/upcoming/asyncdispatch.nim
@@ -231,8 +231,14 @@ when defined(windows) or defined(nimdoc):
         "Operation performed on a socket which has not been registered with" &
         " the dispatcher yet.")
 
+  proc hasPendingOperations*(): bool =
+    ## Returns `true` if the global dispatcher has pending operations.
+    let p = getGlobalDispatcher()
+    p.handles.len != 0 or p.timers.len != 0 or p.callbacks.len != 0
+
   proc poll*(timeout = 500) =
-    ## Waits for completion events and processes them.
+    ## Waits for completion events and processes them. Raises ``ValueError``
+    ## if there are no pending operations.
     let p = getGlobalDispatcher()
     if p.handles.len == 0 and p.timers.len == 0 and p.callbacks.len == 0:
       raise newException(ValueError,
@@ -1182,6 +1188,10 @@ else:
       raise newException(ValueError, "File descriptor not registered.")
     p.selector.updateHandle(fd.SocketHandle, newEvents)
 
+  proc hasPendingOperations*(): bool =
+    let p = getGlobalDispatcher()
+    not p.selector.isEmpty() or p.timers.len != 0 or p.callbacks.len != 0
+
   proc poll*(timeout = 500) =
     var keys: array[64, ReadyKey[AsyncData]]
 
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 2441c7267..bb0e7a648 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -790,7 +790,7 @@ const
  IOC_WS2* = 0x08000000
  IOC_INOUT* = IOC_IN or IOC_OUT
 
-template WSAIORW*(x,y): expr = (IOC_INOUT or x or y)
+template WSAIORW*(x,y): untyped = (IOC_INOUT or x or y)
 
 const
   SIO_GET_EXTENSION_FUNCTION_POINTER* = WSAIORW(IOC_WS2,6).DWORD