Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
commit
6377b52d8e
13 changed files with 132 additions and 39 deletions
|
|
@ -1315,8 +1315,11 @@ proc shouldRecompile(code: Rope, cfile: Cfile): bool =
|
||||||
if optForceFullMake notin gGlobalOptions:
|
if optForceFullMake notin gGlobalOptions:
|
||||||
if not equalsFile(code, cfile.cname):
|
if not equalsFile(code, cfile.cname):
|
||||||
if isDefined("nimdiff"):
|
if isDefined("nimdiff"):
|
||||||
|
if fileExists(cfile.cname):
|
||||||
copyFile(cfile.cname, cfile.cname & ".backup")
|
copyFile(cfile.cname, cfile.cname & ".backup")
|
||||||
echo "diff ", cfile.cname, ".backup ", cfile.cname
|
echo "diff ", cfile.cname, ".backup ", cfile.cname
|
||||||
|
else:
|
||||||
|
echo "new file ", cfile.cname
|
||||||
writeRope(code, cfile.cname)
|
writeRope(code, cfile.cname)
|
||||||
return
|
return
|
||||||
if existsFile(cfile.obj) and os.fileNewer(cfile.obj, cfile.cname):
|
if existsFile(cfile.obj) and os.fileNewer(cfile.obj, cfile.cname):
|
||||||
|
|
|
||||||
|
|
@ -449,7 +449,8 @@ proc unsignedTrimmerPHP(size: BiggestInt): Rope =
|
||||||
template unsignedTrimmer(size: BiggestInt): Rope =
|
template unsignedTrimmer(size: BiggestInt): Rope =
|
||||||
size.unsignedTrimmerJS | size.unsignedTrimmerPHP
|
size.unsignedTrimmerJS | size.unsignedTrimmerPHP
|
||||||
|
|
||||||
proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string, reassign: bool = false) =
|
proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string,
|
||||||
|
reassign = false) =
|
||||||
var x, y: TCompRes
|
var x, y: TCompRes
|
||||||
gen(p, n.sons[1], x)
|
gen(p, n.sons[1], x)
|
||||||
gen(p, n.sons[2], y)
|
gen(p, n.sons[2], y)
|
||||||
|
|
@ -2128,6 +2129,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
else: r.res = rope(f.toStrMaxPrecision)
|
else: r.res = rope(f.toStrMaxPrecision)
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
|
if isEmptyType(n.typ): genLineDir(p, n)
|
||||||
if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic != mNone):
|
if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic != mNone):
|
||||||
genMagic(p, n, r)
|
genMagic(p, n, r)
|
||||||
elif n.sons[0].kind == nkSym and sfInfixCall in n.sons[0].sym.flags and
|
elif n.sons[0].kind == nkSym and sfInfixCall in n.sons[0].sym.flags and
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ proc lowerTupleUnpackingForAsgn*(n: PNode; owner: PSym): PNode =
|
||||||
let value = n.lastSon
|
let value = n.lastSon
|
||||||
result = newNodeI(nkStmtList, n.info)
|
result = newNodeI(nkStmtList, n.info)
|
||||||
|
|
||||||
var temp = newSym(skLet, getIdent(genPrefix), owner, value.info)
|
var temp = newSym(skLet, getIdent("_"), owner, value.info)
|
||||||
var v = newNodeI(nkLetSection, value.info)
|
var v = newNodeI(nkLetSection, value.info)
|
||||||
let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)
|
let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)
|
||||||
|
|
||||||
|
|
|
||||||
4
koch.nim
4
koch.nim
|
|
@ -178,7 +178,7 @@ proc bundleNimbleExe() =
|
||||||
bundleNimbleSrc()
|
bundleNimbleSrc()
|
||||||
# now compile Nimble and copy it to $nim/bin for the installer.ini
|
# now compile Nimble and copy it to $nim/bin for the installer.ini
|
||||||
# to pick it up:
|
# to pick it up:
|
||||||
nimexec("c dist/nimble/src/nimble.nim")
|
nimexec("c -d:release dist/nimble/src/nimble.nim")
|
||||||
copyExe("dist/nimble/src/nimble".exe, "bin/nimble".exe)
|
copyExe("dist/nimble/src/nimble".exe, "bin/nimble".exe)
|
||||||
|
|
||||||
proc buildNimble(latest: bool) =
|
proc buildNimble(latest: bool) =
|
||||||
|
|
@ -205,7 +205,7 @@ proc buildNimble(latest: bool) =
|
||||||
else:
|
else:
|
||||||
exec("git checkout -f stable")
|
exec("git checkout -f stable")
|
||||||
exec("git pull")
|
exec("git pull")
|
||||||
nimexec("c --noNimblePath -p:compiler " & installDir / "src/nimble.nim")
|
nimexec("c --noNimblePath -p:compiler -d:release " & installDir / "src/nimble.nim")
|
||||||
copyExe(installDir / "src/nimble".exe, "bin/nimble".exe)
|
copyExe(installDir / "src/nimble".exe, "bin/nimble".exe)
|
||||||
|
|
||||||
proc bundleNimsuggest(buildExe: bool) =
|
proc bundleNimsuggest(buildExe: bool) =
|
||||||
|
|
|
||||||
|
|
@ -97,15 +97,6 @@ when not defined(macosx):
|
||||||
## Second-granularity time of last status change.
|
## Second-granularity time of last status change.
|
||||||
result = s.st_ctim.tv_sec
|
result = s.st_ctim.tv_sec
|
||||||
|
|
||||||
proc WIFCONTINUED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
|
|
||||||
## True if child has been continued.
|
|
||||||
proc WIFEXITED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
|
|
||||||
## True if child exited normally.
|
|
||||||
proc WIFSIGNALED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
|
|
||||||
## True if child exited due to uncaught signal.
|
|
||||||
proc WIFSTOPPED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
|
|
||||||
## True if child is currently stopped.
|
|
||||||
|
|
||||||
when hasAioH:
|
when hasAioH:
|
||||||
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||||
proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||||
|
|
|
||||||
|
|
@ -602,3 +602,12 @@ var
|
||||||
include posix_linux_amd64_consts
|
include posix_linux_amd64_consts
|
||||||
|
|
||||||
const POSIX_SPAWN_USEVFORK* = cint(0x40) # needs _GNU_SOURCE!
|
const POSIX_SPAWN_USEVFORK* = cint(0x40) # needs _GNU_SOURCE!
|
||||||
|
|
||||||
|
# <sys/wait.h>
|
||||||
|
proc WEXITSTATUS*(s: cint): cint = (s and 0xff00) shr 8
|
||||||
|
proc WTERMSIG*(s:cint): cint = s and 0x7f
|
||||||
|
proc WSTOPSIG*(s:cint): cint = WEXITSTATUS(s)
|
||||||
|
proc WIFEXITED*(s:cint) : bool = WTERMSIG(s) == 0
|
||||||
|
proc WIFSIGNALED*(s:cint) : bool = (cast[int8]((s and 0x7f) + 1) shr 1) > 0
|
||||||
|
proc WIFSTOPPED*(s:cint) : bool = (s and 0xff) == 0x7f
|
||||||
|
proc WIFCONTINUED*(s:cint) : bool = s == W_CONTINUED
|
||||||
|
|
|
||||||
|
|
@ -611,3 +611,18 @@ when hasSpawnH:
|
||||||
# OR'ing of flags:
|
# OR'ing of flags:
|
||||||
const POSIX_SPAWN_USEVFORK* = cint(0)
|
const POSIX_SPAWN_USEVFORK* = cint(0)
|
||||||
|
|
||||||
|
# <sys/wait.h>
|
||||||
|
proc WEXITSTATUS*(s: cint): cint {.importc, header: "<sys/wait.h>".}
|
||||||
|
## Exit code, iff WIFEXITED(s)
|
||||||
|
proc WTERMSIG*(s: cint): cint {.importc, header: "<sys/wait.h>".}
|
||||||
|
## Termination signal, iff WIFSIGNALED(s)
|
||||||
|
proc WSTOPSIG*(s: cint): cint {.importc, header: "<sys/wait.h>".}
|
||||||
|
## Stop signal, iff WIFSTOPPED(s)
|
||||||
|
proc WIFEXITED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
|
||||||
|
## True if child exited normally.
|
||||||
|
proc WIFSIGNALED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
|
||||||
|
## True if child exited due to uncaught signal.
|
||||||
|
proc WIFSTOPPED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
|
||||||
|
## True if child is currently stopped.
|
||||||
|
proc WIFCONTINUED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
|
||||||
|
## True if child has been continued.
|
||||||
|
|
|
||||||
|
|
@ -1213,22 +1213,22 @@ when not defined(js):
|
||||||
proc parseJson*(s: Stream, filename: string): JsonNode =
|
proc parseJson*(s: Stream, filename: string): JsonNode =
|
||||||
## Parses from a stream `s` into a `JsonNode`. `filename` is only needed
|
## Parses from a stream `s` into a `JsonNode`. `filename` is only needed
|
||||||
## for nice error messages.
|
## for nice error messages.
|
||||||
## If `s` contains extra data, it will raising `JsonParsingError`.
|
## If `s` contains extra data, it will raise `JsonParsingError`.
|
||||||
var p: JsonParser
|
var p: JsonParser
|
||||||
p.open(s, filename)
|
p.open(s, filename)
|
||||||
defer: p.close()
|
defer: p.close()
|
||||||
discard getTok(p) # read first token
|
discard getTok(p) # read first token
|
||||||
result = p.parseJson()
|
result = p.parseJson()
|
||||||
eat(p, tkEof) # check there are no exstra data
|
eat(p, tkEof) # check if there is no extra data
|
||||||
|
|
||||||
proc parseJson*(buffer: string): JsonNode =
|
proc parseJson*(buffer: string): JsonNode =
|
||||||
## Parses JSON from `buffer`.
|
## Parses JSON from `buffer`.
|
||||||
## If `buffer` contains extra data, it will raising `JsonParsingError`.
|
## If `buffer` contains extra data, it will raise `JsonParsingError`.
|
||||||
result = parseJson(newStringStream(buffer), "input")
|
result = parseJson(newStringStream(buffer), "input")
|
||||||
|
|
||||||
proc parseFile*(filename: string): JsonNode =
|
proc parseFile*(filename: string): JsonNode =
|
||||||
## Parses `file` into a `JsonNode`.
|
## Parses `file` into a `JsonNode`.
|
||||||
## If `file` contains extra data, it will raising `JsonParsingError`.
|
## If `file` contains extra data, it will raise `JsonParsingError`.
|
||||||
var stream = newFileStream(filename, fmRead)
|
var stream = newFileStream(filename, fmRead)
|
||||||
if stream == nil:
|
if stream == nil:
|
||||||
raise newException(IOError, "cannot read from file: " & filename)
|
raise newException(IOError, "cannot read from file: " & filename)
|
||||||
|
|
|
||||||
|
|
@ -209,9 +209,16 @@ proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
|
||||||
##
|
##
|
||||||
## **Warning**: Be careful when using waitForExit for processes created without
|
## **Warning**: Be careful when using waitForExit for processes created without
|
||||||
## poParentStreams because they may fill output buffers, causing deadlock.
|
## poParentStreams because they may fill output buffers, causing deadlock.
|
||||||
|
##
|
||||||
|
## On posix, if the process has exited because of a signal, 128 + signal
|
||||||
|
## number will be returned.
|
||||||
|
|
||||||
|
|
||||||
proc peekExitCode*(p: Process): int {.tags: [].}
|
proc peekExitCode*(p: Process): int {.tags: [].}
|
||||||
## return -1 if the process is still running. Otherwise the process' exit code
|
## return -1 if the process is still running. Otherwise the process' exit code
|
||||||
|
##
|
||||||
|
## On posix, if the process has exited because of a signal, 128 + signal
|
||||||
|
## number will be returned.
|
||||||
|
|
||||||
proc inputStream*(p: Process): Stream {.rtl, extern: "nosp$1", tags: [].}
|
proc inputStream*(p: Process): Stream {.rtl, extern: "nosp$1", tags: [].}
|
||||||
## returns ``p``'s input stream for writing to.
|
## returns ``p``'s input stream for writing to.
|
||||||
|
|
@ -679,6 +686,16 @@ elif not defined(useNimRtl):
|
||||||
readIdx = 0
|
readIdx = 0
|
||||||
writeIdx = 1
|
writeIdx = 1
|
||||||
|
|
||||||
|
proc isExitStatus(status: cint): bool =
|
||||||
|
WIFEXITED(status) or WIFSIGNALED(status)
|
||||||
|
|
||||||
|
proc exitStatus(status: cint): cint =
|
||||||
|
if WIFSIGNALED(status):
|
||||||
|
# like the shell!
|
||||||
|
128 + WTERMSIG(status)
|
||||||
|
else:
|
||||||
|
WEXITSTATUS(status)
|
||||||
|
|
||||||
proc envToCStringArray(t: StringTableRef): cstringArray =
|
proc envToCStringArray(t: StringTableRef): cstringArray =
|
||||||
result = cast[cstringArray](alloc0((t.len + 1) * sizeof(cstring)))
|
result = cast[cstringArray](alloc0((t.len + 1) * sizeof(cstring)))
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
@ -967,7 +984,7 @@ elif not defined(useNimRtl):
|
||||||
var status : cint = 1
|
var status : cint = 1
|
||||||
ret = waitpid(p.id, status, WNOHANG)
|
ret = waitpid(p.id, status, WNOHANG)
|
||||||
if ret == int(p.id):
|
if ret == int(p.id):
|
||||||
if WIFEXITED(status):
|
if isExitStatus(status):
|
||||||
p.exitStatus = status
|
p.exitStatus = status
|
||||||
return false
|
return false
|
||||||
else:
|
else:
|
||||||
|
|
@ -990,7 +1007,9 @@ elif not defined(useNimRtl):
|
||||||
import kqueue, times
|
import kqueue, times
|
||||||
|
|
||||||
proc waitForExit(p: Process, timeout: int = -1): int =
|
proc waitForExit(p: Process, timeout: int = -1): int =
|
||||||
if p.exitStatus != -3: return((p.exitStatus and 0xFF00) shr 8)
|
if p.exitStatus != -3:
|
||||||
|
return exitStatus(p.exitStatus)
|
||||||
|
|
||||||
if timeout == -1:
|
if timeout == -1:
|
||||||
var status : cint = 1
|
var status : cint = 1
|
||||||
if waitpid(p.id, status, 0) < 0:
|
if waitpid(p.id, status, 0) < 0:
|
||||||
|
|
@ -1041,7 +1060,7 @@ elif not defined(useNimRtl):
|
||||||
finally:
|
finally:
|
||||||
discard posix.close(kqFD)
|
discard posix.close(kqFD)
|
||||||
|
|
||||||
result = ((p.exitStatus and 0xFF00) shr 8)
|
result = exitStatus(p.exitStatus)
|
||||||
else:
|
else:
|
||||||
import times
|
import times
|
||||||
|
|
||||||
|
|
@ -1077,7 +1096,9 @@ elif not defined(useNimRtl):
|
||||||
# ``waitPid`` fails if the process is not running anymore. But then
|
# ``waitPid`` fails if the process is not running anymore. But then
|
||||||
# ``running`` probably set ``p.exitStatus`` for us. Since ``p.exitStatus`` is
|
# ``running`` probably set ``p.exitStatus`` for us. Since ``p.exitStatus`` is
|
||||||
# initialized with -3, wrong success exit codes are prevented.
|
# initialized with -3, wrong success exit codes are prevented.
|
||||||
if p.exitStatus != -3: return((p.exitStatus and 0xFF00) shr 8)
|
if p.exitStatus != -3:
|
||||||
|
return exitStatus(p.exitStatus)
|
||||||
|
|
||||||
if timeout == -1:
|
if timeout == -1:
|
||||||
var status : cint = 1
|
var status : cint = 1
|
||||||
if waitpid(p.id, status, 0) < 0:
|
if waitpid(p.id, status, 0) < 0:
|
||||||
|
|
@ -1151,17 +1172,19 @@ elif not defined(useNimRtl):
|
||||||
if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1:
|
if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
result = ((p.exitStatus and 0xFF00) shr 8)
|
result = exitStatus(p.exitStatus)
|
||||||
|
|
||||||
proc peekExitCode(p: Process): int =
|
proc peekExitCode(p: Process): int =
|
||||||
var status = cint(0)
|
var status = cint(0)
|
||||||
result = -1
|
result = -1
|
||||||
if p.exitStatus != -3: return((p.exitStatus and 0xFF00) shr 8)
|
if p.exitStatus != -3:
|
||||||
|
return exitStatus(p.exitStatus)
|
||||||
|
|
||||||
var ret = waitpid(p.id, status, WNOHANG)
|
var ret = waitpid(p.id, status, WNOHANG)
|
||||||
if ret > 0:
|
if ret > 0:
|
||||||
if WIFEXITED(status):
|
if isExitStatus(status):
|
||||||
p.exitStatus = status
|
p.exitStatus = status
|
||||||
result = (status and 0xFF00) shr 8
|
result = exitStatus(status)
|
||||||
|
|
||||||
proc createStream(stream: var Stream, handle: var FileHandle,
|
proc createStream(stream: var Stream, handle: var FileHandle,
|
||||||
fileMode: FileMode) =
|
fileMode: FileMode) =
|
||||||
|
|
@ -1189,7 +1212,8 @@ elif not defined(useNimRtl):
|
||||||
|
|
||||||
proc execCmd(command: string): int =
|
proc execCmd(command: string): int =
|
||||||
when defined(linux):
|
when defined(linux):
|
||||||
result = csystem(command) shr 8
|
let tmp = csystem(command)
|
||||||
|
result = if tmp == -1: tmp else: exitStatus(tmp)
|
||||||
else:
|
else:
|
||||||
result = csystem(command)
|
result = csystem(command)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2016,6 +2016,12 @@ proc min*(x, y: float): float {.magic: "MinF64", noSideEffect.} =
|
||||||
if x <= y: x else: y
|
if x <= y: x else: y
|
||||||
proc max*(x, y: float): float {.magic: "MaxF64", noSideEffect.} =
|
proc max*(x, y: float): float {.magic: "MaxF64", noSideEffect.} =
|
||||||
if y <= x: x else: y
|
if y <= x: x else: y
|
||||||
|
|
||||||
|
proc min*[T](x, y: T): T =
|
||||||
|
if x <= y: x else: y
|
||||||
|
|
||||||
|
proc max*[T](x, y: T): T =
|
||||||
|
if y <= x: x else: y
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
proc clamp*[T](x, a, b: T): T =
|
proc clamp*[T](x, a, b: T): T =
|
||||||
|
|
|
||||||
36
tests/osproc/texitsignal.nim
Normal file
36
tests/osproc/texitsignal.nim
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
discard """
|
||||||
|
output: '''true
|
||||||
|
true'''
|
||||||
|
targets: "c"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os, osproc
|
||||||
|
when not defined(windows):
|
||||||
|
import posix
|
||||||
|
|
||||||
|
# Checks that the environment is passed correctly in startProcess
|
||||||
|
# To do that launches a copy of itself with a new environment.
|
||||||
|
|
||||||
|
if paramCount() == 0:
|
||||||
|
# Parent process
|
||||||
|
|
||||||
|
let p = startProcess(
|
||||||
|
getAppFilename(),
|
||||||
|
args = @["child"],
|
||||||
|
options = {poStdErrToStdOut, poUsePath, poParentStreams}
|
||||||
|
)
|
||||||
|
|
||||||
|
echo p.running()
|
||||||
|
|
||||||
|
p.kill()
|
||||||
|
|
||||||
|
when defined(windows):
|
||||||
|
# windows kill happens using TerminateProcess(h, 0), so we should get a
|
||||||
|
# 0 here
|
||||||
|
echo p.waitForExit() == 0
|
||||||
|
else:
|
||||||
|
# on posix (non-windows), kill sends SIGKILL
|
||||||
|
echo p.waitForExit() == 128 + SIGKILL
|
||||||
|
|
||||||
|
else:
|
||||||
|
sleep(5000) # should get killed before this
|
||||||
|
|
@ -21,6 +21,8 @@ proc pg[T](x, y: var T) =
|
||||||
|
|
||||||
# test as a top level statement:
|
# test as a top level statement:
|
||||||
var x, y, a, b: int
|
var x, y, a, b: int
|
||||||
|
# test for regression:
|
||||||
|
(x, y) = (1, 2)
|
||||||
(x, y) = fooBar()
|
(x, y) = fooBar()
|
||||||
|
|
||||||
echo x, " ", y
|
echo x, " ", y
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ Changelog
|
||||||
Changes affecting backwards compatibility
|
Changes affecting backwards compatibility
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
|
- There are now two different HTTP response types, ``Response`` and
|
||||||
|
``AsyncResponse``. ``AsyncResponse``'s ``body`` accessor returns a
|
||||||
|
``Future[string]``!
|
||||||
- ``httpclient.request`` now respects ``maxRedirects`` option. Previously
|
- ``httpclient.request`` now respects ``maxRedirects`` option. Previously
|
||||||
redirects were handled only by ``get`` and ``post`` procs.
|
redirects were handled only by ``get`` and ``post`` procs.
|
||||||
- The IO routines now raise ``EOFError`` for the "end of file" condition.
|
- The IO routines now raise ``EOFError`` for the "end of file" condition.
|
||||||
|
|
@ -56,6 +59,8 @@ Changes affecting backwards compatibility
|
||||||
checks. When fields within case objects are initialiazed, the compiler will
|
checks. When fields within case objects are initialiazed, the compiler will
|
||||||
now demand that the respective discriminator field has a matching known
|
now demand that the respective discriminator field has a matching known
|
||||||
compile-time value.
|
compile-time value.
|
||||||
|
- On posix, the results of `waitForExit`, `peekExitCode`, `execCmd` will return
|
||||||
|
128 + signal number if the application terminates via signal.
|
||||||
|
|
||||||
Library Additions
|
Library Additions
|
||||||
-----------------
|
-----------------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue