aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jim.c53
-rw-r--r--tests/errors.tcl36
-rw-r--r--tests/stacktrace.test62
3 files changed, 83 insertions, 68 deletions
diff --git a/jim.c b/jim.c
index be5406a..4a7713a 100644
--- a/jim.c
+++ b/jim.c
@@ -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