[backport] run nimpretty on os-related stuff
This commit is contained in:
parent
dcf3181bd1
commit
34d0be2ec1
10 changed files with 191 additions and 182 deletions
|
|
@ -39,7 +39,8 @@ proc bitxor*[T: SomeInteger](x, y: T): T {.magic: "BitxorI", noSideEffect.}
|
||||||
|
|
||||||
const useBuiltins = not defined(noIntrinsicsBitOpts)
|
const useBuiltins = not defined(noIntrinsicsBitOpts)
|
||||||
const noUndefined = defined(noUndefinedBitOpts)
|
const noUndefined = defined(noUndefinedBitOpts)
|
||||||
const useGCC_builtins = (defined(gcc) or defined(llvm_gcc) or defined(clang)) and useBuiltins
|
const useGCC_builtins = (defined(gcc) or defined(llvm_gcc) or
|
||||||
|
defined(clang)) and useBuiltins
|
||||||
const useICC_builtins = defined(icc) and useBuiltins
|
const useICC_builtins = defined(icc) and useBuiltins
|
||||||
const useVCC_builtins = defined(vcc) and useBuiltins
|
const useVCC_builtins = defined(vcc) and useBuiltins
|
||||||
const arch64 = sizeof(int) == 8
|
const arch64 = sizeof(int) == 8
|
||||||
|
|
@ -196,7 +197,8 @@ template parityImpl[T](value: T): int =
|
||||||
when useGCC_builtins:
|
when useGCC_builtins:
|
||||||
# Returns the number of set 1-bits in value.
|
# Returns the number of set 1-bits in value.
|
||||||
proc builtin_popcount(x: cuint): cint {.importc: "__builtin_popcount", cdecl.}
|
proc builtin_popcount(x: cuint): cint {.importc: "__builtin_popcount", cdecl.}
|
||||||
proc builtin_popcountll(x: culonglong): cint {.importc: "__builtin_popcountll", cdecl.}
|
proc builtin_popcountll(x: culonglong): cint {.
|
||||||
|
importc: "__builtin_popcountll", cdecl.}
|
||||||
|
|
||||||
# Returns the bit parity in value
|
# Returns the bit parity in value
|
||||||
proc builtin_parity(x: cuint): cint {.importc: "__builtin_parity", cdecl.}
|
proc builtin_parity(x: cuint): cint {.importc: "__builtin_parity", cdecl.}
|
||||||
|
|
@ -216,17 +218,24 @@ when useGCC_builtins:
|
||||||
|
|
||||||
elif useVCC_builtins:
|
elif useVCC_builtins:
|
||||||
# Counts the number of one bits (population count) in a 16-, 32-, or 64-byte unsigned integer.
|
# Counts the number of one bits (population count) in a 16-, 32-, or 64-byte unsigned integer.
|
||||||
proc builtin_popcnt16(a2: uint16): uint16 {.importc: "__popcnt16" header: "<intrin.h>", noSideEffect.}
|
proc builtin_popcnt16(a2: uint16): uint16 {.
|
||||||
proc builtin_popcnt32(a2: uint32): uint32 {.importc: "__popcnt" header: "<intrin.h>", noSideEffect.}
|
importc: "__popcnt16"header: "<intrin.h>", noSideEffect.}
|
||||||
proc builtin_popcnt64(a2: uint64): uint64 {.importc: "__popcnt64" header: "<intrin.h>", noSideEffect.}
|
proc builtin_popcnt32(a2: uint32): uint32 {.
|
||||||
|
importc: "__popcnt"header: "<intrin.h>", noSideEffect.}
|
||||||
|
proc builtin_popcnt64(a2: uint64): uint64 {.
|
||||||
|
importc: "__popcnt64"header: "<intrin.h>", noSideEffect.}
|
||||||
|
|
||||||
# Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1).
|
# Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1).
|
||||||
proc bitScanReverse(index: ptr culong, mask: culong): cuchar {.importc: "_BitScanReverse", header: "<intrin.h>", noSideEffect.}
|
proc bitScanReverse(index: ptr culong, mask: culong): cuchar {.
|
||||||
proc bitScanReverse64(index: ptr culong, mask: uint64): cuchar {.importc: "_BitScanReverse64", header: "<intrin.h>", noSideEffect.}
|
importc: "_BitScanReverse", header: "<intrin.h>", noSideEffect.}
|
||||||
|
proc bitScanReverse64(index: ptr culong, mask: uint64): cuchar {.
|
||||||
|
importc: "_BitScanReverse64", header: "<intrin.h>", noSideEffect.}
|
||||||
|
|
||||||
# Search the mask data from least significant bit (LSB) to the most significant bit (MSB) for a set bit (1).
|
# Search the mask data from least significant bit (LSB) to the most significant bit (MSB) for a set bit (1).
|
||||||
proc bitScanForward(index: ptr culong, mask: culong): cuchar {.importc: "_BitScanForward", header: "<intrin.h>", noSideEffect.}
|
proc bitScanForward(index: ptr culong, mask: culong): cuchar {.
|
||||||
proc bitScanForward64(index: ptr culong, mask: uint64): cuchar {.importc: "_BitScanForward64", header: "<intrin.h>", noSideEffect.}
|
importc: "_BitScanForward", header: "<intrin.h>", noSideEffect.}
|
||||||
|
proc bitScanForward64(index: ptr culong, mask: uint64): cuchar {.
|
||||||
|
importc: "_BitScanForward64", header: "<intrin.h>", noSideEffect.}
|
||||||
|
|
||||||
template vcc_scan_impl(fnc: untyped; v: untyped): int =
|
template vcc_scan_impl(fnc: untyped; v: untyped): int =
|
||||||
var index: culong
|
var index: culong
|
||||||
|
|
@ -238,16 +247,22 @@ elif useICC_builtins:
|
||||||
# Intel compiler intrinsics: http://fulla.fnal.gov/intel/compiler_c/main_cls/intref_cls/common/intref_allia_misc.htm
|
# Intel compiler intrinsics: http://fulla.fnal.gov/intel/compiler_c/main_cls/intref_cls/common/intref_allia_misc.htm
|
||||||
# see also: https://software.intel.com/en-us/node/523362
|
# see also: https://software.intel.com/en-us/node/523362
|
||||||
# Count the number of bits set to 1 in an integer a, and return that count in dst.
|
# Count the number of bits set to 1 in an integer a, and return that count in dst.
|
||||||
proc builtin_popcnt32(a: cint): cint {.importc: "_popcnt" header: "<immintrin.h>", noSideEffect.}
|
proc builtin_popcnt32(a: cint): cint {.
|
||||||
proc builtin_popcnt64(a: uint64): cint {.importc: "_popcnt64" header: "<immintrin.h>", noSideEffect.}
|
importc: "_popcnt"header: "<immintrin.h>", noSideEffect.}
|
||||||
|
proc builtin_popcnt64(a: uint64): cint {.
|
||||||
|
importc: "_popcnt64"header: "<immintrin.h>", noSideEffect.}
|
||||||
|
|
||||||
# Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.
|
# Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.
|
||||||
proc bitScanForward(p: ptr uint32, b: uint32): cuchar {.importc: "_BitScanForward", header: "<immintrin.h>", noSideEffect.}
|
proc bitScanForward(p: ptr uint32, b: uint32): cuchar {.
|
||||||
proc bitScanForward64(p: ptr uint32, b: uint64): cuchar {.importc: "_BitScanForward64", header: "<immintrin.h>", noSideEffect.}
|
importc: "_BitScanForward", header: "<immintrin.h>", noSideEffect.}
|
||||||
|
proc bitScanForward64(p: ptr uint32, b: uint64): cuchar {.
|
||||||
|
importc: "_BitScanForward64", header: "<immintrin.h>", noSideEffect.}
|
||||||
|
|
||||||
# Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
|
# Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
|
||||||
proc bitScanReverse(p: ptr uint32, b: uint32): cuchar {.importc: "_BitScanReverse", header: "<immintrin.h>", noSideEffect.}
|
proc bitScanReverse(p: ptr uint32, b: uint32): cuchar {.
|
||||||
proc bitScanReverse64(p: ptr uint32, b: uint64): cuchar {.importc: "_BitScanReverse64", header: "<immintrin.h>", noSideEffect.}
|
importc: "_BitScanReverse", header: "<immintrin.h>", noSideEffect.}
|
||||||
|
proc bitScanReverse64(p: ptr uint32, b: uint64): cuchar {.
|
||||||
|
importc: "_BitScanReverse64", header: "<immintrin.h>", noSideEffect.}
|
||||||
|
|
||||||
template icc_scan_impl(fnc: untyped; v: untyped): int =
|
template icc_scan_impl(fnc: untyped; v: untyped): int =
|
||||||
var index: uint32
|
var index: uint32
|
||||||
|
|
@ -266,21 +281,21 @@ proc countSetBits*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
else:
|
else:
|
||||||
when useGCC_builtins:
|
when useGCC_builtins:
|
||||||
when sizeof(x) <= 4: result = builtin_popcount(x.cuint).int
|
when sizeof(x) <= 4: result = builtin_popcount(x.cuint).int
|
||||||
else: result = builtin_popcountll(x.culonglong).int
|
else: result = builtin_popcountll(x.culonglong).int
|
||||||
elif useVCC_builtins:
|
elif useVCC_builtins:
|
||||||
when sizeof(x) <= 2: result = builtin_popcnt16(x.uint16).int
|
when sizeof(x) <= 2: result = builtin_popcnt16(x.uint16).int
|
||||||
elif sizeof(x) <= 4: result = builtin_popcnt32(x.uint32).int
|
elif sizeof(x) <= 4: result = builtin_popcnt32(x.uint32).int
|
||||||
elif arch64: result = builtin_popcnt64(x.uint64).int
|
elif arch64: result = builtin_popcnt64(x.uint64).int
|
||||||
else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).uint32 ).int +
|
else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).uint32).int +
|
||||||
builtin_popcnt32((x.uint64 shr 32'u64).uint32 ).int
|
builtin_popcnt32((x.uint64 shr 32'u64).uint32).int
|
||||||
elif useICC_builtins:
|
elif useICC_builtins:
|
||||||
when sizeof(x) <= 4: result = builtin_popcnt32(x.cint).int
|
when sizeof(x) <= 4: result = builtin_popcnt32(x.cint).int
|
||||||
elif arch64: result = builtin_popcnt64(x.uint64).int
|
elif arch64: result = builtin_popcnt64(x.uint64).int
|
||||||
else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).cint ).int +
|
else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).cint).int +
|
||||||
builtin_popcnt32((x.uint64 shr 32'u64).cint ).int
|
builtin_popcnt32((x.uint64 shr 32'u64).cint).int
|
||||||
else:
|
else:
|
||||||
when sizeof(x) <= 4: result = countSetBitsNim(x.uint32)
|
when sizeof(x) <= 4: result = countSetBitsNim(x.uint32)
|
||||||
else: result = countSetBitsNim(x.uint64)
|
else: result = countSetBitsNim(x.uint64)
|
||||||
|
|
||||||
proc popcount*(x: SomeInteger): int {.inline, noSideEffect.} =
|
proc popcount*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
## Alias for for countSetBits (Hamming weight.)
|
## Alias for for countSetBits (Hamming weight.)
|
||||||
|
|
@ -298,10 +313,10 @@ proc parityBits*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
else:
|
else:
|
||||||
when useGCC_builtins:
|
when useGCC_builtins:
|
||||||
when sizeof(x) <= 4: result = builtin_parity(x.uint32).int
|
when sizeof(x) <= 4: result = builtin_parity(x.uint32).int
|
||||||
else: result = builtin_parityll(x.uint64).int
|
else: result = builtin_parityll(x.uint64).int
|
||||||
else:
|
else:
|
||||||
when sizeof(x) <= 4: result = parityImpl(x.uint32)
|
when sizeof(x) <= 4: result = parityImpl(x.uint32)
|
||||||
else: result = parityImpl(x.uint64)
|
else: result = parityImpl(x.uint64)
|
||||||
|
|
||||||
proc firstSetBit*(x: SomeInteger): int {.inline, noSideEffect.} =
|
proc firstSetBit*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
## Returns the 1-based index of the least significant set bit of x.
|
## Returns the 1-based index of the least significant set bit of x.
|
||||||
|
|
@ -321,7 +336,7 @@ proc firstSetBit*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
return 0
|
return 0
|
||||||
when useGCC_builtins:
|
when useGCC_builtins:
|
||||||
when sizeof(x) <= 4: result = builtin_ffs(cast[cint](x.cuint)).int
|
when sizeof(x) <= 4: result = builtin_ffs(cast[cint](x.cuint)).int
|
||||||
else: result = builtin_ffsll(cast[clonglong](x.culonglong)).int
|
else: result = builtin_ffsll(cast[clonglong](x.culonglong)).int
|
||||||
elif useVCC_builtins:
|
elif useVCC_builtins:
|
||||||
when sizeof(x) <= 4:
|
when sizeof(x) <= 4:
|
||||||
result = 1 + vcc_scan_impl(bitScanForward, x.culong)
|
result = 1 + vcc_scan_impl(bitScanForward, x.culong)
|
||||||
|
|
@ -338,7 +353,7 @@ proc firstSetBit*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
result = firstSetBitNim(x.uint64)
|
result = firstSetBitNim(x.uint64)
|
||||||
else:
|
else:
|
||||||
when sizeof(x) <= 4: result = firstSetBitNim(x.uint32)
|
when sizeof(x) <= 4: result = firstSetBitNim(x.uint32)
|
||||||
else: result = firstSetBitNim(x.uint64)
|
else: result = firstSetBitNim(x.uint64)
|
||||||
|
|
||||||
proc fastLog2*(x: SomeInteger): int {.inline, noSideEffect.} =
|
proc fastLog2*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
## Quickly find the log base 2 of an integer.
|
## Quickly find the log base 2 of an integer.
|
||||||
|
|
@ -354,7 +369,7 @@ proc fastLog2*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
else:
|
else:
|
||||||
when useGCC_builtins:
|
when useGCC_builtins:
|
||||||
when sizeof(x) <= 4: result = 31 - builtin_clz(x.uint32).int
|
when sizeof(x) <= 4: result = 31 - builtin_clz(x.uint32).int
|
||||||
else: result = 63 - builtin_clzll(x.uint64).int
|
else: result = 63 - builtin_clzll(x.uint64).int
|
||||||
elif useVCC_builtins:
|
elif useVCC_builtins:
|
||||||
when sizeof(x) <= 4:
|
when sizeof(x) <= 4:
|
||||||
result = vcc_scan_impl(bitScanReverse, x.culong)
|
result = vcc_scan_impl(bitScanReverse, x.culong)
|
||||||
|
|
@ -371,7 +386,7 @@ proc fastLog2*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
result = fastlog2Nim(x.uint64)
|
result = fastlog2Nim(x.uint64)
|
||||||
else:
|
else:
|
||||||
when sizeof(x) <= 4: result = fastlog2Nim(x.uint32)
|
when sizeof(x) <= 4: result = fastlog2Nim(x.uint32)
|
||||||
else: result = fastlog2Nim(x.uint64)
|
else: result = fastlog2Nim(x.uint64)
|
||||||
|
|
||||||
proc countLeadingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
|
proc countLeadingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
## Returns the number of leading zero bits in integer.
|
## Returns the number of leading zero bits in integer.
|
||||||
|
|
@ -387,10 +402,10 @@ proc countLeadingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
else:
|
else:
|
||||||
when useGCC_builtins:
|
when useGCC_builtins:
|
||||||
when sizeof(x) <= 4: result = builtin_clz(x.uint32).int - (32 - sizeof(x)*8)
|
when sizeof(x) <= 4: result = builtin_clz(x.uint32).int - (32 - sizeof(x)*8)
|
||||||
else: result = builtin_clzll(x.uint64).int
|
else: result = builtin_clzll(x.uint64).int
|
||||||
else:
|
else:
|
||||||
when sizeof(x) <= 4: result = sizeof(x)*8 - 1 - fastlog2Nim(x.uint32)
|
when sizeof(x) <= 4: result = sizeof(x)*8 - 1 - fastlog2Nim(x.uint32)
|
||||||
else: result = sizeof(x)*8 - 1 - fastlog2Nim(x.uint64)
|
else: result = sizeof(x)*8 - 1 - fastlog2Nim(x.uint64)
|
||||||
|
|
||||||
proc countTrailingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
|
proc countTrailingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
## Returns the number of trailing zeros in integer.
|
## Returns the number of trailing zeros in integer.
|
||||||
|
|
@ -406,7 +421,7 @@ proc countTrailingZeroBits*(x: SomeInteger): int {.inline, noSideEffect.} =
|
||||||
else:
|
else:
|
||||||
when useGCC_builtins:
|
when useGCC_builtins:
|
||||||
when sizeof(x) <= 4: result = builtin_ctz(x.uint32).int
|
when sizeof(x) <= 4: result = builtin_ctz(x.uint32).int
|
||||||
else: result = builtin_ctzll(x.uint64).int
|
else: result = builtin_ctzll(x.uint64).int
|
||||||
else:
|
else:
|
||||||
result = firstSetBit(x) - 1
|
result = firstSetBit(x) - 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,10 @@ when not defined(nimscript):
|
||||||
|
|
||||||
type
|
type
|
||||||
Distribution* {.pure.} = enum ## the list of known distributions
|
Distribution* {.pure.} = enum ## the list of known distributions
|
||||||
Windows ## some version of Windows
|
Windows ## some version of Windows
|
||||||
Posix ## some Posix system
|
Posix ## some Posix system
|
||||||
MacOSX ## some version of OSX
|
MacOSX ## some version of OSX
|
||||||
Linux ## some version of Linux
|
Linux ## some version of Linux
|
||||||
Ubuntu
|
Ubuntu
|
||||||
Debian
|
Debian
|
||||||
Gentoo
|
Gentoo
|
||||||
|
|
@ -133,8 +133,9 @@ const
|
||||||
LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware,
|
LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware,
|
||||||
Distribution.ArchLinux}
|
Distribution.ArchLinux}
|
||||||
|
|
||||||
var unameRes, releaseRes, hostnamectlRes: string ## we cache the result of the 'uname -a'
|
# we cache the result of the 'uname -a'
|
||||||
## execution for faster platform detections.
|
# execution for faster platform detections.
|
||||||
|
var unameRes, releaseRes, hostnamectlRes: string
|
||||||
|
|
||||||
template unameRelease(cmd, cache): untyped =
|
template unameRelease(cmd, cache): untyped =
|
||||||
if cache.len == 0:
|
if cache.len == 0:
|
||||||
|
|
@ -173,7 +174,8 @@ proc detectOsImpl(d: Distribution): bool =
|
||||||
result = defined(haiku)
|
result = defined(haiku)
|
||||||
else:
|
else:
|
||||||
let dd = toLowerAscii($d)
|
let dd = toLowerAscii($d)
|
||||||
result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release()) or ("operating system: " & dd) in toLowerAscii(hostnamectl())
|
result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release()) or
|
||||||
|
("operating system: " & dd) in toLowerAscii(hostnamectl())
|
||||||
|
|
||||||
template detectOs*(d: untyped): bool =
|
template detectOs*(d: untyped): bool =
|
||||||
## Distro/OS detection. For convenience the
|
## Distro/OS detection. For convenience the
|
||||||
|
|
@ -184,7 +186,7 @@ template detectOs*(d: untyped): bool =
|
||||||
when not defined(nimble):
|
when not defined(nimble):
|
||||||
var foreignDeps: seq[string] = @[]
|
var foreignDeps: seq[string] = @[]
|
||||||
|
|
||||||
proc foreignCmd*(cmd: string; requiresSudo=false) =
|
proc foreignCmd*(cmd: string; requiresSudo = false) =
|
||||||
## Registers a foreign command to the intern list of commands
|
## Registers a foreign command to the intern list of commands
|
||||||
## that can be queried later.
|
## that can be queried later.
|
||||||
let c = (if requiresSudo: "sudo " else: "") & cmd
|
let c = (if requiresSudo: "sudo " else: "") & cmd
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ import strutils
|
||||||
type
|
type
|
||||||
LibHandle* = pointer ## a handle to a dynamically loaded library
|
LibHandle* = pointer ## a handle to a dynamically loaded library
|
||||||
|
|
||||||
proc loadLib*(path: string, globalSymbols=false): LibHandle {.gcsafe.}
|
proc loadLib*(path: string, globalSymbols = false): LibHandle {.gcsafe.}
|
||||||
## loads a library from `path`. Returns nil if the library could not
|
## loads a library from `path`. Returns nil if the library could not
|
||||||
## be loaded.
|
## be loaded.
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ proc libCandidates*(s: string, dest: var seq[string]) =
|
||||||
else:
|
else:
|
||||||
add(dest, s)
|
add(dest, s)
|
||||||
|
|
||||||
proc loadLibPattern*(pattern: string, globalSymbols=false): LibHandle =
|
proc loadLibPattern*(pattern: string, globalSymbols = false): LibHandle =
|
||||||
## loads a library with name matching `pattern`, similar to what `dlimport`
|
## loads a library with name matching `pattern`, similar to what `dlimport`
|
||||||
## pragma does. Returns nil if the library could not be loaded.
|
## pragma does. Returns nil if the library could not be loaded.
|
||||||
## Warning: this proc uses the GC and so cannot be used to load the GC.
|
## Warning: this proc uses the GC and so cannot be used to load the GC.
|
||||||
|
|
@ -117,7 +117,7 @@ when defined(posix) and not defined(nintendoswitch):
|
||||||
#
|
#
|
||||||
import posix
|
import posix
|
||||||
|
|
||||||
proc loadLib(path: string, globalSymbols=false): LibHandle =
|
proc loadLib(path: string, globalSymbols = false): LibHandle =
|
||||||
let flags =
|
let flags =
|
||||||
if globalSymbols: RTLD_NOW or RTLD_GLOBAL
|
if globalSymbols: RTLD_NOW or RTLD_GLOBAL
|
||||||
else: RTLD_NOW
|
else: RTLD_NOW
|
||||||
|
|
@ -141,7 +141,7 @@ elif defined(nintendoswitch):
|
||||||
raise newException(OSError, "dlopen not implemented on Nintendo Switch!")
|
raise newException(OSError, "dlopen not implemented on Nintendo Switch!")
|
||||||
proc dlsym(lib: LibHandle, name: cstring): pointer =
|
proc dlsym(lib: LibHandle, name: cstring): pointer =
|
||||||
raise newException(OSError, "dlsym not implemented on Nintendo Switch!")
|
raise newException(OSError, "dlsym not implemented on Nintendo Switch!")
|
||||||
proc loadLib(path: string, global_symbols=false): LibHandle =
|
proc loadLib(path: string, global_symbols = false): LibHandle =
|
||||||
raise newException(OSError, "loadLib not implemented on Nintendo Switch!")
|
raise newException(OSError, "loadLib not implemented on Nintendo Switch!")
|
||||||
proc loadLib(): LibHandle =
|
proc loadLib(): LibHandle =
|
||||||
raise newException(OSError, "loadLib not implemented on Nintendo Switch!")
|
raise newException(OSError, "loadLib not implemented on Nintendo Switch!")
|
||||||
|
|
@ -158,7 +158,7 @@ elif defined(windows) or defined(dos):
|
||||||
#
|
#
|
||||||
type
|
type
|
||||||
HMODULE {.importc: "HMODULE".} = pointer
|
HMODULE {.importc: "HMODULE".} = pointer
|
||||||
FARPROC {.importc: "FARPROC".} = pointer
|
FARPROC {.importc: "FARPROC".} = pointer
|
||||||
|
|
||||||
proc FreeLibrary(lib: HMODULE) {.importc, header: "<windows.h>", stdcall.}
|
proc FreeLibrary(lib: HMODULE) {.importc, header: "<windows.h>", stdcall.}
|
||||||
proc winLoadLibrary(path: cstring): HMODULE {.
|
proc winLoadLibrary(path: cstring): HMODULE {.
|
||||||
|
|
@ -166,7 +166,7 @@ elif defined(windows) or defined(dos):
|
||||||
proc getProcAddress(lib: HMODULE, name: cstring): FARPROC {.
|
proc getProcAddress(lib: HMODULE, name: cstring): FARPROC {.
|
||||||
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
|
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
|
||||||
|
|
||||||
proc loadLib(path: string, globalSymbols=false): LibHandle =
|
proc loadLib(path: string, globalSymbols = false): LibHandle =
|
||||||
result = cast[LibHandle](winLoadLibrary(path))
|
result = cast[LibHandle](winLoadLibrary(path))
|
||||||
proc loadLib(): LibHandle =
|
proc loadLib(): LibHandle =
|
||||||
result = cast[LibHandle](winLoadLibrary(nil))
|
result = cast[LibHandle](winLoadLibrary(nil))
|
||||||
|
|
|
||||||
|
|
@ -55,13 +55,13 @@ when useBuiltinSwap:
|
||||||
tmp = op(tmp)
|
tmp = op(tmp)
|
||||||
copyMem(outp, addr tmp, sizeof(T))
|
copyMem(outp, addr tmp, sizeof(T))
|
||||||
|
|
||||||
proc swapEndian64*(outp, inp: pointer) {.inline, noSideEffect.}=
|
proc swapEndian64*(outp, inp: pointer) {.inline, noSideEffect.} =
|
||||||
swapOpImpl(uint64, builtin_bswap64)
|
swapOpImpl(uint64, builtin_bswap64)
|
||||||
|
|
||||||
proc swapEndian32*(outp, inp: pointer) {.inline, noSideEffect.}=
|
proc swapEndian32*(outp, inp: pointer) {.inline, noSideEffect.} =
|
||||||
swapOpImpl(uint32, builtin_bswap32)
|
swapOpImpl(uint32, builtin_bswap32)
|
||||||
|
|
||||||
proc swapEndian16*(outp, inp: pointer) {.inline, noSideEffect.}=
|
proc swapEndian16*(outp, inp: pointer) {.inline, noSideEffect.} =
|
||||||
swapOpImpl(uint16, builtin_bswap16)
|
swapOpImpl(uint16, builtin_bswap16)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -29,20 +29,20 @@ proc newEIO(msg: string): ref IOError =
|
||||||
result.msg = msg
|
result.msg = msg
|
||||||
|
|
||||||
type
|
type
|
||||||
MemFile* = object ## represents a memory mapped file
|
MemFile* = object ## represents a memory mapped file
|
||||||
mem*: pointer ## a pointer to the memory mapped file. The pointer
|
mem*: pointer ## a pointer to the memory mapped file. The pointer
|
||||||
## can be used directly to change the contents of the
|
## can be used directly to change the contents of the
|
||||||
## file, if it was opened with write access.
|
## file, if it was opened with write access.
|
||||||
size*: int ## size of the memory mapped file
|
size*: int ## size of the memory mapped file
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
fHandle*: Handle ## **Caution**: Windows specific public field to allow
|
fHandle*: Handle ## **Caution**: Windows specific public field to allow
|
||||||
## even more low level trickery.
|
## even more low level trickery.
|
||||||
mapHandle*: Handle ## **Caution**: Windows specific public field.
|
mapHandle*: Handle ## **Caution**: Windows specific public field.
|
||||||
wasOpened*: bool ## **Caution**: Windows specific public field.
|
wasOpened*: bool ## **Caution**: Windows specific public field.
|
||||||
else:
|
else:
|
||||||
handle*: cint ## **Caution**: Posix specific public field.
|
handle*: cint ## **Caution**: Posix specific public field.
|
||||||
flags: cint ## **Caution**: Platform specific private field.
|
flags: cint ## **Caution**: Platform specific private field.
|
||||||
|
|
||||||
proc mapMem*(m: var MemFile, mode: FileMode = fmRead,
|
proc mapMem*(m: var MemFile, mode: FileMode = fmRead,
|
||||||
mappedSize = -1, offset = 0, mapFlags = cint(-1)): pointer =
|
mappedSize = -1, offset = 0, mapFlags = cint(-1)): pointer =
|
||||||
|
|
@ -163,7 +163,8 @@ proc open*(filename: string, mode: FileMode = fmRead,
|
||||||
if readonly: shareMode else: shareMode or FILE_SHARE_WRITE,
|
if readonly: shareMode else: shareMode or FILE_SHARE_WRITE,
|
||||||
nil,
|
nil,
|
||||||
if newFileSize != -1: CREATE_ALWAYS else: OPEN_EXISTING,
|
if newFileSize != -1: CREATE_ALWAYS else: OPEN_EXISTING,
|
||||||
if readonly: FILE_ATTRIBUTE_READONLY or flags else: FILE_ATTRIBUTE_NORMAL or flags,
|
if readonly: FILE_ATTRIBUTE_READONLY or flags
|
||||||
|
else: FILE_ATTRIBUTE_NORMAL or flags,
|
||||||
0)
|
0)
|
||||||
|
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
|
|
@ -177,13 +178,13 @@ proc open*(filename: string, mode: FileMode = fmRead,
|
||||||
if newFileSize != -1:
|
if newFileSize != -1:
|
||||||
var
|
var
|
||||||
sizeHigh = int32(newFileSize shr 32)
|
sizeHigh = int32(newFileSize shr 32)
|
||||||
sizeLow = int32(newFileSize and 0xffffffff)
|
sizeLow = int32(newFileSize and 0xffffffff)
|
||||||
|
|
||||||
var status = setFilePointer(result.fHandle, sizeLow, addr(sizeHigh),
|
var status = setFilePointer(result.fHandle, sizeLow, addr(sizeHigh),
|
||||||
FILE_BEGIN)
|
FILE_BEGIN)
|
||||||
let lastErr = osLastError()
|
let lastErr = osLastError()
|
||||||
if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
|
if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
|
||||||
(setEndOfFile(result.fHandle) == 0):
|
(setEndOfFile(result.fHandle) == 0):
|
||||||
fail(lastErr, "error setting file size")
|
fail(lastErr, "error setting file size")
|
||||||
|
|
||||||
# since the strings are always 'nil', we simply always call
|
# since the strings are always 'nil', we simply always call
|
||||||
|
|
@ -310,10 +311,10 @@ when defined(posix) or defined(nimdoc):
|
||||||
"Cannot resize MemFile opened with allowRemap=false")
|
"Cannot resize MemFile opened with allowRemap=false")
|
||||||
if ftruncate(f.handle, newFileSize) == -1:
|
if ftruncate(f.handle, newFileSize) == -1:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
when defined(linux): #Maybe NetBSD, too?
|
when defined(linux): #Maybe NetBSD, too?
|
||||||
#On Linux this can be over 100 times faster than a munmap,mmap cycle.
|
#On Linux this can be over 100 times faster than a munmap,mmap cycle.
|
||||||
proc mremap(old: pointer; oldSize,newSize: csize; flags: cint): pointer {.
|
proc mremap(old: pointer; oldSize, newSize: csize; flags: cint):
|
||||||
importc: "mremap", header: "<sys/mman.h>" .}
|
pointer {.importc: "mremap", header: "<sys/mman.h>".}
|
||||||
let newAddr = mremap(f.mem, csize(f.size), csize(newFileSize), cint(1))
|
let newAddr = mremap(f.mem, csize(f.size), csize(newFileSize), cint(1))
|
||||||
if newAddr == cast[pointer](MAP_FAILED):
|
if newAddr == cast[pointer](MAP_FAILED):
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
@ -362,7 +363,7 @@ proc close*(f: var MemFile) =
|
||||||
|
|
||||||
if error: raiseOSError(lastErr)
|
if error: raiseOSError(lastErr)
|
||||||
|
|
||||||
type MemSlice* = object ## represent slice of a MemFile for iteration over delimited lines/records
|
type MemSlice* = object ## represent slice of a MemFile for iteration over delimited lines/records
|
||||||
data*: pointer
|
data*: pointer
|
||||||
size*: int
|
size*: int
|
||||||
|
|
||||||
|
|
@ -375,7 +376,7 @@ proc `$`*(ms: MemSlice): string {.inline.} =
|
||||||
result.setLen(ms.size)
|
result.setLen(ms.size)
|
||||||
copyMem(addr(result[0]), ms.data, ms.size)
|
copyMem(addr(result[0]), ms.data, ms.size)
|
||||||
|
|
||||||
iterator memSlices*(mfile: MemFile, delim='\l', eat='\r'): MemSlice {.inline.} =
|
iterator memSlices*(mfile: MemFile, delim = '\l', eat = '\r'): MemSlice {.inline.} =
|
||||||
## Iterates over [optional `eat`] `delim`-delimited slices in MemFile `mfile`.
|
## Iterates over [optional `eat`] `delim`-delimited slices in MemFile `mfile`.
|
||||||
##
|
##
|
||||||
## Default parameters parse lines ending in either Unix(\\l) or Windows(\\r\\l)
|
## Default parameters parse lines ending in either Unix(\\l) or Windows(\\r\\l)
|
||||||
|
|
@ -408,7 +409,7 @@ iterator memSlices*(mfile: MemFile, delim='\l', eat='\r'): MemSlice {.inline.} =
|
||||||
## echo count
|
## echo count
|
||||||
|
|
||||||
proc c_memchr(cstr: pointer, c: char, n: csize): pointer {.
|
proc c_memchr(cstr: pointer, c: char, n: csize): pointer {.
|
||||||
importc: "memchr", header: "<string.h>" .}
|
importc: "memchr", header: "<string.h>".}
|
||||||
proc `-!`(p, q: pointer): int {.inline.} = return cast[int](p) -% cast[int](q)
|
proc `-!`(p, q: pointer): int {.inline.} = return cast[int](p) -% cast[int](q)
|
||||||
var ms: MemSlice
|
var ms: MemSlice
|
||||||
var ending: pointer
|
var ending: pointer
|
||||||
|
|
@ -416,18 +417,19 @@ iterator memSlices*(mfile: MemFile, delim='\l', eat='\r'): MemSlice {.inline.} =
|
||||||
var remaining = mfile.size
|
var remaining = mfile.size
|
||||||
while remaining > 0:
|
while remaining > 0:
|
||||||
ending = c_memchr(ms.data, delim, remaining)
|
ending = c_memchr(ms.data, delim, remaining)
|
||||||
if ending == nil: # unterminated final slice
|
if ending == nil: # unterminated final slice
|
||||||
ms.size = remaining # Weird case..check eat?
|
ms.size = remaining # Weird case..check eat?
|
||||||
yield ms
|
yield ms
|
||||||
break
|
break
|
||||||
ms.size = ending -! ms.data # delim is NOT included
|
ms.size = ending -! ms.data # delim is NOT included
|
||||||
if eat != '\0' and ms.size > 0 and cast[cstring](ms.data)[ms.size - 1] == eat:
|
if eat != '\0' and ms.size > 0 and cast[cstring](ms.data)[ms.size - 1] == eat:
|
||||||
dec(ms.size) # trim pre-delim char
|
dec(ms.size) # trim pre-delim char
|
||||||
yield ms
|
yield ms
|
||||||
ms.data = cast[pointer](cast[int](ending) +% 1) # skip delim
|
ms.data = cast[pointer](cast[int](ending) +% 1) # skip delim
|
||||||
remaining = mfile.size - (ms.data -! mfile.mem)
|
remaining = mfile.size - (ms.data -! mfile.mem)
|
||||||
|
|
||||||
iterator lines*(mfile: MemFile, buf: var TaintedString, delim='\l', eat='\r'): TaintedString {.inline.} =
|
iterator lines*(mfile: MemFile, buf: var TaintedString, delim = '\l',
|
||||||
|
eat = '\r'): TaintedString {.inline.} =
|
||||||
## Replace contents of passed buffer with each new line, like
|
## Replace contents of passed buffer with each new line, like
|
||||||
## `readLine(File) <system.html#readLine,File,TaintedString>`_.
|
## `readLine(File) <system.html#readLine,File,TaintedString>`_.
|
||||||
## `delim`, `eat`, and delimiting logic is exactly as for
|
## `delim`, `eat`, and delimiting logic is exactly as for
|
||||||
|
|
@ -446,7 +448,7 @@ iterator lines*(mfile: MemFile, buf: var TaintedString, delim='\l', eat='\r'): T
|
||||||
copyMem(addr buf[0], ms.data, ms.size)
|
copyMem(addr buf[0], ms.data, ms.size)
|
||||||
yield buf
|
yield buf
|
||||||
|
|
||||||
iterator lines*(mfile: MemFile, delim='\l', eat='\r'): TaintedString {.inline.} =
|
iterator lines*(mfile: MemFile, delim = '\l', eat = '\r'): TaintedString {.inline.} =
|
||||||
## Return each line in a file as a Nim string, like
|
## Return each line in a file as a Nim string, like
|
||||||
## `lines(File) <system.html#lines.i,File>`_.
|
## `lines(File) <system.html#lines.i,File>`_.
|
||||||
## `delim`, `eat`, and delimiting logic is exactly as for
|
## `delim`, `eat`, and delimiting logic is exactly as for
|
||||||
|
|
@ -476,7 +478,7 @@ proc mmsClose(s: Stream) =
|
||||||
proc mmsFlush(s: Stream) = flush(MemMapFileStream(s).mf)
|
proc mmsFlush(s: Stream) = flush(MemMapFileStream(s).mf)
|
||||||
|
|
||||||
proc mmsAtEnd(s: Stream): bool = (MemMapFileStream(s).pos >= MemMapFileStream(s).mf.size) or
|
proc mmsAtEnd(s: Stream): bool = (MemMapFileStream(s).pos >= MemMapFileStream(s).mf.size) or
|
||||||
(MemMapFileStream(s).pos < 0)
|
(MemMapFileStream(s).pos < 0)
|
||||||
|
|
||||||
proc mmsSetPosition(s: Stream, pos: int) =
|
proc mmsSetPosition(s: Stream, pos: int) =
|
||||||
if pos > MemMapFileStream(s).mf.size or pos < 0:
|
if pos > MemMapFileStream(s).mf.size or pos < 0:
|
||||||
|
|
@ -507,8 +509,8 @@ proc mmsWriteData(s: Stream, buffer: pointer, bufLen: int) =
|
||||||
moveMem(cast[pointer](p), buffer, bufLen)
|
moveMem(cast[pointer](p), buffer, bufLen)
|
||||||
inc(MemMapFileStream(s).pos, bufLen)
|
inc(MemMapFileStream(s).pos, bufLen)
|
||||||
|
|
||||||
proc newMemMapFileStream*(filename: string, mode: FileMode = fmRead, fileSize: int = -1):
|
proc newMemMapFileStream*(filename: string, mode: FileMode = fmRead,
|
||||||
MemMapFileStream =
|
fileSize: int = -1): MemMapFileStream =
|
||||||
## creates a new stream from the file named `filename` with the mode `mode`.
|
## creates a new stream from the file named `filename` with the mode `mode`.
|
||||||
## Raises ## `OSError` if the file cannot be opened. See the `system
|
## Raises ## `OSError` if the file cannot be opened. See the `system
|
||||||
## <system.html>`_ module for a list of available FileMode enums.
|
## <system.html>`_ module for a list of available FileMode enums.
|
||||||
|
|
|
||||||
|
|
@ -1929,6 +1929,6 @@ runnableExamples:
|
||||||
assert m.getMimetype("") == "text/plain"
|
assert m.getMimetype("") == "text/plain"
|
||||||
assert m.getExt("") == "txt"
|
assert m.getExt("") == "txt"
|
||||||
## Register new Mimetypes.
|
## Register new Mimetypes.
|
||||||
m.register(ext="fakext", mimetype="text/fakelang")
|
m.register(ext = "fakext", mimetype = "text/fakelang")
|
||||||
assert m.getMimetype("fakext") == "text/fakelang"
|
assert m.getMimetype("fakext") == "text/fakelang"
|
||||||
assert m.getMimetype("FaKeXT") == "text/fakelang"
|
assert m.getMimetype("FaKeXT") == "text/fakelang"
|
||||||
|
|
|
||||||
|
|
@ -32,22 +32,22 @@ when defined(linux):
|
||||||
|
|
||||||
type
|
type
|
||||||
ProcessOption* = enum ## Options that can be passed to `startProcess proc
|
ProcessOption* = enum ## Options that can be passed to `startProcess proc
|
||||||
## <#startProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_.
|
## <#startProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_.
|
||||||
poEchoCmd, ## Echo the command before execution.
|
poEchoCmd, ## Echo the command before execution.
|
||||||
poUsePath, ## Asks system to search for executable using PATH environment
|
poUsePath, ## Asks system to search for executable using PATH environment
|
||||||
## variable.
|
## variable.
|
||||||
## On Windows, this is the default.
|
## On Windows, this is the default.
|
||||||
poEvalCommand, ## Pass `command` directly to the shell, without quoting.
|
poEvalCommand, ## Pass `command` directly to the shell, without quoting.
|
||||||
## Use it only if `command` comes from trusted source.
|
## Use it only if `command` comes from trusted source.
|
||||||
poStdErrToStdOut, ## Merge stdout and stderr to the stdout stream.
|
poStdErrToStdOut, ## Merge stdout and stderr to the stdout stream.
|
||||||
poParentStreams, ## Use the parent's streams.
|
poParentStreams, ## Use the parent's streams.
|
||||||
poInteractive, ## Optimize the buffer handling for responsiveness for
|
poInteractive, ## Optimize the buffer handling for responsiveness for
|
||||||
## UI applications. Currently this only affects
|
## UI applications. Currently this only affects
|
||||||
## Windows: Named pipes are used so that you can peek
|
## Windows: Named pipes are used so that you can peek
|
||||||
## at the process' output streams.
|
## at the process' output streams.
|
||||||
poDaemon ## Windows: The program creates no Window.
|
poDaemon ## Windows: The program creates no Window.
|
||||||
## Unix: Start the program as a daemon. This is still
|
## Unix: Start the program as a daemon. This is still
|
||||||
## work in progress!
|
## work in progress!
|
||||||
|
|
||||||
ProcessObj = object of RootObj
|
ProcessObj = object of RootObj
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
|
|
@ -66,21 +66,16 @@ type
|
||||||
Process* = ref ProcessObj ## Represents an operating system process.
|
Process* = ref ProcessObj ## Represents an operating system process.
|
||||||
|
|
||||||
const poDemon* {.deprecated.} = poDaemon ## Nim versions before 0.20
|
const poDemon* {.deprecated.} = poDaemon ## Nim versions before 0.20
|
||||||
## used the wrong spelling ("demon").
|
## used the wrong spelling ("demon").
|
||||||
## Now `ProcessOption` uses the correct spelling ("daemon"),
|
## Now `ProcessOption` uses the correct spelling ("daemon"),
|
||||||
## and this is needed just for backward compatibility.
|
## and this is needed just for backward compatibility.
|
||||||
|
|
||||||
|
|
||||||
proc execProcess*(command: string,
|
proc execProcess*(command: string, workingDir: string = "",
|
||||||
workingDir: string = "",
|
args: openArray[string] = [], env: StringTableRef = nil,
|
||||||
args: openArray[string] = [],
|
options: set[ProcessOption] = {poStdErrToStdOut, poUsePath, poEvalCommand}):
|
||||||
env: StringTableRef = nil,
|
TaintedString {.rtl, extern: "nosp$1",
|
||||||
options: set[ProcessOption] = {poStdErrToStdOut,
|
tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
|
||||||
poUsePath,
|
|
||||||
poEvalCommand}): TaintedString {.
|
|
||||||
rtl, extern: "nosp$1",
|
|
||||||
tags: [ExecIOEffect, ReadIOEffect,
|
|
||||||
RootEffect].}
|
|
||||||
## A convenience procedure that executes ``command`` with ``startProcess``
|
## A convenience procedure that executes ``command`` with ``startProcess``
|
||||||
## and returns its output as a string.
|
## and returns its output as a string.
|
||||||
##
|
##
|
||||||
|
|
@ -102,8 +97,8 @@ proc execProcess*(command: string,
|
||||||
## # Note: outp may have an interleave of text from the nim compile
|
## # Note: outp may have an interleave of text from the nim compile
|
||||||
## # and any output from mytestfile when it runs
|
## # and any output from mytestfile when it runs
|
||||||
|
|
||||||
proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [ExecIOEffect,
|
proc execCmd*(command: string): int {.rtl, extern: "nosp$1",
|
||||||
ReadIOEffect, RootEffect].}
|
tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
|
||||||
## Executes ``command`` and returns its error code.
|
## Executes ``command`` and returns its error code.
|
||||||
##
|
##
|
||||||
## Standard input, output, error streams are inherited from the calling process.
|
## Standard input, output, error streams are inherited from the calling process.
|
||||||
|
|
@ -121,13 +116,11 @@ proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [ExecIOEffect
|
||||||
## .. code-block:: Nim
|
## .. code-block:: Nim
|
||||||
## let errC = execCmd("nim c -r mytestfile.nim")
|
## let errC = execCmd("nim c -r mytestfile.nim")
|
||||||
|
|
||||||
proc startProcess*(command: string,
|
proc startProcess*(command: string, workingDir: string = "",
|
||||||
workingDir: string = "",
|
args: openArray[string] = [], env: StringTableRef = nil,
|
||||||
args: openArray[string] = [],
|
options: set[ProcessOption] = {poStdErrToStdOut}):
|
||||||
env: StringTableRef = nil,
|
owned(Process) {.rtl, extern: "nosp$1",
|
||||||
options: set[ProcessOption] = {poStdErrToStdOut}):
|
tags: [ExecIOEffect, ReadEnvEffect, RootEffect].}
|
||||||
owned(Process) {.rtl, extern: "nosp$1", tags: [ExecIOEffect, ReadEnvEffect,
|
|
||||||
RootEffect].}
|
|
||||||
## Starts a process. `Command` is the executable file, `workingDir` is the
|
## Starts a process. `Command` is the executable file, `workingDir` is the
|
||||||
## process's working directory. If ``workingDir == ""`` the current directory
|
## process's working directory. If ``workingDir == ""`` the current directory
|
||||||
## is used (default). `args` are the command line arguments that are passed to the
|
## is used (default). `args` are the command line arguments that are passed to the
|
||||||
|
|
@ -216,7 +209,7 @@ proc processID*(p: Process): int {.rtl, extern: "nosp$1".} =
|
||||||
return p.id
|
return p.id
|
||||||
|
|
||||||
proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
|
proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
|
||||||
extern: "nosp$1", tags: [].}
|
extern: "nosp$1", tags: [].}
|
||||||
## Waits for the process to finish and returns `p`'s error code.
|
## Waits for the process to finish and returns `p`'s error code.
|
||||||
##
|
##
|
||||||
## **WARNING**: Be careful when using `waitForExit` for processes created without
|
## **WARNING**: Be careful when using `waitForExit` for processes created without
|
||||||
|
|
@ -274,7 +267,7 @@ proc inputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
||||||
result = p.inHandle
|
result = p.inHandle
|
||||||
|
|
||||||
proc outputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
proc outputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
||||||
tags: [].} =
|
tags: [].} =
|
||||||
## Returns ``p``'s output file handle for reading from.
|
## Returns ``p``'s output file handle for reading from.
|
||||||
##
|
##
|
||||||
## **WARNING**: The returned `FileHandle` should not be closed manually as
|
## **WARNING**: The returned `FileHandle` should not be closed manually as
|
||||||
|
|
@ -286,7 +279,7 @@ proc outputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
||||||
result = p.outHandle
|
result = p.outHandle
|
||||||
|
|
||||||
proc errorHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
proc errorHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
|
||||||
tags: [].} =
|
tags: [].} =
|
||||||
## Returns ``p``'s error file handle for reading from.
|
## Returns ``p``'s error file handle for reading from.
|
||||||
##
|
##
|
||||||
## **WARNING**: The returned `FileHandle` should not be closed manually as
|
## **WARNING**: The returned `FileHandle` should not be closed manually as
|
||||||
|
|
@ -303,12 +296,11 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
|
||||||
result = cpuinfo.countProcessors()
|
result = cpuinfo.countProcessors()
|
||||||
|
|
||||||
proc execProcesses*(cmds: openArray[string],
|
proc execProcesses*(cmds: openArray[string],
|
||||||
options = {poStdErrToStdOut, poParentStreams},
|
options = {poStdErrToStdOut, poParentStreams}, n = countProcessors(),
|
||||||
n = countProcessors(),
|
beforeRunEvent: proc(idx: int) = nil,
|
||||||
beforeRunEvent: proc(idx: int) = nil,
|
afterRunEvent: proc(idx: int, p: Process) = nil):
|
||||||
afterRunEvent: proc(idx: int, p: Process) = nil): int
|
int {.rtl, extern: "nosp$1",
|
||||||
{.rtl, extern: "nosp$1",
|
tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect].} =
|
||||||
tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect].} =
|
|
||||||
## Executes the commands `cmds` in parallel.
|
## Executes the commands `cmds` in parallel.
|
||||||
## Creates `n` processes that execute in parallel.
|
## Creates `n` processes that execute in parallel.
|
||||||
##
|
##
|
||||||
|
|
@ -413,20 +405,20 @@ proc execProcesses*(cmds: openArray[string],
|
||||||
for i in 0..high(cmds):
|
for i in 0..high(cmds):
|
||||||
if beforeRunEvent != nil:
|
if beforeRunEvent != nil:
|
||||||
beforeRunEvent(i)
|
beforeRunEvent(i)
|
||||||
var p = startProcess(cmds[i], options=options + {poEvalCommand})
|
var p = startProcess(cmds[i], options = options + {poEvalCommand})
|
||||||
result = max(abs(waitForExit(p)), result)
|
result = max(abs(waitForExit(p)), result)
|
||||||
if afterRunEvent != nil: afterRunEvent(i, p)
|
if afterRunEvent != nil: afterRunEvent(i, p)
|
||||||
close(p)
|
close(p)
|
||||||
|
|
||||||
when not defined(useNimRtl):
|
when not defined(useNimRtl):
|
||||||
proc execProcess(command: string,
|
proc execProcess(command: string, workingDir: string = "",
|
||||||
workingDir: string = "",
|
args: openArray[string] = [], env: StringTableRef = nil,
|
||||||
args: openArray[string] = [],
|
options: set[ProcessOption] = {poStdErrToStdOut, poUsePath,
|
||||||
env: StringTableRef = nil,
|
poEvalCommand}):
|
||||||
options: set[ProcessOption] = {poStdErrToStdOut,
|
TaintedString =
|
||||||
poUsePath,
|
|
||||||
poEvalCommand}): TaintedString =
|
var p = startProcess(command, workingDir = workingDir, args = args,
|
||||||
var p = startProcess(command, workingDir=workingDir, args=args, env=env, options=options)
|
env = env, options = options)
|
||||||
var outp = outputStream(p)
|
var outp = outputStream(p)
|
||||||
result = TaintedString""
|
result = TaintedString""
|
||||||
var line = newStringOfCap(120).TaintedString
|
var line = newStringOfCap(120).TaintedString
|
||||||
|
|
@ -501,16 +493,14 @@ when defined(Windows) and not defined(useNimRtl):
|
||||||
#var
|
#var
|
||||||
# O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int
|
# O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int
|
||||||
# O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int
|
# O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int
|
||||||
proc myDup(h: Handle; inherit: WINBOOL=1): Handle =
|
proc myDup(h: Handle; inherit: WINBOOL = 1): Handle =
|
||||||
let thisProc = getCurrentProcess()
|
let thisProc = getCurrentProcess()
|
||||||
if duplicateHandle(thisProc, h,
|
if duplicateHandle(thisProc, h, thisProc, addr result, 0, inherit,
|
||||||
thisProc, addr result,0,inherit,
|
|
||||||
DUPLICATE_SAME_ACCESS) == 0:
|
DUPLICATE_SAME_ACCESS) == 0:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
proc createAllPipeHandles(si: var STARTUPINFO;
|
proc createAllPipeHandles(si: var STARTUPINFO;
|
||||||
stdin, stdout, stderr: var Handle;
|
stdin, stdout, stderr: var Handle; hash: int) =
|
||||||
hash: int) =
|
|
||||||
var sa: SECURITY_ATTRIBUTES
|
var sa: SECURITY_ATTRIBUTES
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES).cint
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES).cint
|
||||||
sa.lpSecurityDescriptor = nil
|
sa.lpSecurityDescriptor = nil
|
||||||
|
|
@ -518,37 +508,37 @@ when defined(Windows) and not defined(useNimRtl):
|
||||||
let pipeOutName = newWideCString(r"\\.\pipe\stdout" & $hash)
|
let pipeOutName = newWideCString(r"\\.\pipe\stdout" & $hash)
|
||||||
let pipeInName = newWideCString(r"\\.\pipe\stdin" & $hash)
|
let pipeInName = newWideCString(r"\\.\pipe\stdin" & $hash)
|
||||||
let pipeOut = createNamedPipe(pipeOutName,
|
let pipeOut = createNamedPipe(pipeOutName,
|
||||||
dwOpenMode=PIPE_ACCESS_INBOUND or FILE_FLAG_WRITE_THROUGH,
|
dwOpenMode = PIPE_ACCESS_INBOUND or FILE_FLAG_WRITE_THROUGH,
|
||||||
dwPipeMode=PIPE_NOWAIT,
|
dwPipeMode = PIPE_NOWAIT,
|
||||||
nMaxInstances=1,
|
nMaxInstances = 1,
|
||||||
nOutBufferSize=1024, nInBufferSize=1024,
|
nOutBufferSize = 1024, nInBufferSize = 1024,
|
||||||
nDefaultTimeOut=0,addr sa)
|
nDefaultTimeOut = 0, addr sa)
|
||||||
if pipeOut == INVALID_HANDLE_VALUE:
|
if pipeOut == INVALID_HANDLE_VALUE:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
let pipeIn = createNamedPipe(pipeInName,
|
let pipeIn = createNamedPipe(pipeInName,
|
||||||
dwOpenMode=PIPE_ACCESS_OUTBOUND or FILE_FLAG_WRITE_THROUGH,
|
dwOpenMode = PIPE_ACCESS_OUTBOUND or FILE_FLAG_WRITE_THROUGH,
|
||||||
dwPipeMode=PIPE_NOWAIT,
|
dwPipeMode = PIPE_NOWAIT,
|
||||||
nMaxInstances=1,
|
nMaxInstances = 1,
|
||||||
nOutBufferSize=1024, nInBufferSize=1024,
|
nOutBufferSize = 1024, nInBufferSize = 1024,
|
||||||
nDefaultTimeOut=0,addr sa)
|
nDefaultTimeOut = 0, addr sa)
|
||||||
if pipeIn == INVALID_HANDLE_VALUE:
|
if pipeIn == INVALID_HANDLE_VALUE:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
si.hStdOutput = createFileW(pipeOutName,
|
si.hStdOutput = createFileW(pipeOutName,
|
||||||
FILE_WRITE_DATA or SYNCHRONIZE, 0, addr sa,
|
FILE_WRITE_DATA or SYNCHRONIZE, 0, addr sa,
|
||||||
OPEN_EXISTING, # very important flag!
|
OPEN_EXISTING, # very important flag!
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
0 # no template file for OPEN_EXISTING
|
0 # no template file for OPEN_EXISTING
|
||||||
)
|
)
|
||||||
if si.hStdOutput == INVALID_HANDLE_VALUE:
|
if si.hStdOutput == INVALID_HANDLE_VALUE:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
si.hStdError = myDup(si.hStdOutput)
|
si.hStdError = myDup(si.hStdOutput)
|
||||||
si.hStdInput = createFileW(pipeInName,
|
si.hStdInput = createFileW(pipeInName,
|
||||||
FILE_READ_DATA or SYNCHRONIZE, 0, addr sa,
|
FILE_READ_DATA or SYNCHRONIZE, 0, addr sa,
|
||||||
OPEN_EXISTING, # very important flag!
|
OPEN_EXISTING, # very important flag!
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
0 # no template file for OPEN_EXISTING
|
0 # no template file for OPEN_EXISTING
|
||||||
)
|
)
|
||||||
if si.hStdOutput == INVALID_HANDLE_VALUE:
|
if si.hStdOutput == INVALID_HANDLE_VALUE:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
|
|
@ -569,11 +559,10 @@ when defined(Windows) and not defined(useNimRtl):
|
||||||
proc fileClose(h: Handle) {.inline.} =
|
proc fileClose(h: Handle) {.inline.} =
|
||||||
if h > 4: discard closeHandle(h)
|
if h > 4: discard closeHandle(h)
|
||||||
|
|
||||||
proc startProcess(command: string,
|
proc startProcess(command: string, workingDir: string = "",
|
||||||
workingDir: string = "",
|
args: openArray[string] = [], env: StringTableRef = nil,
|
||||||
args: openArray[string] = [],
|
options: set[ProcessOption] = {poStdErrToStdOut}):
|
||||||
env: StringTableRef = nil,
|
owned Process =
|
||||||
options: set[ProcessOption] = {poStdErrToStdOut}): owned Process =
|
|
||||||
var
|
var
|
||||||
si: STARTUPINFO
|
si: STARTUPINFO
|
||||||
procInfo: PROCESS_INFORMATION
|
procInfo: PROCESS_INFORMATION
|
||||||
|
|
@ -789,7 +778,7 @@ when defined(Windows) and not defined(useNimRtl):
|
||||||
|
|
||||||
proc hasData*(p: Process): bool =
|
proc hasData*(p: Process): bool =
|
||||||
var x: int32
|
var x: int32
|
||||||
if peekNamedPipe(p.outHandle, lpTotalBytesAvail=addr x):
|
if peekNamedPipe(p.outHandle, lpTotalBytesAvail = addr x):
|
||||||
result = x > 0
|
result = x > 0
|
||||||
|
|
||||||
elif not defined(useNimRtl):
|
elif not defined(useNimRtl):
|
||||||
|
|
@ -842,11 +831,10 @@ elif not defined(useNimRtl):
|
||||||
tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], cdecl, gcsafe.}
|
tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], cdecl, gcsafe.}
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
proc startProcess(command: string,
|
proc startProcess(command: string, workingDir: string = "",
|
||||||
workingDir: string = "",
|
args: openArray[string] = [], env: StringTableRef = nil,
|
||||||
args: openArray[string] = [],
|
options: set[ProcessOption] = {poStdErrToStdOut}):
|
||||||
env: StringTableRef = nil,
|
owned Process =
|
||||||
options: set[ProcessOption] = {poStdErrToStdOut}): owned Process =
|
|
||||||
var
|
var
|
||||||
pStdin, pStdout, pStderr: array[0..1, cint]
|
pStdin, pStdout, pStderr: array[0..1, cint]
|
||||||
new(result)
|
new(result)
|
||||||
|
|
@ -1013,7 +1001,7 @@ elif not defined(useNimRtl):
|
||||||
if sizeRead == sizeof(error):
|
if sizeRead == sizeof(error):
|
||||||
raiseOSError(osLastError(),
|
raiseOSError(osLastError(),
|
||||||
"Could not find command: '$1'. OS error: $2" %
|
"Could not find command: '$1'. OS error: $2" %
|
||||||
[$data.sysCommand, $strerror(error)])
|
[$data.sysCommand, $strerror(error)])
|
||||||
|
|
||||||
return pid
|
return pid
|
||||||
|
|
||||||
|
|
@ -1066,7 +1054,7 @@ elif not defined(useNimRtl):
|
||||||
discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
|
discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
|
||||||
|
|
||||||
startProcessFail(data)
|
startProcessFail(data)
|
||||||
{.pop}
|
{.pop.}
|
||||||
|
|
||||||
proc close(p: Process) =
|
proc close(p: Process) =
|
||||||
if poParentStreams notin p.options:
|
if poParentStreams notin p.options:
|
||||||
|
|
@ -1401,7 +1389,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
|
||||||
## .. code-block:: Nim
|
## .. code-block:: Nim
|
||||||
## let (outp, errC) = execCmdEx("nim c -r mytestfile.nim")
|
## let (outp, errC) = execCmdEx("nim c -r mytestfile.nim")
|
||||||
|
|
||||||
var p = startProcess(command, options=options + {poEvalCommand})
|
var p = startProcess(command, options = options + {poEvalCommand})
|
||||||
var outp = outputStream(p)
|
var outp = outputStream(p)
|
||||||
|
|
||||||
# There is no way to provide input for the child process
|
# There is no way to provide input for the child process
|
||||||
|
|
|
||||||
|
|
@ -11,24 +11,25 @@
|
||||||
## for JavaScript.
|
## for JavaScript.
|
||||||
|
|
||||||
type
|
type
|
||||||
PathComponent* = enum ## Enumeration specifying a path component.
|
PathComponent* = enum ## Enumeration specifying a path component.
|
||||||
pcFile, ## path refers to a file
|
pcFile, ## path refers to a file
|
||||||
pcLinkToFile, ## path refers to a symbolic link to a file
|
pcLinkToFile, ## path refers to a symbolic link to a file
|
||||||
pcDir, ## path refers to a directory
|
pcDir, ## path refers to a directory
|
||||||
pcLinkToDir ## path refers to a symbolic link to a directory
|
pcLinkToDir ## path refers to a symbolic link to a directory
|
||||||
|
|
||||||
proc staticWalkDir(dir: string; relative: bool): seq[
|
proc staticWalkDir(dir: string; relative: bool): seq[
|
||||||
tuple[kind: PathComponent, path: string]] =
|
tuple[kind: PathComponent; path: string]] =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: string] =
|
iterator walkDir*(dir: string; relative = false): tuple[kind: PathComponent;
|
||||||
|
path: string] =
|
||||||
for k, v in items(staticWalkDir(dir, relative)):
|
for k, v in items(staticWalkDir(dir, relative)):
|
||||||
yield (k, v)
|
yield (k, v)
|
||||||
|
|
||||||
iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string =
|
iterator walkDirRec*(dir: string; filter = {pcFile, pcDir}): string =
|
||||||
var stack = @[dir]
|
var stack = @[dir]
|
||||||
while stack.len > 0:
|
while stack.len > 0:
|
||||||
for k,p in walkDir(stack.pop()):
|
for k, p in walkDir(stack.pop()):
|
||||||
if k in filter:
|
if k in filter:
|
||||||
case k
|
case k
|
||||||
of pcFile, pcLinkToFile: yield p
|
of pcFile, pcLinkToFile: yield p
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,8 @@ proc isDotDot(x: string; bounds: (int, int)): bool =
|
||||||
proc isSlash(x: string; bounds: (int, int)): bool =
|
proc isSlash(x: string; bounds: (int, int)): bool =
|
||||||
bounds[1] == bounds[0] and x[bounds[0]] in {DirSep, AltSep}
|
bounds[1] == bounds[0] and x[bounds[0]] in {DirSep, AltSep}
|
||||||
|
|
||||||
proc addNormalizePath*(x: string; result: var string; state: var int; dirSep = DirSep) =
|
proc addNormalizePath*(x: string; result: var string; state: var int;
|
||||||
|
dirSep = DirSep) =
|
||||||
## Low level proc. Undocumented.
|
## Low level proc. Undocumented.
|
||||||
|
|
||||||
# state: 0th bit set if isAbsolute path. Other bits count
|
# state: 0th bit set if isAbsolute path. Other bits count
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ when defined(windows):
|
||||||
VectoredHandler = proc (p: PEXCEPTION_POINTERS): LONG {.stdcall.}
|
VectoredHandler = proc (p: PEXCEPTION_POINTERS): LONG {.stdcall.}
|
||||||
proc addVectoredExceptionHandler(firstHandler: ULONG,
|
proc addVectoredExceptionHandler(firstHandler: ULONG,
|
||||||
handler: VectoredHandler): pointer {.
|
handler: VectoredHandler): pointer {.
|
||||||
importc: "AddVectoredExceptionHandler", stdcall, dynlib: "kernel32.dll"}
|
importc: "AddVectoredExceptionHandler", stdcall, dynlib: "kernel32.dll".}
|
||||||
|
|
||||||
{.push stackTrace: off.}
|
{.push stackTrace: off.}
|
||||||
proc segfaultHandler(p: PEXCEPTION_POINTERS): LONG {.stdcall.} =
|
proc segfaultHandler(p: PEXCEPTION_POINTERS): LONG {.stdcall.} =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue