added system.gorgeEx that includes the exitCode; refs #4874; fixes #1994

This commit is contained in:
Araq 2017-01-07 02:38:26 +01:00
commit 9d488261df
8 changed files with 46 additions and 20 deletions

View file

@ -879,7 +879,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
# it's a callback: # it's a callback:
c.callbacks[-prc.offset-2].value( c.callbacks[-prc.offset-2].value(
VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs), VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs),
currentException: c.currentExceptionB)) currentException: c.currentExceptionB,
currentLineInfo: c.debug[pc]))
elif sfImportc in prc.flags: elif sfImportc in prc.flags:
if allowFFI notin c.features: if allowFFI notin c.features:
globalError(c.debug[pc], errGenerated, "VM not allowed to do FFI") globalError(c.debug[pc], errGenerated, "VM not allowed to do FFI")
@ -1246,7 +1247,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
createStr regs[ra] createStr regs[ra]
regs[ra].node.strVal = opGorge(regs[rb].node.strVal, regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
regs[rc].node.strVal, regs[rd].node.strVal, regs[rc].node.strVal, regs[rd].node.strVal,
c.debug[pc]) c.debug[pc])[0]
of opcNError: of opcNError:
decodeB(rkNode) decodeB(rkNode)
let a = regs[ra].node let a = regs[ra].node

View file

@ -181,6 +181,7 @@ type
ra*, rb*, rc*: Natural ra*, rb*, rc*: Natural
slots*: pointer slots*: pointer
currentException*: PNode currentException*: PNode
currentLineInfo*: TLineInfo
VmCallback* = proc (args: VmArgs) {.closure.} VmCallback* = proc (args: VmArgs) {.closure.}
PCtx* = ref TCtx PCtx* = ref TCtx

View file

@ -9,24 +9,24 @@
import ast, types, msgs, os, osproc, streams, options, idents, securehash import ast, types, msgs, os, osproc, streams, options, idents, securehash
proc readOutput(p: Process): string = proc readOutput(p: Process): (string, int) =
result = "" result[0] = ""
var output = p.outputStream var output = p.outputStream
while not output.atEnd: while not output.atEnd:
result.add(output.readLine) result[0].add(output.readLine)
result.add("\n") result[0].add("\n")
if result.len > 0: if result[0].len > 0:
result.setLen(result.len - "\n".len) result[0].setLen(result[0].len - "\n".len)
discard p.waitForExit result[1] = p.waitForExit
proc opGorge*(cmd, input, cache: string, info: TLineInfo): string = proc opGorge*(cmd, input, cache: string, info: TLineInfo): (string, int) =
let workingDir = parentDir(info.toFullPath) let workingDir = parentDir(info.toFullPath)
if cache.len > 0:# and optForceFullMake notin gGlobalOptions: if cache.len > 0:# and optForceFullMake notin gGlobalOptions:
let h = secureHash(cmd & "\t" & input & "\t" & cache) let h = secureHash(cmd & "\t" & input & "\t" & cache)
let filename = options.toGeneratedFile("gorge_" & $h, "txt") let filename = options.toGeneratedFile("gorge_" & $h, "txt")
var f: File var f: File
if open(f, filename): if open(f, filename):
result = f.readAll result = (f.readAll, 0)
f.close f.close
return return
var readSuccessful = false var readSuccessful = false
@ -38,9 +38,9 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo): string =
p.inputStream.close() p.inputStream.close()
result = p.readOutput result = p.readOutput
readSuccessful = true readSuccessful = true
writeFile(filename, result) writeFile(filename, result[0])
except IOError, OSError: except IOError, OSError:
if not readSuccessful: result = "" if not readSuccessful: result = ("", -1)
else: else:
try: try:
var p = startProcess(cmd, workingDir, var p = startProcess(cmd, workingDir,
@ -50,7 +50,7 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo): string =
p.inputStream.close() p.inputStream.close()
result = p.readOutput result = p.readOutput
except IOError, OSError: except IOError, OSError:
result = "" result = ("", -1)
proc opSlurp*(file: string, info: TLineInfo, module: PSym): string = proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
try: try:

View file

@ -59,6 +59,11 @@ proc staticWalkDirImpl(path: string, relative: bool): PNode =
result.add newTree(nkPar, newIntNode(nkIntLit, k.ord), result.add newTree(nkPar, newIntNode(nkIntLit, k.ord),
newStrNode(nkStrLit, f)) newStrNode(nkStrLit, f))
proc gorgeExWrapper(a: VmArgs) {.nimcall.} =
let (s, e) = opGorge(getString(a, 0), getString(a, 1), getString(a, 2),
a.currentLineInfo)
setResult a, newTree(nkPar, newStrNode(nkStrLit, s), newIntNode(nkIntLit, e))
proc registerAdditionalOps*(c: PCtx) = proc registerAdditionalOps*(c: PCtx) =
wrap1f_math(sqrt) wrap1f_math(sqrt)
wrap1f_math(ln) wrap1f_math(ln)
@ -92,3 +97,4 @@ proc registerAdditionalOps*(c: PCtx) =
systemop getCurrentExceptionMsg systemop getCurrentExceptionMsg
registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} = registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} =
setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1))) setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1)))
systemop gorgeEx

View file

@ -3368,6 +3368,11 @@ proc staticExec*(command: string, input = "", cache = ""): string {.
## .. code-block:: nim ## .. code-block:: nim
## const stateMachine = staticExec("dfaoptimizer", "input", "0.8.0") ## const stateMachine = staticExec("dfaoptimizer", "input", "0.8.0")
proc gorgeEx*(command: string, input = "", cache = ""): tuple[output: string,
exitCode: int] =
## Same as `gorge` but also returns the precious exit code.
discard
proc `+=`*[T: SomeOrdinal|uint|uint64](x: var T, y: T) {. proc `+=`*[T: SomeOrdinal|uint|uint64](x: var T, y: T) {.
magic: "Inc", noSideEffect.} magic: "Inc", noSideEffect.}
## Increments an ordinal ## Increments an ordinal

View file

@ -3,10 +3,18 @@ import os
template getScriptDir(): string = template getScriptDir(): string =
parentDir(instantiationInfo(-1, true).filename) parentDir(instantiationInfo(-1, true).filename)
block gorge:
const const
execName = when defined(windows): "tgorge.bat" else: "sh tgorge.sh" execName = when defined(windows): "tgorge.bat" else: "./tgorge.sh"
relOutput = gorge(execName) relOutput = gorge(execName)
absOutput = gorge(getScriptDir() / execName) absOutput = gorge(getScriptDir() / execName)
doAssert relOutput == "gorge test" doAssert relOutput == "gorge test"
doAssert absOutput == "gorge test" doAssert absOutput == "gorge test"
block gorgeEx:
const
execName = when defined(windows): "tgorgeex.bat" else: "./tgorgeex.sh"
res = gorgeEx(execName)
doAssert res.output == "gorgeex test"
doAssert res.exitCode == 1

2
tests/vm/tgorgeex.bat Normal file
View file

@ -0,0 +1,2 @@
@echo gorgeex test
@exit /b 1

3
tests/vm/tgorgeex.sh Normal file
View file

@ -0,0 +1,3 @@
#!/bin/sh
echo "gorgeex test"
exit 1