diff options
-rw-r--r-- | jim.c | 53 | ||||
-rw-r--r-- | tests/errors.tcl | 36 | ||||
-rw-r--r-- | tests/stacktrace.test | 62 |
3 files changed, 83 insertions, 68 deletions
@@ -1160,7 +1160,7 @@ void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr)) * Results of missing quotes, braces, etc. from parsing. */ struct JimParseMissing { - int ch; /* At end of parse, ' ' if complete, '{' if braces incomplete, '"' if quotes incomplete */ + int ch; /* At end of parse, ' ' if complete or '{', '[', '"', '\\' , '{' if incomplete */ int line; /* Line number starting the missing token */ }; @@ -3188,7 +3188,7 @@ static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line) */ static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); -static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); +static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); static int JimParseCheckMissing(Jim_Interp *interp, int ch); static const Jim_ObjType scriptObjType = { @@ -3288,7 +3288,8 @@ typedef struct ScriptObj only used by Jim_EvalObj() as protection against shimmering of the currently evaluated object. */ int firstline; /* Line number of the first line */ - int linenr; /* Line number of the current line */ + int linenr; /* Error line number, if any */ + int missing; /* Missing char if script failed to parse, or ' ' if OK */ } ScriptObj; void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) @@ -3623,7 +3624,7 @@ static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, * On parse error, sets an error message and returns JIM_ERR * (Note: the object is still converted to a script, even if an error occurs) */ -static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) { int scriptTextLen; const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); @@ -3631,7 +3632,6 @@ static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) struct ScriptObj *script; ParseTokenList tokenlist; int line = 1; - int retcode = JIM_OK; /* Try to get information about filename / line number */ if (objPtr->typePtr == &sourceObjType) { @@ -3648,8 +3648,6 @@ static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) parser.tline); } - retcode = JimParseCheckMissing(interp, parser.missing.ch); - /* Add a final EOF token */ ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); @@ -3663,8 +3661,9 @@ static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) else { script->fileNameObj = interp->emptyObj; } - script->linenr = parser.missing.line; Jim_IncrRefCount(script->fileNameObj); + script->missing = parser.missing.ch; + script->linenr = parser.missing.line; ScriptObjAddTokens(interp, script, &tokenlist); @@ -3675,10 +3674,10 @@ static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) Jim_FreeIntRep(interp, objPtr); Jim_SetIntRepPtr(objPtr, script); objPtr->typePtr = &scriptObjType; - - return retcode; } +static void JimAddErrorToStack(Jim_Interp *interp, int retcode, ScriptObj *script); + /** * Returns NULL if the script failed to parse and leaves * an error message in the interp result. @@ -3686,19 +3685,28 @@ static int JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) * Otherwise returns a parsed script object. * (Note: the object is still converted to a script, even if an error occurs) */ -ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr) +ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr, int flags) { + ScriptObj *script; + if (objPtr == interp->emptyObj) { /* Avoid converting emptyObj to a script. use nullScriptObj instead. */ objPtr = interp->nullScriptObj; } if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { - if (JimSetScriptFromAny(interp, objPtr) == JIM_ERR) { - return NULL; + JimSetScriptFromAny(interp, objPtr); + } + + script = (ScriptObj *)Jim_GetIntRepPtr(objPtr); + + if (JimParseCheckMissing(interp, script->missing)) { + if ((flags & JIM_ERRMSG)) { + JimAddErrorToStack(interp, JIM_ERR, script); } + return NULL; } - return (ScriptObj *) Jim_GetIntRepPtr(objPtr); + return script; } /* ----------------------------------------------------------------------------- @@ -10465,7 +10473,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) } Jim_IncrRefCount(scriptObjPtr); /* Make sure it's shared. */ - script = Jim_GetScript(interp, scriptObjPtr); + script = Jim_GetScript(interp, scriptObjPtr, JIM_ERRMSG); if (script == NULL) { Jim_DecrRefCount(interp, scriptObjPtr); return JIM_ERR; @@ -10831,7 +10839,7 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj callFramePtr->staticVars = cmd->u.proc.staticVars; /* Remember where we were called from. */ - script = Jim_GetScript(interp, interp->currentScriptObj); + script = Jim_GetScript(interp, interp->currentScriptObj, JIM_NONE); callFramePtr->fileNameObj = script->fileNameObj; callFramePtr->line = script->linenr; @@ -11032,9 +11040,8 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename) Jim_IncrRefCount(scriptObjPtr); /* Now check the script for unmatched braces, etc. */ - if (Jim_GetScript(interp, scriptObjPtr) == NULL) { - /* EvalFile changes context, so add a stack frame here */ - JimAddErrorToStack(interp, JIM_ERR, (ScriptObj *)Jim_GetIntRepPtr(scriptObjPtr)); + /* EvalFile changes context, so add a stack frame here */ + if (Jim_GetScript(interp, scriptObjPtr, JIM_ERRMSG) == NULL) { Jim_DecrRefCount(interp, scriptObjPtr); return JIM_ERR; } @@ -11646,7 +11653,7 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv /* Do it only if there aren't shared arguments */ expr = JimGetExpression(interp, argv[2]); - incrScript = Jim_GetScript(interp, argv[3]); + incrScript = Jim_GetScript(interp, argv[3], JIM_NONE); /* Ensure proper lengths to start */ if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { @@ -12812,7 +12819,7 @@ static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar Jim_WrongNumArgs(interp, 2, argv, "script"); return JIM_ERR; } - script = Jim_GetScript(interp, argv[2]); + script = Jim_GetScript(interp, argv[2], JIM_NONE); if (script == NULL) return JIM_ERR; Jim_SetResultInt(interp, script->len); @@ -14491,7 +14498,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg Jim_WrongNumArgs(interp, 2, argv, ""); return JIM_ERR; } - Jim_SetResult(interp, Jim_GetScript(interp, interp->currentScriptObj)->fileNameObj); + Jim_SetResult(interp, Jim_GetScript(interp, interp->currentScriptObj, JIM_NONE)->fileNameObj); break; case INFO_SOURCE:{ @@ -14516,7 +14523,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg line = argv[2]->internalRep.sourceValue.lineNumber; } else if (argv[2]->typePtr == &scriptObjType) { - ScriptObj *script = Jim_GetScript(interp, argv[2]); + ScriptObj *script = Jim_GetScript(interp, argv[2], JIM_NONE); fileNameObj = script->fileNameObj; line = script->firstline; } diff --git a/tests/errors.tcl b/tests/errors.tcl index 1105dfa..0992c59 100644 --- a/tests/errors.tcl +++ b/tests/errors.tcl @@ -4,56 +4,60 @@ proc error_generator {type} { switch $type { badcmd { bogus command called - } + } badvar { set bogus - } + } error { error bogus - } + } interpbadvar { set x "some $bogus text" - } + } interpbadcmd { set x "some $bogus text" - } + } package { package require dummy - } + } source { source dummy.tcl - } + } badpackage { package require bogus - } + } returncode { return -code error failure - } + } + badproc { + error_badproc + } default { puts "Unknown type=$type" } } } - - - # line 40: Some empty lines above so that line numbers don't change proc error_caller {type {method call}} { switch $method { call { error_generator $type - } + } uplevel { uplevel 1 [list error_generator $type] - } + } eval { eval [list error_generator $type] - } + } evalstr { eval error_generator $type - } + } default { puts "Unknown method=$method" } } } + +proc error_badproc {} { + return [list missing bracket here +} diff --git a/tests/stacktrace.test b/tests/stacktrace.test index 13028a9..847297b 100644 --- a/tests/stacktrace.test +++ b/tests/stacktrace.test @@ -4,7 +4,7 @@ package require errors # Make this a proc so that the line numbers don't have to change proc main {} { set id1 0 - foreach type {badcmd badvar error interpbadvar interpbadcmd package source badpackage returncode} { + foreach type {badcmd badvar badproc error interpbadvar interpbadcmd package source badpackage returncode} { set id2 0 incr id1 foreach method {call uplevel eval evalstr} { @@ -74,38 +74,42 @@ set expected { err-2.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 47 error_caller stacktrace.test 17}} err-2.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 50 error_caller stacktrace.test 17}} err-2.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 53 error_caller stacktrace.test 17}} - err-3.1 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 44 error_caller stacktrace.test 17}} - err-3.2 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 47 error_caller stacktrace.test 17}} - err-3.3 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 50 error_caller stacktrace.test 17}} - err-3.4 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 53 error_caller stacktrace.test 17}} - err-4.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 44 error_caller stacktrace.test 17}} - err-4.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 47 error_caller stacktrace.test 17}} - err-4.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 50 error_caller stacktrace.test 17}} - err-4.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 53 error_caller stacktrace.test 17}} - err-5.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 44 error_caller stacktrace.test 17}} - err-5.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 47 error_caller stacktrace.test 17}} - err-5.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 50 error_caller stacktrace.test 17}} - err-5.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 53 error_caller stacktrace.test 17}} - err-6.1 {1 {from dummyproc + err-3.1 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 44 error_caller stacktrace.test 17}} + err-3.2 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 47 error_caller stacktrace.test 17}} + err-3.3 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 50 error_caller stacktrace.test 17}} + err-3.4 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 53 error_caller stacktrace.test 17}} + err-4.1 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 44 error_caller stacktrace.test 17}} + err-4.2 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 47 error_caller stacktrace.test 17}} + err-4.3 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 50 error_caller stacktrace.test 17}} + err-4.4 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 53 error_caller stacktrace.test 17}} + err-5.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 44 error_caller stacktrace.test 17}} + err-5.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 47 error_caller stacktrace.test 17}} + err-5.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 50 error_caller stacktrace.test 17}} + err-5.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 53 error_caller stacktrace.test 17}} + err-6.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 44 error_caller stacktrace.test 17}} + err-6.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 47 error_caller stacktrace.test 17}} + err-6.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 50 error_caller stacktrace.test 17}} + err-6.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 53 error_caller stacktrace.test 17}} + err-7.1 {1 {from dummyproc Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 44 error_caller stacktrace.test 17}} - err-6.2 {1 {from dummyproc + err-7.2 {1 {from dummyproc Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 47 error_caller stacktrace.test 17}} - err-6.3 {1 {from dummyproc + err-7.3 {1 {from dummyproc Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 50 error_caller stacktrace.test 17}} - err-6.4 {1 {from dummyproc + err-7.4 {1 {from dummyproc Can't load package dummy} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 21 error_generator errors.tcl 53 error_caller stacktrace.test 17}} - err-7.1 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 44 error_caller stacktrace.test 17}} - err-7.2 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 47 error_caller stacktrace.test 17}} - err-7.3 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 50 error_caller stacktrace.test 17}} - err-7.4 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 53 error_caller stacktrace.test 17}} - err-8.1 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 44 error_caller stacktrace.test 17}} - err-8.2 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 47 error_caller stacktrace.test 17}} - err-8.3 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 50 error_caller stacktrace.test 17}} - err-8.4 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 53 error_caller stacktrace.test 17}} - err-9.1 {1 failure {{} errors.tcl 44 error_caller stacktrace.test 17}} - err-9.2 {1 failure {{} errors.tcl 47 error_caller stacktrace.test 17}} - err-9.3 {1 failure {{} errors.tcl 50 error_caller stacktrace.test 17}} - err-9.4 {1 failure {{} errors.tcl 53 error_caller stacktrace.test 17}} + err-8.1 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 44 error_caller stacktrace.test 17}} + err-8.2 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 47 error_caller stacktrace.test 17}} + err-8.3 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 50 error_caller stacktrace.test 17}} + err-8.4 {1 {from dummyproc} {{} dummy.tcl 3 dummyproc dummy.tcl 6 {} errors.tcl 24 error_generator errors.tcl 53 error_caller stacktrace.test 17}} + err-9.1 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 44 error_caller stacktrace.test 17}} + err-9.2 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 47 error_caller stacktrace.test 17}} + err-9.3 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 50 error_caller stacktrace.test 17}} + err-9.4 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 53 error_caller stacktrace.test 17}} + err-10.1 {1 failure {{} errors.tcl 44 error_caller stacktrace.test 17}} + err-10.2 {1 failure {{} errors.tcl 47 error_caller stacktrace.test 17}} + err-10.3 {1 failure {{} errors.tcl 50 error_caller stacktrace.test 17}} + err-10.4 {1 failure {{} errors.tcl 53 error_caller stacktrace.test 17}} } # Set this to output expected results to stderr |