diff --git a/ast/eval.go b/ast/eval.go index 7444b61..ab1a29a 100644 --- a/ast/eval.go +++ b/ast/eval.go @@ -19,6 +19,9 @@ package ast import "gitlab.com/whom/shs/log" +var CallExecutablesFromUndefFuncCalls = false +var CallExecutableToken = "l" + func (t *Token) Eval(funcs FuncTable, vars VarTable) (*Token, bool) { if t == nil { return nil, false @@ -69,13 +72,29 @@ func (t *Token) Eval(funcs FuncTable, vars VarTable) (*Token, bool) { return nil, false } + //if symbol in front of a list, could be a function call if ret.Tag == SYMBOL { f := GetFunction(ret.Inner.(string), funcs) if f == nil { - log.Log(log.DEBUG, - "could not find definition for symbol " + ret.Inner.(string), - "eval") - return nil, false + if CallExecutablesFromUndefFuncCalls { + f = GetFunction(CallExecutableToken, funcs) + if f == nil { + log.Log(log.DEBUG, "Symbol " + ret.Inner.(string) + + " has no definition in function table. Additionally " + + "the configured LoadExecutableToken is also not defined", + "eval") + return ret, false + } + + // see the use of CallFunction below + ret = &Token{Next: ret} + + } else { + log.Log(log.DEBUG, + "could not find definition for symbol " + ret.Inner.(string), + "eval") + return ret, false + } } return (*f).CallFunction(ret.Next, vars, funcs), true diff --git a/cmd/shs_repl.go b/cmd/shs_repl.go index 3485008..9900b4e 100644 --- a/cmd/shs_repl.go +++ b/cmd/shs_repl.go @@ -46,6 +46,8 @@ func setLogLvl() { } func main() { + ast.CallExecutablesFromUndefFuncCalls = true + debug := os.Getenv("SH_DEBUG_MODE") hist := os.Getenv("SH_HIST_FILE") prompt := os.Getenv("SHS_SH_PROMPT") diff --git a/go.mod b/go.mod index cbec79e..125370b 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,4 @@ module gitlab.com/whom/shs go 1.14 -require ( - github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect - gitlab.com/whom/shs/ast v0.0.0-20200628205108-baa4ce030060 // indirect - gitlab.com/whom/shs/log v0.0.0-20200628205108-baa4ce030060 // indirect - gitlab.com/whom/shs/stdlib v0.0.0-20200628205108-baa4ce030060 // indirect -) +require github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect diff --git a/go.sum b/go.sum index 8b3e7fa..454fe40 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,2 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -gitlab.com/whom/shs/ast v0.0.0-20200628205108-baa4ce030060 h1:q8VtryYSdSIeYlgJbZswVUAjy0LvmMsydQZmi1Qb+gc= -gitlab.com/whom/shs/ast v0.0.0-20200628205108-baa4ce030060/go.mod h1:uez84wOTSf9wSv/Um4BOhpsZgRNN8xkRRCZ86k7M7uU= -gitlab.com/whom/shs/log v0.0.0-20200628205108-baa4ce030060 h1:9kXRXS6ItnGKJlavvevLiIMJZVVipWlhCDwKmi+7600= -gitlab.com/whom/shs/log v0.0.0-20200628205108-baa4ce030060/go.mod h1:ns9Wf5kw0cdOZH8SDcGpUiSwlABF+XTZBJwZyzQdM/w= -gitlab.com/whom/shs/stdlib v0.0.0-20200628205108-baa4ce030060 h1:Khuo4tniRsU2fGYiRbyucS5l8UksSvfdLkNb6ivq4/A= -gitlab.com/whom/shs/stdlib v0.0.0-20200628205108-baa4ce030060/go.mod h1:noPvbzvyEtapi7VS/D/tcSBAM3cXUU+/AtkBNJWBnn4= diff --git a/stdlib/call.go b/stdlib/call.go index 9ceed6b..95e2050 100644 --- a/stdlib/call.go +++ b/stdlib/call.go @@ -29,6 +29,7 @@ import ( ) var bgProcs = make([]*exec.Cmd, 0) +var LastExitCode int func call(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { if in == nil { @@ -60,7 +61,6 @@ func call(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin - exit := 0 signalChan := make(chan os.Signal, 2) signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) @@ -74,13 +74,13 @@ func call(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { signal.Reset(os.Interrupt, syscall.SIGTERM) if err != nil { if exitError, ok := err.(*exec.ExitError); ok { - exit = exitError.ExitCode() + LastExitCode = exitError.ExitCode() } else { log.Log(log.ERR, "Execution step returned unparsable error: " + err.Error(), "call") } } - return &ast.Token{Tag: ast.NUMBER, Inner: fmt.Sprintf("%d", exit)} + return nil } func bgcall(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { @@ -127,7 +127,6 @@ func fg(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { cmd.Stdout = os.Stdout cmd.Stdin = os.Stdin - exit := 0 signalChan := make(chan os.Signal, 2) signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) @@ -141,13 +140,13 @@ func fg(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { signal.Reset(os.Interrupt, syscall.SIGTERM) if err != nil { if exitError, ok := err.(*exec.ExitError); ok { - exit = exitError.ExitCode() + LastExitCode = exitError.ExitCode() } else { - log.Log(log.ERR, "Execution step returned unparsable error: " + err.Error(), "call") + log.Log(log.ERR, "Execution step returned error: " + err.Error(), "call") } } - return &ast.Token{Tag: ast.NUMBER, Inner: fmt.Sprintf("%d", exit)} + return nil } func read_cmd(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { @@ -193,9 +192,17 @@ func read_cmd(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { close(signalChan) signal.Reset(os.Interrupt, syscall.SIGTERM) if err != nil { - log.Log(log.ERR, err.Error(), "$") + if exitError, ok := err.(*exec.ExitError); ok { + LastExitCode = exitError.ExitCode() + } else { + log.Log(log.ERR, "Execution step returned error: " + err.Error(), "$") + } } return &ast.Token{Tag: ast.STRING, Inner: out.String()} } + +func get_exit(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { + return &ast.Token{Tag: ast.NUMBER, Inner: fmt.Sprintf("%d", LastExitCode)} +} diff --git a/stdlib/stdlib.go b/stdlib/stdlib.go index 28a722c..a7971f4 100644 --- a/stdlib/stdlib.go +++ b/stdlib/stdlib.go @@ -122,6 +122,13 @@ func GenFuncTable() ast.FuncTable { TimesCalled: 0, Args: 0, }, + + "?": &ast.Function{ + Function: get_exit, + Name:"get exit code", + TimesCalled: 0, + Args: 0, + }, } return stdlib