aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jim-package.c3
-rw-r--r--jim.c283
-rw-r--r--jim.h6
-rw-r--r--stdlib.tcl39
-rw-r--r--tcltest.tcl46
-rw-r--r--tests/error.test12
-rw-r--r--tests/event.test6
-rw-r--r--tests/infoframe.test30
-rw-r--r--tests/misc.test13
-rw-r--r--tests/stacktrace.test84
10 files changed, 234 insertions, 288 deletions
diff --git a/jim-package.c b/jim-package.c
index 1d42197..be53688 100644
--- a/jim-package.c
+++ b/jim-package.c
@@ -181,9 +181,6 @@ static int package_cmd_provide(Jim_Interp *interp, int argc, Jim_Obj *const *arg
*/
static int package_cmd_require(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- /* package require failing is important enough to add to the stack */
- interp->addStackTrace++;
-
return Jim_PackageRequire(interp, Jim_String(argv[0]), JIM_ERRMSG);
}
diff --git a/jim.c b/jim.c
index 012c0e4..908cc31 100644
--- a/jim.c
+++ b/jim.c
@@ -150,6 +150,7 @@ static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen);
static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len);
static int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_Var *var);
static Jim_Var *JimFindVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr);
+static void JimSetErrorStack(Jim_Interp *interp);
/* Fast access to the int (wide) value of an object which is known to be of int type */
#define JimWideValue(objPtr) (objPtr)->internalRep.wideValue
@@ -3748,12 +3749,10 @@ static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
objPtr->typePtr = &scriptObjType;
}
-static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script);
-
/**
* Returns the parsed script.
* Note that if there is any possibility that the script is not valid,
- * call JimScriptValid() to check
+ * call JimParseCheckMissing() to check
*/
static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
{
@@ -3769,21 +3768,6 @@ static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
return (ScriptObj *)Jim_GetIntRepPtr(objPtr);
}
-/**
- * Returns 1 if the script is valid (parsed ok), otherwise returns 0
- * and leaves an error message in the interp result.
- *
- */
-static int JimScriptValid(Jim_Interp *interp, ScriptObj *script)
-{
- if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) {
- JimAddErrorToStack(interp, script);
- return 0;
- }
- return 1;
-}
-
-
/* -----------------------------------------------------------------------------
* Commands
* ---------------------------------------------------------------------------*/
@@ -5686,7 +5670,6 @@ Jim_Interp *Jim_CreateInterp(void)
i->trueObj = Jim_NewIntObj(i, 1);
i->falseObj = Jim_NewIntObj(i, 0);
i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL, i->emptyObj);
- i->errorFileNameObj = i->emptyObj;
i->result = i->emptyObj;
i->stackTrace = Jim_NewListObj(i, NULL, 0);
i->unknown = Jim_NewStringObj(i, "unknown", -1);
@@ -5695,7 +5678,6 @@ Jim_Interp *Jim_CreateInterp(void)
i->nullScriptObj = Jim_NewEmptyStringObj(i);
i->evalFrame = &i->topEvalFrame;
Jim_IncrRefCount(i->emptyObj);
- Jim_IncrRefCount(i->errorFileNameObj);
Jim_IncrRefCount(i->result);
Jim_IncrRefCount(i->stackTrace);
Jim_IncrRefCount(i->unknown);
@@ -5718,6 +5700,7 @@ Jim_Interp *Jim_CreateInterp(void)
Jim_SetVariableStrWithStr(i, "tcl_platform(bootstrap)", "0");
Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *)));
Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide)));
+ Jim_SetVariableStr(i, "tcl_platform(stackFormat)", Jim_NewIntObj(i, 4));
return i;
}
@@ -5746,7 +5729,6 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_DecrRefCount(i, i->errorProc);
Jim_DecrRefCount(i, i->unknown);
Jim_DecrRefCount(i, i->defer);
- Jim_DecrRefCount(i, i->errorFileNameObj);
Jim_DecrRefCount(i, i->nullScriptObj);
/* This will disard any cached commands */
@@ -5924,76 +5906,75 @@ static Jim_EvalFrame *JimGetEvalFrameByProcLevel(Jim_Interp *interp, int proclev
return NULL;
}
+/* Find the proc for a given eval frame.
+ * When a proc is called (JimCallProcedure), the command name is stored in the eval frame.
+ * So to find the proc that called the code that is currently executing, we need
+ * to look back through eval frames until we find one that has a command name
+ */
+static Jim_Obj *JimProcForEvalFrame(Jim_Interp *interp, Jim_EvalFrame *frame)
+{
+ /* If at the lowest level or if this level called a proc directly, go
+ * look for the caller
+ */
+ if (frame == interp->evalFrame || (frame->cmd && frame->cmd->cmdNameObj)) {
+ Jim_EvalFrame *e;
+ for (e = frame->parent; e; e = e->parent) {
+ if (e->cmd && e->cmd->isproc && e->cmd->cmdNameObj) {
+ break;
+ }
+ }
+ if (e && e->cmd && e->cmd->cmdNameObj) {
+ return e->cmd->cmdNameObj;
+ }
+ }
+ return NULL;
+}
-static void JimResetStackTrace(Jim_Interp *interp)
+/**
+ * Append stack trace info (proc, file, line, cmd) from the eval frame
+ * to listObj
+ */
+static void JimAddStackFrame(Jim_Interp *interp, Jim_EvalFrame *frame, Jim_Obj *listObj)
{
- Jim_DecrRefCount(interp, interp->stackTrace);
- interp->stackTrace = Jim_NewListObj(interp, NULL, 0);
- Jim_IncrRefCount(interp->stackTrace);
+ Jim_Obj *procNameObj = JimProcForEvalFrame(interp, frame);
+ Jim_Obj *fileNameObj = interp->emptyObj;
+ int linenr = 1;
+
+ if (frame->scriptObj) {
+ ScriptObj *script = JimGetScript(interp, frame->scriptObj);
+ fileNameObj = script->fileNameObj;
+ linenr = script->linenr;
+ }
+
+ Jim_ListAppendElement(interp, listObj, procNameObj ? procNameObj : interp->emptyObj);
+ Jim_ListAppendElement(interp, listObj, fileNameObj);
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, linenr));
+ Jim_ListAppendElement(interp, listObj, Jim_NewListObj(interp, frame->argv, frame->argc));
}
static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj)
{
- int len;
-
/* Increment reference first in case these are the same object */
Jim_IncrRefCount(stackTraceObj);
Jim_DecrRefCount(interp, interp->stackTrace);
interp->stackTrace = stackTraceObj;
interp->errorFlag = 1;
-
- /* This is a bit ugly.
- * If the filename of the last entry of the stack trace is empty,
- * the next stack level should be added.
- */
- len = Jim_ListLength(interp, interp->stackTrace);
- if (len >= 3) {
- if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) {
- interp->addStackTrace = 1;
- }
- }
}
-static void JimAppendStackTrace(Jim_Interp *interp, const char *procname,
- Jim_Obj *fileNameObj, int linenr)
+static void JimSetErrorStack(Jim_Interp *interp)
{
- if (strcmp(procname, "unknown") == 0) {
- procname = "";
- }
- if (!*procname && !Jim_Length(fileNameObj)) {
- /* No useful info here */
- return;
- }
-
- if (Jim_IsShared(interp->stackTrace)) {
- Jim_DecrRefCount(interp, interp->stackTrace);
- interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace);
- Jim_IncrRefCount(interp->stackTrace);
- }
-
- /* If we have no procname but the previous element did, merge with that frame */
- if (!*procname && Jim_Length(fileNameObj)) {
- /* Just a filename. Check the previous entry */
- int len = Jim_ListLength(interp, interp->stackTrace);
+ if (!interp->errorFlag) {
+ int i;
+ Jim_Obj *stackTrace = Jim_NewListObj(interp, NULL, 0);
- if (len >= 3) {
- Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3);
- if (Jim_Length(objPtr)) {
- /* Yes, the previous level had procname */
- objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2);
- if (Jim_Length(objPtr) == 0) {
- /* But no filename, so merge the new info with that frame */
- ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0);
- ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0);
- return;
- }
+ for (i = 0; i <= interp->procLevel; i++) {
+ Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, -i);
+ if (frame) {
+ JimAddStackFrame(interp, frame, stackTrace);
}
}
+ JimSetStackTrace(interp, stackTrace);
}
-
- Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, procname, -1));
- Jim_ListAppendElement(interp, interp->stackTrace, fileNameObj);
- Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewIntObj(interp, linenr));
}
int Jim_SetAssocData(Jim_Interp *interp, const char *key, Jim_InterpDeleteProc * delProc,
@@ -10759,10 +10740,7 @@ static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
}
interp->evalDepth++;
prevPrivData = interp->cmdPrivData;
- /* XXX We should consider creating a struct here (on the stack) with a back pointer
- * so that the entire call chain can be walked. This would allow 'info frame' to walk
- * the full call chain, not just call frames
- */
+
tailcall:
interp->evalFrame->argc = objc;
@@ -10780,6 +10758,9 @@ tailcall:
interp->cmdPrivData = cmdPtr->u.native.privData;
retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
}
+ if (retcode == JIM_ERR) {
+ JimSetErrorStack(interp);
+ }
}
if (tailcallObj) {
@@ -10788,6 +10769,10 @@ tailcall:
tailcallObj = NULL;
}
+ /* These are now invalid */
+ interp->evalFrame->argc = 0;
+ interp->evalFrame->argv = NULL;
+
/* If a tailcall is returned for this frame, loop to invoke the new command */
if (retcode == JIM_EVAL && interp->framePtr->tailcallObj) {
JimDecrCmdRefCount(interp, cmdPtr);
@@ -10811,6 +10796,10 @@ tailcall:
out:
JimDecrCmdRefCount(interp, cmdPtr);
+ if (retcode == JIM_ERR) {
+ JimSetErrorStack(interp);
+ }
+
if (interp->framePtr->tailcallObj) {
/* We might have skipped invoking a tailcall, perhaps because of an error
* in defer handling so cleanup now
@@ -10870,41 +10859,6 @@ int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *co
return ret;
}
-static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script)
-{
- if (!interp->errorFlag) {
- /* This is the first error, so save the file/line information and reset the stack */
- interp->errorFlag = 1;
- Jim_IncrRefCount(script->fileNameObj);
- Jim_DecrRefCount(interp, interp->errorFileNameObj);
- interp->errorFileNameObj = script->fileNameObj;
- interp->errorLine = script->linenr;
-
- JimResetStackTrace(interp);
- /* Always add a level where the error first occurs */
- interp->addStackTrace++;
- }
-
- /* Now if this is an "interesting" level, add it to the stack trace */
- if (interp->addStackTrace > 0) {
- /* Add the stack info for the current level */
-
- JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr);
-
- /* Note: if we didn't have a filename for this level,
- * don't clear the addStackTrace flag
- * so we can pick it up at the next level
- */
- if (Jim_Length(script->fileNameObj)) {
- interp->addStackTrace = 0;
- }
-
- Jim_DecrRefCount(interp, interp->errorProc);
- interp->errorProc = interp->emptyObj;
- Jim_IncrRefCount(interp->errorProc);
- }
-}
-
static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Obj **objPtrPtr)
{
Jim_Obj *objPtr;
@@ -11060,7 +11014,6 @@ static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
JimPanic((Jim_IsList(listPtr) == 0, "JimEvalObjList() invoked on non-list."));
- /* XXX should we pass listPtr as scriptObj here? */
JimPushEvalFrame(interp, &frame, NULL);
if (listPtr->internalRep.listValue.len) {
@@ -11099,7 +11052,8 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
Jim_IncrRefCount(scriptObjPtr); /* Make sure it's shared. */
script = JimGetScript(interp, scriptObjPtr);
- if (!JimScriptValid(interp, script)) {
+ if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) {
+ JimSetErrorStack(interp);
Jim_DecrRefCount(interp, scriptObjPtr);
return JIM_ERR;
}
@@ -11151,6 +11105,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
JimPushEvalFrame(interp, &frame, scriptObjPtr);
+ /* Collect a new error stack trace if an error occurs */
interp->errorFlag = 0;
argv = sargv;
@@ -11301,12 +11256,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
/* Possibly add to the error stack trace */
if (retcode == JIM_ERR) {
- JimAddErrorToStack(interp, script);
- }
- /* Propagate the addStackTrace value through 'return -code error' */
- else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) {
- /* No need to add stack trace */
- interp->addStackTrace = 0;
+ JimSetErrorStack(interp);
}
JimPopEvalFrame(interp);
@@ -11538,12 +11488,6 @@ badargset:
interp->returnLevel = 0;
}
}
- else if (retcode == JIM_ERR) {
- interp->addStackTrace++;
- Jim_DecrRefCount(interp, interp->errorProc);
- interp->errorProc = argv[0];
- Jim_IncrRefCount(interp->errorProc);
- }
interp->procLevel--;
return retcode;
@@ -11639,10 +11583,6 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
interp->returnLevel = 0;
}
}
- if (retcode == JIM_ERR) {
- /* EvalFile changes context, so add a stack frame here */
- interp->addStackTrace++;
- }
Jim_DecrRefCount(interp, scriptObjPtr);
@@ -11957,54 +11897,36 @@ static int JimInfoFrame(Jim_Interp *interp, Jim_Obj *levelObjPtr, Jim_Obj **objP
long level;
if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
- Jim_EvalFrame *targetEvalFrame = JimGetEvalFrameByProcLevel(interp, level);
- if (targetEvalFrame) {
+ Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, level);
+ if (frame) {
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
- int linenr;
- Jim_Obj *fileNameObj;
- /*Jim_EvalFrame *procEvalFrame;*/
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "source", -1));
- if (targetEvalFrame->scriptObj) {
- ScriptObj *script = JimGetScript(interp, targetEvalFrame->scriptObj);
- linenr = script->linenr;
- fileNameObj = script->fileNameObj;
+ if (frame->scriptObj) {
+ ScriptObj *script = JimGetScript(interp, frame->scriptObj);
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "line", -1));
- Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, linenr));
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, script->linenr));
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "file", -1));
- Jim_ListAppendElement(interp, listObj, fileNameObj);
+ Jim_ListAppendElement(interp, listObj, script->fileNameObj);
}
#ifndef JIM_NO_INTROSPECTION
{
- Jim_Obj *cmdObj = Jim_NewListObj(interp, targetEvalFrame->argv, targetEvalFrame->argc);
+ Jim_Obj *cmdObj = Jim_NewListObj(interp, frame->argv, frame->argc);
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "cmd", -1));
Jim_ListAppendElement(interp, listObj, cmdObj);
}
#endif
- /* XXX explain how this works */
- if (targetEvalFrame == interp->evalFrame || (targetEvalFrame->cmd && targetEvalFrame->cmd->isproc && targetEvalFrame->cmd->cmdNameObj)) {
- Jim_EvalFrame *e, *p = NULL;
- for (e = targetEvalFrame->parent; e; e = e->parent) {
- if (e->cmd && e->cmd->isproc && e->cmd->cmdNameObj) {
- p = e;
- break;
- }
- }
- if (p && p->level) {
- if (p->cmd && p->cmd->isproc) {
- if (p->cmd->cmdNameObj) {
- Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "proc", -1));
- Jim_ListAppendElement(interp, listObj, p->cmd->cmdNameObj);
- }
- }
+ {
+ Jim_Obj *procNameObj = JimProcForEvalFrame(interp, frame);
+ if (procNameObj) {
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "proc", -1));
+ Jim_ListAppendElement(interp, listObj, procNameObj);
}
}
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "level", -1));
- Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, interp->framePtr->level - targetEvalFrame->framePtr->level));
- Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "proclevel", -1));
- Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetEvalFrame->procLevel));
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, interp->framePtr->level - frame->framePtr->level));
*objPtrPtr = listObj;
return JIM_OK;
@@ -13733,10 +13655,6 @@ static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
}
- if (rc == JIM_ERR) {
- /* eval is "interesting", so add a stack frame here */
- interp->addStackTrace++;
- }
return rc;
}
@@ -13844,6 +13762,37 @@ static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const
return JimBreakContinueHelper(interp, argc, argv, JIM_CONTINUE);
}
+/* [stacktrace] */
+static int Jim_StacktraceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_Obj *listObj;
+ int i;
+ jim_wide skip = 0;
+ jim_wide last = 0;
+
+ if (argc > 1) {
+ if (Jim_GetWideExpr(interp, argv[1], &skip) != JIM_OK) {
+ return JIM_ERR;
+ }
+ }
+ if (argc > 2) {
+ if (Jim_GetWideExpr(interp, argv[2], &last) != JIM_OK) {
+ return JIM_ERR;
+ }
+ }
+
+ listObj = Jim_NewListObj(interp, NULL, 0);
+ for (i = skip; i <= interp->procLevel; i++) {
+ Jim_EvalFrame *frame = JimGetEvalFrameByProcLevel(interp, -i);
+ if (frame->procLevel < last) {
+ break;
+ }
+ JimAddStackFrame(interp, frame, listObj);
+ }
+ Jim_SetResult(interp, listObj);
+ return JIM_OK;
+}
+
/* [return] */
static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -14851,7 +14800,7 @@ wrongargs:
}
else {
exitCode = Jim_EvalObj(interp, argv[idx]);
- /* Don't want any caught error included in a later stack trace */
+ /* Once caught, a new error will set a stack trace again */
interp->errorFlag = 0;
}
interp->signal_level -= sig;
@@ -16117,7 +16066,6 @@ static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
JimSetStackTrace(interp, argv[2]);
return JIM_ERR;
}
- interp->addStackTrace++;
return JIM_ERR;
}
@@ -16443,6 +16391,7 @@ static const struct {
{"local", Jim_LocalCoreCommand},
{"upcall", Jim_UpcallCoreCommand},
{"apply", Jim_ApplyCoreCommand},
+ {"stacktrace", Jim_StacktraceCoreCommand},
{NULL, NULL},
};
diff --git a/jim.h b/jim.h
index a8d8cbb..0d5ab0a 100644
--- a/jim.h
+++ b/jim.h
@@ -540,9 +540,9 @@ typedef struct Jim_PrngState {
* ---------------------------------------------------------------------------*/
typedef struct Jim_Interp {
Jim_Obj *result; /* object returned by the last command called. */
- int errorLine; /* Error line where an error occurred. */
- Jim_Obj *errorFileNameObj; /* Error file where an error occurred. */
- int addStackTrace; /* > 0 if a level should be added to the stack trace */
+ int unused_errorLine; /* Error line where an error occurred. */
+ Jim_Obj *unused_errorFileNameObj; /* Error file where an error occurred. */
+ int unused_addStackTrace;
int maxCallFrameDepth; /* Used for infinite loop detection. */
int maxEvalDepth; /* Used for infinite loop detection. */
int evalDepth; /* Current eval depth */
diff --git a/stdlib.tcl b/stdlib.tcl
index 5945185..289acbf 100644
--- a/stdlib.tcl
+++ b/stdlib.tcl
@@ -33,39 +33,28 @@ proc function {value} {
return $value
}
-# Returns a live stack trace as a list of proc filename line ...
-# with 3 entries for each stack frame (proc),
-# (deepest level first)
-proc stacktrace {{skip 0}} {
- set frames {}
- loop level $skip+1 [info frame] {
- set frame [info frame -$level]
- if {[dict exists $frame proc]} {
- lappend frames $frame(proc) $frame(file) $frame(line)
- }
- }
- return $frames
-}
-
# Returns a human-readable version of a stack trace
proc stackdump {stacktrace} {
set lines {}
- foreach {l f p} [lreverse $stacktrace] {
+ lappend lines "Traceback (most recent call last):"
+ foreach {cmd l f p} [lreverse $stacktrace] {
set line {}
- if {$p ne ""} {
- append line "in procedure '$p' "
- if {$f ne ""} {
- append line "called "
- }
- }
if {$f ne ""} {
- append line "at file \"$f\", line $l"
+ append line " File \"$f\", line $l"
+ }
+ if {$p ne ""} {
+ append line ", in $p"
}
if {$line ne ""} {
lappend lines $line
+ if {$cmd ne ""} {
+ lappend lines " $cmd"
+ }
}
}
- join $lines \n
+ if {[llength $lines] > 1} {
+ return [join $lines \n]
+ }
}
# Add the given script to $jim::defer, to be evaluated when the current
@@ -81,10 +70,8 @@ proc errorInfo {msg {stacktrace ""}} {
if {$stacktrace eq ""} {
# By default add the stack backtrace and the live stacktrace
set stacktrace [info stacktrace]
- # omit the procedure 'errorInfo' from the stack
- lappend stacktrace {*}[stacktrace 1]
}
- lassign $stacktrace p f l
+ lassign $stacktrace p f l cmd
if {$f ne ""} {
set result "$f:$l: Error: "
}
diff --git a/tcltest.tcl b/tcltest.tcl
index 2b8d3d8..9478dcd 100644
--- a/tcltest.tcl
+++ b/tcltest.tcl
@@ -78,11 +78,20 @@ proc skiptest {{msg {}}} {
# Also convert proc name ::a into a for compatibility between Tcl and Jim
proc basename-stacktrace {stacktrace} {
set result {}
- foreach {p f l} $stacktrace {
- if {[string match ::* $p]} {
+ foreach {p f l cmd} $stacktrace {
+ if {[string match *tcltest-* $f]} {
+ #break
+ }
+ if {$p eq "::tcltest::RunTest"} {
+ set p test
+ } elseif {[string match ::* $p]} {
set p [string range $p 2 end]
}
- lappend result $p [file tail $f] $l
+ set cmd [string map [list \n \\n] $cmd]
+ if {[string length $cmd] > 20} {
+ set cmd [string range $cmd 0 20]...
+ }
+ lappend result $p [file tail $f] $l $cmd
}
return $result
}
@@ -101,28 +110,23 @@ if {[catch {info version}]} {
proc testreport {} {
::tcltest::cleanupTests
}
- proc stacktrace {{skip 0}} {
- set trace {}
- # Need to skip info frame 0 and this (stacktrace) level
- incr skip 1
- set maxlevel [info frame]
- for {set level $skip} {$level < $maxlevel} {incr level} {
+ proc stacktrace {{skip 0} {last 0}} {
+ set frames {}
+ incr skip
+ for {set level $skip} {$level < [info frame] - $last} {incr level} {
set frame [info frame -$level]
- if {[dict get $frame type] eq "source" && [dict exists $frame proc]} {
+ puts $frame
+ if {[dict get $frame type] ne "source"} {
+ continue
+ }
+ if {[dict exists $frame proc]} {
set proc [dict get $frame proc]
- # make it look like it is running under Jim tcltest
- if {$proc eq "::tcltest::RunTest"} {
- set proc test
- } else {
- set proc [string range $proc 2 end]
- }
- lappend trace $proc [dict get $frame file] [dict get $frame line]
- if {$proc eq "test"} {
- break
- }
+ } else {
+ set proc ""
}
+ lappend frames $proc [dict get $frame file] [dict get $frame line] [dict get $frame cmd]
}
- return $trace
+ return $frames
}
return
}
diff --git a/tests/error.test b/tests/error.test
index d226900..5669b7b 100644
--- a/tests/error.test
+++ b/tests/error.test
@@ -11,12 +11,12 @@ proc b {} {
}
}
-test error-1.1 "Rethrow caught error" {
+test error-1.1 {Rethrow caught error} -body {
set rc [catch {b} msg]
#puts stderr "error-1.1\n[errorInfo $msg]\n"
list $rc $msg [basename-stacktrace [info stacktrace]]
-} {1 {error thrown from a} {{} error.test 4 a error.test 8 b error.test 15}}
+} -result {1 {error thrown from a} {a error.test 4 error\ \{error\ thrown\ f... b error.test 8 a test error.test 15 b {} error.test 14 test\ error-1.1\ \{Rethr...}}
proc c {} {
a
@@ -30,22 +30,22 @@ proc e {} {
d
}
-test error-1.2 "Modify stacktrace" {
+test error-1.2 {Modify stacktrace} -body {
set rc [catch {e} msg]
set st [info stacktrace]
# Now elide one entry from the stacktrace
#puts [errorInfo $msg]
set newst {}
- foreach {p f l} $st {
+ foreach {p f l cmd} $st {
if {$p ne "d"} {
- lappend newst $p $f $l
+ lappend newst $p $f $l $cmd
}
}
# Now rethrow with the new stack
set rc [catch {error $msg $newst} msg]
#puts [errorInfo $msg]
basename-stacktrace [info stacktrace]
-} {{} error.test 4 a error.test 22 c error.test 26 e error.test 34}
+} -result {a error.test 4 error\ \{error\ thrown\ f... c error.test 22 a e error.test 30 d test error.test 34 e {} error.test 33 test\ error-1.2\ \{Modif...}
# Package should be able to invoke exit, which should exit if not caught
test error-2.1 "Exit from package" {
diff --git a/tests/event.test b/tests/event.test
index 278f4e3..b95f76e 100644
--- a/tests/event.test
+++ b/tests/event.test
@@ -92,7 +92,11 @@ test event-7.4 {bgerror throws an error} -constraints jim -body {
update
}
} -result {stdin:3: Error: inside bgerror
-at file "stdin", line 3}
+Traceback (most recent call last):
+ File "stdin", line 6
+ bgerror err1
+ File "stdin", line 3, in bgerror
+ error {inside bgerror}}
# end of bgerror tests
catch {rename bgerror {}}
diff --git a/tests/infoframe.test b/tests/infoframe.test
index e8544b1..ef827bc 100644
--- a/tests/infoframe.test
+++ b/tests/infoframe.test
@@ -1,44 +1,50 @@
source [file dirname [info script]]/testing.tcl
-proc a {n} {
+proc a {n args} {
if {$n eq "trace"} {
- return [basename-stacktrace [stacktrace]]
+ return [basename-stacktrace [stacktrace {*}$args]]
}
set frame [info frame $n]
if {![dict exists $frame proc]} {
dict set frame proc {}
}
- basename-stacktrace [list [dict get $frame proc] [file tail [dict get $frame file]] [dict get $frame line]]
+ basename-stacktrace [list [dict get $frame proc] [file tail [dict get $frame file]] [dict get $frame line] [dict get $frame cmd]]
}
-proc b {n} {
- a $n
+proc b {args} {
+ a {*}$args
}
-proc c {n} {
- b $n
+proc c {args} {
+ b {*}$args
}
# --- Don't change line numbers above
test info-frame-1.1 {Current command} -body {
c 0
-} -result {a infoframe.test 7}
+} -result {a infoframe.test 7 {info frame 0}}
test info-frame-1.2 {Current Proc} -body {
c -1
-} -result {b infoframe.test 15}
+} -result {b infoframe.test 15 {a -1}}
test info-frame-1.3 Caller -body {
c -2
-} -result {c infoframe.test 19}
+} -result {c infoframe.test 19 {b -2}}
test info-frame-1.4 {Caller of Caller} -body {
c -3
-} -result {test infoframe.test 37}
+} -result {test infoframe.test 37 {c -3}}
test stacktrace-1.1 {Full stack trace} -body {
c trace
-} -result {a infoframe.test 5 b infoframe.test 15 c infoframe.test 19 test infoframe.test 41}
+} -result {a infoframe.test 5 stacktrace b infoframe.test 15 {a trace} c infoframe.test 19 {b trace} test infoframe.test 41 {c trace} {} infoframe.test 40 test\ stacktrace-1.1\ \{...}
+
+test stacktrace-1.2 {Stack trace with limited depth} -body {
+ # This will limit the stack trace to omit "this" level and below
+ c trace 0 [info frame]
+} -result {a infoframe.test 5 {stacktrace 0 2} b infoframe.test 15 {a trace 0 2} c infoframe.test 19 {b trace 0 2}}
+
testreport
diff --git a/tests/misc.test b/tests/misc.test
index a997057..cffb0a6 100644
--- a/tests/misc.test
+++ b/tests/misc.test
@@ -301,25 +301,24 @@ test catch-1.9 "catch no error has no -errorinfo" {
list $rc [info exists opts(-errorinfo)]
} {0 0}
-test return-1.1 "return can rethrow an error" {
+test return-1.1 {return can rethrow an error} -body {
proc a {} { error "from a" }
proc b {} { catch {a} msg opts; return {*}$opts $msg }
set rc [catch {b} msg opts]
- list $rc $msg [llength $opts(-errorinfo)]
-} {1 {from a} 9}
+ list $rc $msg [basename-stacktrace $opts(-errorinfo)]
+} -result {1 {from a} {a misc.test 305 {error {from a}} b misc.test 306 a test misc.test 307 b {} misc.test 304 test\ return-1.1\ \{retu...}}
-test return-1.2 "error can rethrow an error" {
+test return-1.2 {error can rethrow an error} -body {
proc a {} { error "from a" }
proc b {} { catch {a} msg; error $msg [info stacktrace] }
set rc [catch {b} msg opts]
- list $rc $msg [llength $opts(-errorinfo)]
-} {1 {from a} 9}
+ list $rc $msg [basename-stacktrace $opts(-errorinfo)]
+} -result {1 {from a} {a misc.test 312 {error {from a}} b misc.test 313 a test misc.test 314 b {} misc.test 311 test\ return-1.2\ \{erro...}}
test return-1.3 "return can rethrow no error" {
proc a {} { return "from a" }
proc b {} { catch {a} msg opts; return {*}$opts $msg }
set rc [catch {b} msg opts]
- #list $rc $msg [llength $opts(-errorinfo)]
list $rc $msg [info exists opts(-errorinfo)]
} {0 {from a} 0}
diff --git a/tests/stacktrace.test b/tests/stacktrace.test
index 9dcc657..4d6b432 100644
--- a/tests/stacktrace.test
+++ b/tests/stacktrace.test
@@ -34,13 +34,13 @@ proc main {} {
error "from unknown"
}
- test err-10.1 "Stacktrace on error from unknown (badcmd, call)" {
+ test err-10.1 {Stacktrace on error from unknown (badcmd, call)} -body {
set rc [catch {error_caller badcmd call} msg]
#puts stderr "err-10.1\n[errorInfo $msg]\n"
#puts stderr "\terr-10.1 {[list $rc $msg [basename-stacktrace [info stacktrace]]]}"
list $rc $msg [basename-stacktrace [info stacktrace]]
- } {1 {from unknown} {{} stacktrace.test 34 {} errors.tcl 6 error_generator errors.tcl 44 error_caller stacktrace.test 38}}
+ } -result {1 {from unknown} {unknown stacktrace.test 34 {error {from unknown}} error_generator errors.tcl 6 {unknown bogus command...} error_caller errors.tcl 44 {error_generator badcm...} test stacktrace.test 38 {error_caller badcmd c...} main stacktrace.test 37 test\ err-10.1\ \{Stackt... {} stacktrace.test 127 main}}
rename unknown ""
@@ -74,50 +74,50 @@ proc main {} {
}
set expected {
- err-1.1 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 44 error_caller stacktrace.test 25}}
- err-1.2 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 47 error_caller stacktrace.test 25}}
- err-1.3 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 50 error_caller stacktrace.test 25}}
- err-1.4 {1 {invalid command name "bogus"} {{} errors.tcl 6 error_generator errors.tcl 53 error_caller stacktrace.test 25}}
- err-2.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 44 error_caller stacktrace.test 25}}
- err-2.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 47 error_caller stacktrace.test 25}}
- err-2.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 50 error_caller stacktrace.test 25}}
- err-2.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 9 error_generator errors.tcl 53 error_caller stacktrace.test 25}}
- err-3.1 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 44 error_caller stacktrace.test 25}}
- err-3.2 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 47 error_caller stacktrace.test 25}}
- err-3.3 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 50 error_caller stacktrace.test 25}}
- err-3.4 {1 {unmatched "["} {{} errors.tcl 62 error_badproc errors.tcl 33 error_generator errors.tcl 53 error_caller stacktrace.test 25}}
- err-4.1 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 44 error_caller stacktrace.test 25}}
- err-4.2 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 47 error_caller stacktrace.test 25}}
- err-4.3 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 50 error_caller stacktrace.test 25}}
- err-4.4 {1 bogus {{} errors.tcl 12 error_generator errors.tcl 53 error_caller stacktrace.test 25}}
- err-5.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 44 error_caller stacktrace.test 25}}
- err-5.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 47 error_caller stacktrace.test 25}}
- err-5.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 50 error_caller stacktrace.test 25}}
- err-5.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 15 error_generator errors.tcl 53 error_caller stacktrace.test 25}}
- err-6.1 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 44 error_caller stacktrace.test 25}}
- err-6.2 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 47 error_caller stacktrace.test 25}}
- err-6.3 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 50 error_caller stacktrace.test 25}}
- err-6.4 {1 {can't read "bogus": no such variable} {{} errors.tcl 18 error_generator errors.tcl 53 error_caller stacktrace.test 25}}
+ err-1.1 {1 {invalid command name "bogus"} {error_generator errors.tcl 6 {} error_caller errors.tcl 44 {error_generator badcm...} test stacktrace.test 25 {error_caller badcmd c...} main stacktrace.test 24 test\ err-1.1\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-1.2 {1 {invalid command name "bogus"} {error_generator errors.tcl 6 {} error_caller errors.tcl 47 {error_generator badcm...} test stacktrace.test 25 {error_caller badcmd u...} main stacktrace.test 24 test\ err-1.2\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-1.3 {1 {invalid command name "bogus"} {error_generator errors.tcl 6 {} error_caller errors.tcl 50 {error_generator badcm...} test stacktrace.test 25 {error_caller badcmd e...} main stacktrace.test 24 test\ err-1.3\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-1.4 {1 {invalid command name "bogus"} {error_generator errors.tcl 6 {} error_caller {} 1 {error_generator badcm...} test stacktrace.test 25 {error_caller badcmd e...} main stacktrace.test 24 test\ err-1.4\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-2.1 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 9 {set bogus} error_caller errors.tcl 44 {error_generator badva...} test stacktrace.test 25 {error_caller badvar c...} main stacktrace.test 24 test\ err-2.1\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-2.2 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 9 {set bogus} error_caller errors.tcl 47 {error_generator badva...} test stacktrace.test 25 {error_caller badvar u...} main stacktrace.test 24 test\ err-2.2\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-2.3 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 9 {set bogus} error_caller errors.tcl 50 {error_generator badva...} test stacktrace.test 25 {error_caller badvar e...} main stacktrace.test 24 test\ err-2.3\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-2.4 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 9 {set bogus} error_caller {} 1 {error_generator badva...} test stacktrace.test 25 {error_caller badvar e...} main stacktrace.test 24 test\ err-2.4\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-3.1 {1 {unmatched "["} {error_generator errors.tcl 33 error_badproc error_generator errors.tcl 33 error_badproc error_caller errors.tcl 44 {error_generator badpr...} test stacktrace.test 25 {error_caller badproc ...} main stacktrace.test 24 test\ err-3.1\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-3.2 {1 {unmatched "["} {error_generator errors.tcl 33 error_badproc error_generator errors.tcl 33 error_badproc error_caller errors.tcl 47 {error_generator badpr...} test stacktrace.test 25 {error_caller badproc ...} main stacktrace.test 24 test\ err-3.2\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-3.3 {1 {unmatched "["} {error_generator errors.tcl 33 error_badproc error_generator errors.tcl 33 error_badproc error_caller errors.tcl 50 {error_generator badpr...} test stacktrace.test 25 {error_caller badproc ...} main stacktrace.test 24 test\ err-3.3\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-3.4 {1 {unmatched "["} {error_generator errors.tcl 33 error_badproc error_generator errors.tcl 33 error_badproc error_caller {} 1 {error_generator badpr...} test stacktrace.test 25 {error_caller badproc ...} main stacktrace.test 24 test\ err-3.4\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-4.1 {1 bogus {error_generator errors.tcl 12 {error bogus} error_caller errors.tcl 44 {error_generator error...} test stacktrace.test 25 {error_caller error ca...} main stacktrace.test 24 test\ err-4.1\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-4.2 {1 bogus {error_generator errors.tcl 12 {error bogus} error_caller errors.tcl 47 {error_generator error...} test stacktrace.test 25 {error_caller error up...} main stacktrace.test 24 test\ err-4.2\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-4.3 {1 bogus {error_generator errors.tcl 12 {error bogus} error_caller errors.tcl 50 {error_generator error...} test stacktrace.test 25 {error_caller error ev...} main stacktrace.test 24 test\ err-4.3\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-4.4 {1 bogus {error_generator errors.tcl 12 {error bogus} error_caller {} 1 {error_generator error...} test stacktrace.test 25 {error_caller error ev...} main stacktrace.test 24 test\ err-4.4\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-5.1 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 15 {} error_caller errors.tcl 44 {error_generator inter...} test stacktrace.test 25 {error_caller interpba...} main stacktrace.test 24 test\ err-5.1\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-5.2 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 15 {} error_caller errors.tcl 47 {error_generator inter...} test stacktrace.test 25 {error_caller interpba...} main stacktrace.test 24 test\ err-5.2\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-5.3 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 15 {} error_caller errors.tcl 50 {error_generator inter...} test stacktrace.test 25 {error_caller interpba...} main stacktrace.test 24 test\ err-5.3\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-5.4 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 15 {} error_caller {} 1 {error_generator inter...} test stacktrace.test 25 {error_caller interpba...} main stacktrace.test 24 test\ err-5.4\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-6.1 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 18 {} error_caller errors.tcl 44 {error_generator inter...} test stacktrace.test 25 {error_caller interpba...} main stacktrace.test 24 test\ err-6.1\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-6.2 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 18 {} error_caller errors.tcl 47 {error_generator inter...} test stacktrace.test 25 {error_caller interpba...} main stacktrace.test 24 test\ err-6.2\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-6.3 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 18 {} error_caller errors.tcl 50 {error_generator inter...} test stacktrace.test 25 {error_caller interpba...} main stacktrace.test 24 test\ err-6.3\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-6.4 {1 {can't read "bogus": no such variable} {error_generator errors.tcl 18 {} error_caller {} 1 {error_generator inter...} test stacktrace.test 25 {error_caller interpba...} main stacktrace.test 24 test\ err-6.4\ \{Stacktr... {} stacktrace.test 127 main}}
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 25}}
+Can't load package dummy} {dummyproc dummy.tcl 3 error\ \{from\ dummyproc... error_generator dummy.tcl 6 dummyproc error_caller errors.tcl 44 {error_generator packa...} test stacktrace.test 25 {error_caller package ...} main stacktrace.test 24 test\ err-7.1\ \{Stacktr... {} stacktrace.test 127 main}}
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 25}}
+Can't load package dummy} {dummyproc dummy.tcl 3 error\ \{from\ dummyproc... error_generator dummy.tcl 6 dummyproc error_caller errors.tcl 47 {error_generator packa...} test stacktrace.test 25 {error_caller package ...} main stacktrace.test 24 test\ err-7.2\ \{Stacktr... {} stacktrace.test 127 main}}
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 25}}
+Can't load package dummy} {dummyproc dummy.tcl 3 error\ \{from\ dummyproc... error_generator dummy.tcl 6 dummyproc error_caller errors.tcl 50 {error_generator packa...} test stacktrace.test 25 {error_caller package ...} main stacktrace.test 24 test\ err-7.3\ \{Stacktr... {} stacktrace.test 127 main}}
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 25}}
- 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 25}}
- 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 25}}
- 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 25}}
- 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 25}}
- err-9.1 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 44 error_caller stacktrace.test 25}}
- err-9.2 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 47 error_caller stacktrace.test 25}}
- err-9.3 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 50 error_caller stacktrace.test 25}}
- err-9.4 {1 {Can't load package bogus} {{} errors.tcl 27 error_generator errors.tcl 53 error_caller stacktrace.test 25}}
- err-10.1 {1 failure {{} errors.tcl 44 error_caller stacktrace.test 25}}
- err-10.2 {1 failure {{} errors.tcl 47 error_caller stacktrace.test 25}}
- err-10.3 {1 failure {{} errors.tcl 50 error_caller stacktrace.test 25}}
- err-10.4 {1 failure {{} errors.tcl 53 error_caller stacktrace.test 25}}
+Can't load package dummy} {dummyproc dummy.tcl 3 error\ \{from\ dummyproc... error_generator dummy.tcl 6 dummyproc error_caller {} 1 {error_generator packa...} test stacktrace.test 25 {error_caller package ...} main stacktrace.test 24 test\ err-7.4\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-8.1 {1 {from dummyproc} {dummyproc dummy.tcl 3 error\ \{from\ dummyproc... error_generator dummy.tcl 6 dummyproc error_caller errors.tcl 44 {error_generator sourc...} test stacktrace.test 25 {error_caller source c...} main stacktrace.test 24 test\ err-8.1\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-8.2 {1 {from dummyproc} {dummyproc dummy.tcl 3 error\ \{from\ dummyproc... error_generator dummy.tcl 6 dummyproc error_caller errors.tcl 47 {error_generator sourc...} test stacktrace.test 25 {error_caller source u...} main stacktrace.test 24 test\ err-8.2\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-8.3 {1 {from dummyproc} {dummyproc dummy.tcl 3 error\ \{from\ dummyproc... error_generator dummy.tcl 6 dummyproc error_caller errors.tcl 50 {error_generator sourc...} test stacktrace.test 25 {error_caller source e...} main stacktrace.test 24 test\ err-8.3\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-8.4 {1 {from dummyproc} {dummyproc dummy.tcl 3 error\ \{from\ dummyproc... error_generator dummy.tcl 6 dummyproc error_caller {} 1 {error_generator sourc...} test stacktrace.test 25 {error_caller source e...} main stacktrace.test 24 test\ err-8.4\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-9.1 {1 {Can't load package bogus} {error_generator errors.tcl 27 {package require bogus...} error_caller errors.tcl 44 {error_generator badpa...} test stacktrace.test 25 {error_caller badpacka...} main stacktrace.test 24 test\ err-9.1\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-9.2 {1 {Can't load package bogus} {error_generator errors.tcl 27 {package require bogus...} error_caller errors.tcl 47 {error_generator badpa...} test stacktrace.test 25 {error_caller badpacka...} main stacktrace.test 24 test\ err-9.2\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-9.3 {1 {Can't load package bogus} {error_generator errors.tcl 27 {package require bogus...} error_caller errors.tcl 50 {error_generator badpa...} test stacktrace.test 25 {error_caller badpacka...} main stacktrace.test 24 test\ err-9.3\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-9.4 {1 {Can't load package bogus} {error_generator errors.tcl 27 {package require bogus...} error_caller {} 1 {error_generator badpa...} test stacktrace.test 25 {error_caller badpacka...} main stacktrace.test 24 test\ err-9.4\ \{Stacktr... {} stacktrace.test 127 main}}
+ err-10.1 {1 failure {error_caller errors.tcl 44 {error_generator retur...} test stacktrace.test 25 {error_caller returnco...} main stacktrace.test 24 test\ err-10.1\ \{Stackt... {} stacktrace.test 127 main}}
+ err-10.2 {1 failure {error_caller errors.tcl 47 {error_generator retur...} test stacktrace.test 25 {error_caller returnco...} main stacktrace.test 24 test\ err-10.2\ \{Stackt... {} stacktrace.test 127 main}}
+ err-10.3 {1 failure {error_caller errors.tcl 50 {error_generator retur...} test stacktrace.test 25 {error_caller returnco...} main stacktrace.test 24 test\ err-10.3\ \{Stackt... {} stacktrace.test 127 main}}
+ err-10.4 {1 failure {error_caller {} 1 {error_generator retur...} test stacktrace.test 25 {error_caller returnco...} main stacktrace.test 24 test\ err-10.4\ \{Stackt... {} stacktrace.test 127 main}}
}
# Set this to output expected results to stderr