Attachment "errorstack5.patch" to
ticket [2868499fff]
added by
ferrieux
2009-10-31 23:36:43.
Index: generic/tclBasic.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclBasic.c,v
retrieving revision 1.404
diff -u -r1.404 tclBasic.c
--- generic/tclBasic.c 11 Sep 2009 20:13:27 -0000 1.404
+++ generic/tclBasic.c 31 Oct 2009 16:33:17 -0000
@@ -530,6 +530,9 @@
iPtr->errorInfo = NULL;
TclNewLiteralStringObj(iPtr->eiVar, "::errorInfo");
Tcl_IncrRefCount(iPtr->eiVar);
+ iPtr->errorStack = Tcl_NewListObj(0, NULL);
+ Tcl_IncrRefCount(iPtr->errorStack);
+ iPtr->resetErrorStack = 1;
iPtr->errorCode = NULL;
TclNewLiteralStringObj(iPtr->ecVar, "::errorCode");
Tcl_IncrRefCount(iPtr->ecVar);
@@ -1470,6 +1473,7 @@
Tcl_DecrRefCount(iPtr->errorInfo);
iPtr->errorInfo = NULL;
}
+ Tcl_DecrRefCount(iPtr->errorStack);
if (iPtr->returnOpts) {
Tcl_DecrRefCount(iPtr->returnOpts);
}
@@ -8821,5 +8825,7 @@
* mode: c
* c-basic-offset: 4
* fill-column: 78
+ * tab-width: 8
+ * indent-tabs-mode: nil
* End:
*/
Index: generic/tclCmdIL.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCmdIL.c,v
retrieving revision 1.171
diff -u -r1.171 tclCmdIL.c
--- generic/tclCmdIL.c 20 Aug 2009 10:56:55 -0000 1.171
+++ generic/tclCmdIL.c 31 Oct 2009 16:33:20 -0000
@@ -118,6 +118,9 @@
int objc, Tcl_Obj *const objv[]);
static int InfoDefaultCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
+/* TIP #348 - New 'info' subcommand 'errorstack' */
+static int InfoErrorStackCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
/* TIP #280 - New 'info' subcommand 'frame' */
static int InfoFrameCmd(ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
@@ -164,6 +167,7 @@
{"complete", InfoCompleteCmd, NULL},
{"coroutine", TclInfoCoroutineCmd, NULL},
{"default", InfoDefaultCmd, NULL},
+ {"errorstack", InfoErrorStackCmd, NULL},
{"exists", TclInfoExistsCmd, TclCompileInfoExistsCmd},
{"frame", InfoFrameCmd, NULL},
{"functions", InfoFunctionsCmd, NULL},
@@ -1017,6 +1021,55 @@
/*
*----------------------------------------------------------------------
*
+ * InfoErrorStackCmd --
+ *
+ * Called to implement the "info errorstack" command that returns information
+ * about the last error's call stack. Handles the following syntax:
+ *
+ * info errorstack ?interp?
+ *
+ * Results:
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ *
+ * Side effects:
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InfoErrorStackCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_Interp *target;
+ Interp *iPtr;
+
+ if ((objc != 1) && (objc != 2)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?interp?");
+ return TCL_ERROR;
+ }
+
+ target = interp;
+ if (objc == 2) {
+ target = Tcl_GetSlave(interp, Tcl_GetString(objv[1]));
+ if (target == NULL) {
+ return TCL_ERROR;
+ }
+ }
+
+ iPtr = (Interp *) target;
+ Tcl_SetObjResult(interp, iPtr->errorStack);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclInfoExistsCmd --
*
* Called to implement the "info exists" command that determines whether
@@ -4388,5 +4441,7 @@
* mode: c
* c-basic-offset: 4
* fill-column: 78
+ * tab-width: 8
+ * indent-tabs-mode: nil
* End:
*/
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.445
diff -u -r1.445 tclInt.h
--- generic/tclInt.h 30 Sep 2009 03:11:26 -0000 1.445
+++ generic/tclInt.h 31 Oct 2009 16:33:25 -0000
@@ -1895,6 +1895,8 @@
Tcl_Obj *eiVar; /* cached ref to ::errorInfo variable. */
Tcl_Obj *errorCode; /* errorCode value (now as a Tcl_Obj). */
Tcl_Obj *ecVar; /* cached ref to ::errorInfo variable. */
+ Tcl_Obj *errorStack; /* ::tcl::errorStack value (as a Tcl_Obj). */
+ int resetErrorStack; /* controls cleaning up of ::errorStack */
int returnLevel; /* [return -level] parameter. */
/*
Index: generic/tclNamesp.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclNamesp.c,v
retrieving revision 1.193
diff -u -r1.193 tclNamesp.c
--- generic/tclNamesp.c 30 Sep 2009 03:11:26 -0000 1.193
+++ generic/tclNamesp.c 31 Oct 2009 16:33:35 -0000
@@ -7574,7 +7574,7 @@
{
register const char *p;
Interp *iPtr = (Interp *) interp;
- int overflow, limit = 150;
+ int overflow, limit = 150, len;
Var *varPtr, *arrayPtr;
if (iPtr->flags & ERR_ALREADY_LOGGED) {
@@ -7633,6 +7633,36 @@
TCL_GLOBAL_ONLY);
}
}
+
+ /*
+ * TIP #348
+ */
+
+ if (Tcl_IsShared(iPtr->errorStack)) {
+ Tcl_Obj *newObj;
+
+ newObj = Tcl_DuplicateObj(iPtr->errorStack);
+ Tcl_DecrRefCount(iPtr->errorStack);
+ Tcl_IncrRefCount(newObj);
+ iPtr->errorStack = newObj;
+ }
+ Tcl_ListObjLength(interp, iPtr->errorStack, &len);
+ if (iPtr->resetErrorStack) {
+ iPtr->resetErrorStack = 0;
+ /* reset while keeping the list intrep as much as possible */
+ Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, 0, NULL);
+ len=0;
+ }
+ if (iPtr->varFramePtr != iPtr->rootFramePtr) {
+ Tcl_Obj *listPtr;
+ int result;
+ listPtr=Tcl_NewListObj(iPtr->varFramePtr->objc,
+ iPtr->varFramePtr->objv);
+ result = Tcl_ListObjReplace(interp, iPtr->errorStack, len, 0, 1, &listPtr);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(listPtr);
+ }
+ }
}
/*
@@ -7640,5 +7670,7 @@
* mode: c
* c-basic-offset: 4
* fill-column: 78
+ * tab-width: 8
+ * indent-tabs-mode: nil
* End:
*/
Index: generic/tclResult.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclResult.c,v
retrieving revision 1.54
diff -u -r1.54 tclResult.c
--- generic/tclResult.c 17 Dec 2008 16:47:38 -0000 1.54
+++ generic/tclResult.c 31 Oct 2009 16:33:37 -0000
@@ -19,7 +19,7 @@
enum returnKeys {
KEY_CODE, KEY_ERRORCODE, KEY_ERRORINFO, KEY_ERRORLINE,
- KEY_LEVEL, KEY_OPTIONS, KEY_LAST
+ KEY_LEVEL, KEY_OPTIONS, KEY_ERRORSTACK, KEY_LAST
};
/*
@@ -922,6 +922,7 @@
Tcl_DecrRefCount(iPtr->errorInfo);
iPtr->errorInfo = NULL;
}
+ iPtr->resetErrorStack = 1;
iPtr->returnLevel = 1;
iPtr->returnCode = TCL_OK;
if (iPtr->returnOpts) {
@@ -1158,6 +1159,7 @@
TclNewLiteralStringObj(keys[KEY_ERRORCODE], "-errorcode");
TclNewLiteralStringObj(keys[KEY_ERRORINFO], "-errorinfo");
TclNewLiteralStringObj(keys[KEY_ERRORLINE], "-errorline");
+ TclNewLiteralStringObj(keys[KEY_ERRORSTACK],"-errorstack");
TclNewLiteralStringObj(keys[KEY_LEVEL], "-level");
TclNewLiteralStringObj(keys[KEY_OPTIONS], "-options");
@@ -1503,6 +1505,7 @@
Tcl_DictObjPut(NULL, options, keys[KEY_ERRORLINE],
Tcl_NewIntObj(iPtr->errorLine));
}
+ Tcl_DictObjPut(NULL, options, keys[KEY_ERRORSTACK], iPtr->errorStack);
return options;
}
@@ -1624,5 +1627,7 @@
* mode: c
* c-basic-offset: 4
* fill-column: 78
+ * tab-width: 8
+ * indent-tabs-mode: nil
* End:
*/
Index: tests/cmdMZ.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/cmdMZ.test,v
retrieving revision 1.26
diff -u -r1.26 cmdMZ.test
--- tests/cmdMZ.test 10 Sep 2008 13:50:05 -0000 1.26
+++ tests/cmdMZ.test 31 Oct 2009 16:33:41 -0000
@@ -119,18 +119,18 @@
return $result
}
-test cmdMZ-return-2.0 {return option handling} {
+test cmdMZ-return-2.0 {return option handling} -body {
list [catch return -> foo] [dictSort $foo]
-} {2 {-code 0 -level 1}}
-test cmdMZ-return-2.1 {return option handling} {
+} -match glob -result {2 {-code 0 -errorstack * -level 1}}
+test cmdMZ-return-2.1 {return option handling} -body {
list [catch {return -bar soom} -> foo] [dictSort $foo]
-} {2 {-bar soom -code 0 -level 1}}
-test cmdMZ-return-2.2 {return option handling} {
+} -match glob -result {2 {-bar soom -code 0 -errorstack * -level 1}}
+test cmdMZ-return-2.2 {return option handling} -body {
list [catch {return -code return} -> foo] [dictSort $foo]
-} {2 {-code 0 -level 2}}
-test cmdMZ-return-2.3 {return option handling} {
+} -match glob -result {2 {-code 0 -errorstack * -level 2}}
+test cmdMZ-return-2.3 {return option handling} -body {
list [catch {return -code return -level 10} -> foo] [dictSort $foo]
-} {2 {-code 0 -level 11}}
+} -match glob -result {2 {-code 0 -errorstack * -level 11}}
test cmdMZ-return-2.4 {return option handling} -body {
return -level 0 -code error
} -returnCodes error -result {}
@@ -149,14 +149,14 @@
test cmdMZ-return-2.9 {return option handling} -body {
return -level 0 -code 10
} -returnCodes 10 -result {}
-test cmdMZ-return-2.10 {return option handling} {
+test cmdMZ-return-2.10 {return option handling} -body {
list [catch {return -level 0 -code error} -> foo] [dictSort $foo]
-} {1 {-code 1 -errorcode NONE -errorinfo {
+} -match glob -result {1 {-code 1 -errorcode NONE -errorinfo {
while executing
-"return -level 0 -code error"} -errorline 1 -level 0}}
-test cmdMZ-return-2.11 {return option handling} {
+"return -level 0 -code error"} -errorline 1 -errorstack * -level 0}}
+test cmdMZ-return-2.11 {return option handling} -body {
list [catch {return -level 0 -code break} -> foo] [dictSort $foo]
-} {3 {-code 3 -level 0}}
+} -match glob -result {3 {-code 3 -errorstack * -level 0}}
test cmdMZ-return-2.12 {return option handling} -body {
return -level 0 -code error -options {-code ok}
} -returnCodes ok -result {}
Index: tests/error.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/error.test,v
retrieving revision 1.22
diff -u -r1.22 error.test
--- tests/error.test 28 Sep 2009 18:02:20 -0000 1.22
+++ tests/error.test 31 Oct 2009 16:33:42 -0000
@@ -153,6 +153,19 @@
list [catch {error msg1 msg2 {}} msg] $msg $::errorInfo $::errorCode
} {1 msg1 msg2 {}}
+test error-4.6 {errorstack via info } -body {
+ proc f x {g $x$x}
+ proc g x {error G:$x}
+ catch {f 12}
+ info errorstack
+} -match glob -result {{g 1212} {f 12} {namespace eval *}}
+test error-4.7 {errorstack via options dict } -body {
+ proc f x {g $x$x}
+ proc g x {error G:$x}
+ catch {f 12} m d
+ dict get $d -errorstack
+} -match glob -result {{g 1212} {f 12} {namespace eval *}}
+
# Errors in error command itself
test error-5.1 {errors in error command} {
@@ -207,6 +220,15 @@
catch foo
list $::errorCode
} {NONE}
+test error-6.10 {catch must reset errorStack} -body {
+ proc f x {g $x$x}
+ proc g x {error G:$x}
+ catch {f 12}
+ set e1 [info errorstack]
+ catch {f 13}
+ set e2 [info errorstack]
+ list $e1 $e2
+} -match glob -result {{{g 1212} {f 12} {namespace eval *}} {{g 1313} {f 13} {namespace eval *}}}
test error-7.1 {Bug 1397843} -body {
variable cmds
Index: tests/execute.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/execute.test,v
retrieving revision 1.32
diff -u -r1.32 execute.test
--- tests/execute.test 24 Jun 2009 13:51:36 -0000 1.32
+++ tests/execute.test 31 Oct 2009 16:33:42 -0000
@@ -956,11 +956,11 @@
demo
} -cleanup {
rename demo {}
-} -result {-code 1 -level 0 -errorcode NONE -errorinfo {FOO
+} -match glob -result {-code 1 -level 0 -errorcode NONE -errorinfo {FOO
while executing
"error FOO"
invoked from within
-"catch [list error FOO] m o"} -errorline 2}
+"catch \[list error FOO\] m o"} -errorline 2 -errorstack *}
test execute-9.1 {Interp result resetting [Bug 1522803]} {
set c 0
Index: tests/info.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/info.test,v
retrieving revision 1.69
diff -u -r1.69 info.test
--- tests/info.test 29 Oct 2009 22:20:12 -0000 1.69
+++ tests/info.test 31 Oct 2009 16:33:45 -0000
@@ -676,16 +676,16 @@
} -result {wrong # args: should be "info subcommand ?arg ...?"}
test info-21.2 {miscellaneous error conditions} -returnCodes error -body {
info gorp
-} -result {unknown or ambiguous subcommand "gorp": must be args, body, class, cmdcount, commands, complete, coroutine, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
+} -result {unknown or ambiguous subcommand "gorp": must be args, body, class, cmdcount, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
test info-21.3 {miscellaneous error conditions} -returnCodes error -body {
info c
-} -result {unknown or ambiguous subcommand "c": must be args, body, class, cmdcount, commands, complete, coroutine, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
+} -result {unknown or ambiguous subcommand "c": must be args, body, class, cmdcount, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
test info-21.4 {miscellaneous error conditions} -returnCodes error -body {
info l
-} -result {unknown or ambiguous subcommand "l": must be args, body, class, cmdcount, commands, complete, coroutine, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
+} -result {unknown or ambiguous subcommand "l": must be args, body, class, cmdcount, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
test info-21.5 {miscellaneous error conditions} -returnCodes error -body {
info s
-} -result {unknown or ambiguous subcommand "s": must be args, body, class, cmdcount, commands, complete, coroutine, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
+} -result {unknown or ambiguous subcommand "s": must be args, body, class, cmdcount, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
##
# ### ### ### ######### ######### #########
Index: tests/init.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/init.test,v
retrieving revision 1.19
diff -u -r1.19 init.test
--- tests/init.test 25 Jul 2009 22:00:10 -0000 1.19
+++ tests/init.test 31 Oct 2009 16:33:45 -0000
@@ -181,7 +181,7 @@
list $code $foo $bar $code2 $foo2 $bar2
} -cleanup {
unset ::auto_index(::xxx)
-} -result {2 xxx {-errorcode NONE -code 1 -level 1} 2 xxx {-code 1 -level 1 -errorcode NONE}}
+} -match glob -result {2 xxx {-errorcode NONE -errorstack * -code 1 -level 1} 2 xxx {-code 1 -level 1 -errorcode NONE -errorstack *}}
cleanupTests
} ;# End of [interp eval $testInterp]