Tcl Source Code

Artifact [8995b9eadf]
Login

Artifact 8995b9eadf39d18a6128f8c2c373e1e8fcd2f2ac:

Attachment "ei.patch" to ticket [1047543fff] added by dgp 2004-10-15 10:56:59.
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.2310
diff -u -r1.2310 ChangeLog
--- ChangeLog	14 Oct 2004 17:20:10 -0000	1.2310
+++ ChangeLog	15 Oct 2004 03:54:36 -0000
@@ -1,3 +1,35 @@
+2004-10-15  Don Porter  <[email protected]>
+
+	* generic/tclBasic.c (Tcl_CreateInterp,Tcl_DeleteInterp,
+		TclEvalObjvInternal,Tcl_LogCommandInfo,TclAddObjErrorInfo):
+	* generic/tclCmdAH.c (Tcl_CatchObjCmd):
+	* generic/tclEvent.c (BgError,ErrAssocData,Tcl_BackgroundError,
+		HandleBgErrors,BgErrorDeleteProc):
+	* generic/tclExecute.c (TclCreateExecEnv,TclDeleteExecEnv):
+	* generic/tclIOUtil.c (comments only):
+	* generic/tclInt.h (ExecEnv,Interp, ERR_IN_PROGRESS):
+	* generic/tclInterp.c ([tclInit]):
+	* generic/tclMain.c (comments only):
+	* generic/tclNamesp.c
+		(Tcl_CreateNamespace,Tcl_DeleteNamespace,TclTeardownNamespace):
+	* generic/tclProc.c (TclUpdateReturnInfo):
+	* generic/tclResult.c
+		(Tcl_ResetResult,TclTransferResult):
+	* generic/tclTrace.c (CallVarTraces):
+	Reworked management of the "errorInfo" data of an interp.
+	That information is now primarily stored in a new private
+	(Tcl_Obj *) field of the Interp struct, rather than using a
+	global variable ::errorInfo as the primary storage.  The
+	ERR_IN_PROGRESS flag bit value is no longer required to manage
+	the value in its new location, and is removed.  Variable traces
+	are established to support compatibility for any code expecting
+	the ::errorInfo variable to hold the information.
+
+	***POTENTIAL INCOMPATIBILITY***
+	Code that sets traces on the ::errorInfo variable may notice a
+	difference in timing of the firing of those traces.  Code that
+	uses the value ERR_IN_PROGRESS.
+
 2004-10-14  Donal K. Fellows  <[email protected]>
 
 	TIP#217 IMPLEMENTATION
@@ -165,7 +197,7 @@
 	the ::errorCode variable to hold the information.
 
 	***POTENTIAL INCOMPATIBILITY***
-	Code that sets traces on the ::errorCode value may notice a
+	Code that sets traces on the ::errorCode variable may notice a
 	difference in timing of the firing of those traces.
 
 	* generic/tclNamesp.c (Tcl_PopCallFrame):	Removed Bug 1038021
Index: generic/tclBasic.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclBasic.c,v
retrieving revision 1.125
diff -u -r1.125 tclBasic.c
--- generic/tclBasic.c	6 Oct 2004 00:24:16 -0000	1.125
+++ generic/tclBasic.c	15 Oct 2004 03:54:44 -0000
@@ -241,7 +241,12 @@
     Tcl_IncrRefCount(iPtr->defaultReturnOpts);
     iPtr->returnOpts = iPtr->defaultReturnOpts;
     Tcl_IncrRefCount(iPtr->returnOpts);
+    iPtr->errorInfo = NULL;
+    iPtr->eiVar = Tcl_NewStringObj("errorInfo", -1);
+    Tcl_IncrRefCount(iPtr->eiVar);
     iPtr->errorCode = NULL;
+    iPtr->ecVar = Tcl_NewStringObj("errorCode", -1);
+    Tcl_IncrRefCount(iPtr->ecVar);
 
     iPtr->appendResult = NULL;
     iPtr->appendAvl = 0;
@@ -894,10 +899,6 @@
     TclLimitRemoveAllHandlers(interp);
 
     /*
-     * Dismantle everything in the global namespace except for the
-     * "errorInfo" and "errorCode" variables. These remain until the
-     * namespace is actually destroyed, in case any errors occur.
-     *   
      * Dismantle the namespace here, before we clear the assocData. If any
      * background errors occur here, they will be deleted below.
      *
@@ -982,10 +983,16 @@
     interp->result = NULL;
     Tcl_DecrRefCount(iPtr->objResultPtr);
     iPtr->objResultPtr = NULL;
+    Tcl_DecrRefCount(iPtr->ecVar);
     if (iPtr->errorCode) {
 	Tcl_DecrRefCount(iPtr->errorCode);
 	iPtr->errorCode = NULL;
     }
+    Tcl_DecrRefCount(iPtr->eiVar);
+    if (iPtr->errorInfo) {
+	Tcl_DecrRefCount(iPtr->errorInfo);
+	iPtr->errorInfo = NULL;
+    }
     Tcl_DecrRefCount(iPtr->returnOpts);
     Tcl_DecrRefCount(iPtr->defaultReturnOpts);
     Tcl_DecrRefCount(iPtr->returnCodeKey);
@@ -3057,10 +3064,13 @@
      * Call 'leave' command traces
      */
     if (!(cmdPtr->flags & CMD_IS_DELETED)) {
-	int saveErrFlags = iPtr->flags
-		& (ERR_IN_PROGRESS | ERR_ALREADY_LOGGED);
+	int saveErrFlags = iPtr->flags & ERR_ALREADY_LOGGED;
 	Tcl_Obj *saveOptions = iPtr->returnOpts;
+	Tcl_Obj *saveErrInfo = iPtr->errorInfo;
 	Tcl_Obj *saveErrCode = iPtr->errorCode;
+	if (saveErrInfo) {
+	    Tcl_IncrRefCount(saveErrInfo);
+	}
 	if (saveErrCode) {
 	    Tcl_IncrRefCount(saveErrCode);
 	}
@@ -3082,8 +3092,17 @@
 		Tcl_DecrRefCount(iPtr->errorCode);
 	    }
 	    iPtr->errorCode = saveErrCode;
-	} else if (saveErrCode) {
-	    Tcl_DecrRefCount(saveErrCode);
+	    if (iPtr->errorInfo) {
+		Tcl_DecrRefCount(iPtr->errorInfo);
+	    }
+	    iPtr->errorInfo = saveErrInfo;
+	} else {
+	    if (saveErrCode) {
+		Tcl_DecrRefCount(saveErrCode);
+	    }
+	    if (saveErrInfo) {
+		Tcl_DecrRefCount(saveErrInfo);
+	    }
 	}
 	Tcl_DecrRefCount(saveOptions);
     }
@@ -3227,7 +3246,7 @@
  * Tcl_LogCommandInfo --
  *
  *	This procedure is invoked after an error occurs in an interpreter.
- *	It adds information to the "errorInfo" variable to describe the
+ *	It adds information to iPtr->errorInfo field to describe the
  *	command that was being executed when the error occurred.
  *
  * Results:
@@ -3235,10 +3254,7 @@
  *
  * Side effects:
  *	Information about the command is added to errorInfo and the
- *	line number stored internally in the interpreter is set.  If this
- *	is the first call to this procedure or Tcl_AddObjErrorInfo since
- *	an error occurred, then old information in errorInfo is
- *	deleted.
+ *	line number stored internally in the interpreter is set.  
  *
  *----------------------------------------------------------------------
  */
@@ -3277,7 +3293,7 @@
 	}
     }
 
-    if (!(iPtr->flags & ERR_IN_PROGRESS)) {
+    if (iPtr->errorInfo == NULL) {
 	message = Tcl_NewStringObj("\n    while executing\n\"", -1);
     } else {
 	message = Tcl_NewStringObj("\n    invoked from within\n\"", -1);
@@ -3602,12 +3618,7 @@
     return TCL_OK;
 
     error:
-    /*
-     * Generate various pieces of error information, such as the line
-     * number where the error occurred and information to add to the
-     * errorInfo variable.  Then free resources that had been allocated
-     * to the command.
-     */
+    /* Generate and log various pieces of error information. */
 
     if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { 
 	commandLength = parse.commandSize;
@@ -3625,6 +3636,8 @@
     }
     iPtr->flags &= ~ERR_ALREADY_LOGGED;
     
+    /* Then free resources that had been allocated to the command. */
+
     for (i = 0; i < objectsUsed; i++) {
 	Tcl_DecrRefCount(objv[i]);
     }
@@ -4359,16 +4372,14 @@
  *
  * TclAppendObjToErrorInfo --
  *
- *	Add a Tcl_Obj value to the "errorInfo" variable that describes the
+ *	Add a Tcl_Obj value to the errorInfo field that describes the
  *	current error.
  *
  * Results:
  *	None.
  *
  * Side effects:
- * 	The value of the Tcl_obj is added to the "errorInfo" variable.
- *	If Tcl_Eval has been called since the current value of errorInfo
- *	was set, errorInfo is cleared before adding the new message.
+ * 	The value of the Tcl_obj is appended to the errorInfo field.
  *	If we are just starting to log an error, errorInfo is initialized
  *	from the error message in the interpreter's result.
  *
@@ -4391,16 +4402,14 @@
  *
  * Tcl_AddErrorInfo --
  *
- *	Add information to the "errorInfo" variable that describes the
+ *	Add information to the errorInfo field that describes the
  *	current error.
  *
  * Results:
  *	None.
  *
  * Side effects:
- *	The contents of message are added to the "errorInfo" variable.
- *	If Tcl_Eval has been called since the current value of errorInfo
- *	was set, errorInfo is cleared before adding the new message.
+ *	The contents of message are appended to the errorInfo field.
  *	If we are just starting to log an error, errorInfo is initialized
  *	from the error message in the interpreter's result.
  *
@@ -4421,7 +4430,7 @@
  *
  * Tcl_AddObjErrorInfo --
  *
- *	Add information to the "errorInfo" variable that describes the
+ *	Add information to the errorInfo field that describes the
  *	current error. This routine differs from Tcl_AddErrorInfo by
  *	taking a byte pointer and length.
  *
@@ -4429,10 +4438,8 @@
  *	None.
  *
  * Side effects:
- *	"length" bytes from "message" are added to the "errorInfo" variable.
+ *	"length" bytes from "message" are appended to the errorInfo field.
  *	If "length" is negative, use bytes up to the first NULL byte.
- *	If Tcl_EvalObj has been called since the current value of errorInfo
- *	was set, errorInfo is cleared before adding the new message.
  *	If we are just starting to log an error, errorInfo is initialized
  *	from the error message in the interpreter's result.
  *
@@ -4457,16 +4464,20 @@
      * from the error message in the interpreter's result.
      */
 
-    if (!(iPtr->flags & ERR_IN_PROGRESS)) { /* just starting to log error */
-	iPtr->flags |= ERR_IN_PROGRESS;
-
-	if (iPtr->result[0] == 0) {
-	    Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorInfo, NULL, 
-	            iPtr->objResultPtr, TCL_GLOBAL_ONLY);
-	} else {		/* use the string result */
-	    Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorInfo, NULL, 
-	            Tcl_NewStringObj(interp->result, -1), TCL_GLOBAL_ONLY);
+    if (iPtr->errorInfo == NULL) { /* just starting to log error */
+	if (iPtr->result[0] != 0) {
+	    /*
+	     * The interp's string result is set, apparently by some
+	     * extension making a deprecated direct write to it.
+	     * That extension may expect interp->result to continue
+	     * to be set, so we'll take special pains to avoid clearing
+	     * it, until we drop support for interp->result completely.
+	     */
+	    iPtr->errorInfo = Tcl_NewStringObj(interp->result, -1);
+	} else {
+	    iPtr->errorInfo = iPtr->objResultPtr;
 	}
+	Tcl_IncrRefCount(iPtr->errorInfo);
     }
 
     /*
@@ -4474,11 +4485,12 @@
      */
 
     if (length != 0) {
-	messagePtr = Tcl_NewStringObj(message, length);
-	Tcl_IncrRefCount(messagePtr);
-	Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorInfo, NULL, 
-	        messagePtr, (TCL_GLOBAL_ONLY | TCL_APPEND_VALUE));
-	Tcl_DecrRefCount(messagePtr); /* free msg object appended above */
+	if (Tcl_IsShared(iPtr->errorInfo)) {
+	    Tcl_DecrRefCount(iPtr->errorInfo);
+	    iPtr->errorInfo = Tcl_DuplicateObj(iPtr->errorInfo);
+	    Tcl_IncrRefCount(iPtr->errorInfo);
+	}
+	Tcl_AppendToObj(iPtr->errorInfo, message, length);
     }
 }
 
Index: generic/tclCmdAH.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCmdAH.c,v
retrieving revision 1.53
diff -u -r1.53 tclCmdAH.c
--- generic/tclCmdAH.c	6 Oct 2004 09:07:12 -0000	1.53
+++ generic/tclCmdAH.c	15 Oct 2004 03:54:48 -0000
@@ -280,17 +280,19 @@
 		    iPtr->returnLevelKey, Tcl_NewIntObj(0));
 	}
 
-	if (iPtr->flags & ERR_IN_PROGRESS) {
+	if (result == TCL_ERROR) {
+	    /*
+	     * When result was an error, fill in any missing values
+	     * for -errorinfo, -errorcode, and -errorline
+	     */
+
 	    value = NULL;
 	    Tcl_DictObjGet(NULL, options, iPtr->returnErrorinfoKey, &value);
 	    if (NULL == value) {
 		Tcl_DictObjPut(NULL, options, iPtr->returnErrorinfoKey,
-			Tcl_ObjGetVar2(interp, iPtr->execEnvPtr->errorInfo,
-			NULL, TCL_GLOBAL_ONLY));
+			iPtr->errorInfo);
 	    }
-	}
 
-	if (result == TCL_ERROR) {
 	    value = NULL;
 	    Tcl_DictObjGet(NULL, options, iPtr->returnErrorcodeKey, &value);
 	    if (NULL == value) {
Index: generic/tclCmdMZ.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCmdMZ.c,v
retrieving revision 1.111
diff -u -r1.111 tclCmdMZ.c
--- generic/tclCmdMZ.c	6 Oct 2004 09:44:11 -0000	1.111
+++ generic/tclCmdMZ.c	15 Oct 2004 03:54:53 -0000
@@ -880,8 +880,7 @@
  *	Returns the return code the [return] command should return.
  *
  * Side effects:
- *	When the return code is TCL_ERROR, the values of ::errorInfo
- *	and ::errorCode may be updated.
+ * 	None.
  *
  *----------------------------------------------------------------------
  */
Index: generic/tclEvent.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclEvent.c,v
retrieving revision 1.47
diff -u -r1.47 tclEvent.c
--- generic/tclEvent.c	5 Oct 2004 18:14:27 -0000	1.47
+++ generic/tclEvent.c	15 Oct 2004 03:54:56 -0000
@@ -25,16 +25,10 @@
  */
 
 typedef struct BgError {
-    Tcl_Interp *interp;		/* Interpreter in which error occurred.  NULL
-				 * means this error report has been cancelled
-				 * (a previous report generated a break). */
-    char *errorMsg;		/* Copy of the error message (the interp's
-				 * result when the error occurred).
-				 * Malloc-ed. */
-    char *errorInfo;		/* Value of the errorInfo variable
-				 * (malloc-ed). */
-    Tcl_Obj *errorCode;		/* Value of the errorCode variable
-				 * (malloc-ed). */
+    Tcl_Obj *errorMsg;		/* Copy of the error message (the interp's
+				 * result when the error occurred). */
+    Tcl_Obj *errorInfo;		/* Value of the errorInfo variable */
+    Tcl_Obj *errorCode;		/* Value of the errorCode variable */
     struct BgError *nextPtr;	/* Next in list of all pending error
 				 * reports for this interpreter, or NULL
 				 * for end of list. */
@@ -47,6 +41,7 @@
  */
 
 typedef struct ErrAssocData {
+    Tcl_Interp *interp;		/* Interpreter in which error occurred. */
     BgError *firstBgPtr;	/* First in list of all background errors
 				 * waiting to be processed for this
 				 * interpreter (NULL if none). */
@@ -160,11 +155,13 @@
 				 * occurred. */
 {
     BgError *errPtr;
-    CONST char *errResult, *varValue;
     ErrAssocData *assocPtr;
-    int length;
     Interp *iPtr = (Interp *) interp;
 
+    errPtr = (BgError *) ckalloc(sizeof(BgError));
+    errPtr->errorMsg = Tcl_GetObjResult(interp);
+    Tcl_IncrRefCount(errPtr->errorMsg);
+	    
     /*
      * The Tcl_AddErrorInfo call below (with an empty string) ensures that
      * errorInfo gets properly set.  It's needed in cases where the error
@@ -174,19 +171,8 @@
      */
 
     Tcl_AddErrorInfo(interp, "");
-
-    errResult = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length);
-	
-    errPtr = (BgError *) ckalloc(sizeof(BgError));
-    errPtr->interp = interp;
-    errPtr->errorMsg = (char *) ckalloc((unsigned) (length + 1));
-    memcpy(errPtr->errorMsg, errResult, (size_t) (length + 1));
-    varValue = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
-    if (varValue == NULL) {
-	varValue = errPtr->errorMsg;
-    }
-    errPtr->errorInfo = (char *) ckalloc((unsigned) (strlen(varValue) + 1));
-    strcpy(errPtr->errorInfo, varValue);
+    errPtr->errorInfo = iPtr->errorInfo;
+    Tcl_IncrRefCount(errPtr->errorInfo);
 
     if (iPtr->errorCode) {
 	errPtr->errorCode = iPtr->errorCode;
@@ -209,6 +195,7 @@
 	 */
 
 	assocPtr = (ErrAssocData *) ckalloc(sizeof(ErrAssocData));
+	assocPtr->interp = interp;
 	assocPtr->firstBgPtr = NULL;
 	assocPtr->lastBgPtr = NULL;
 	Tcl_SetAssocData(interp, "tclBgError", BgErrorDeleteProc,
@@ -245,43 +232,50 @@
 HandleBgErrors(clientData)
     ClientData clientData;	/* Pointer to ErrAssocData structure. */
 {
-    Tcl_Interp *interp;
-    int code;
-    BgError *errPtr;
     ErrAssocData *assocPtr = (ErrAssocData *) clientData;
-    Tcl_Channel errChannel;
+    Tcl_Interp *interp = assocPtr->interp;
+    BgError *errPtr;
     Tcl_Obj *objv[2];
 
+    /*
+     * Not bothering to save/restore the interp state.  Assume that
+     * any code that has interp state it needs to keep will make
+     * its own Tcl_SaveResult call before calling something like
+     * Tcl_DoOneEvent() that could lead us here.
+     */
+
     objv[0] = Tcl_NewStringObj("bgerror", -1);
     Tcl_IncrRefCount(objv[0]);
-    objv[1] = NULL;
 
     Tcl_Preserve((ClientData) assocPtr);
+    Tcl_Preserve((ClientData) interp);
     while (assocPtr->firstBgPtr != NULL) {
-	interp = assocPtr->firstBgPtr->interp;
-	if (interp == NULL) {
-	    goto doneWithInterp;
-	}
+	int code;
+	Interp *iPtr = (Interp *)interp;
+	errPtr = assocPtr->firstBgPtr;
 
 	/*
 	 * Restore important state variables to what they were at
 	 * the time the error occurred.
+	 *
+	 * Need to set the variables, not the interp fields, because
+	 * Tcl_EvalObjv() calls Tcl_ResetResult() which would destroy
+	 * anything we write to the interp fields.
 	 */
 
-	Tcl_SetVar(interp, "errorInfo", assocPtr->firstBgPtr->errorInfo,
-		TCL_GLOBAL_ONLY);
-	Tcl_SetVar2Ex(interp, "errorCode", NULL,
-		assocPtr->firstBgPtr->errorCode, TCL_GLOBAL_ONLY);
+	Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
+		errPtr->errorInfo, TCL_GLOBAL_ONLY);
+	Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL,
+		errPtr->errorCode, TCL_GLOBAL_ONLY);
 
 	/*
 	 * Create and invoke the bgerror command.
 	 */
 
-	objv[1] = Tcl_NewStringObj(assocPtr->firstBgPtr->errorMsg, -1);
+	objv[1] = errPtr->errorMsg;
 	Tcl_IncrRefCount(objv[1]);
 	
 	Tcl_AllowExceptions(interp);
-        Tcl_Preserve((ClientData) interp);
 	code = Tcl_EvalObjv(interp, 2, objv, TCL_EVAL_GLOBAL);
 	if (code == TCL_ERROR) {
 
@@ -302,49 +296,37 @@
 		Tcl_SaveResult(interp, &save);
                 TclObjInvoke(interp, 2, objv, TCL_INVOKE_HIDDEN);
 		Tcl_RestoreResult(interp, &save);
+            } else {
 
-                goto doneWithInterp;
-            } 
-
-            /*
-             * We have to get the error output channel at the latest possible
-             * time, because the eval (above) might have changed the channel.
-             */
+		/*
+		 * We have to get the error output channel at the latest
+		 * possible time, because the eval (above) might have
+		 * changed the channel.
+		 */
             
-            errChannel = Tcl_GetStdChannel(TCL_STDERR);
-            if (errChannel != (Tcl_Channel) NULL) {
-		char *string;
-		int len;
-
-		string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len);
-		if (Tcl_FindCommand(interp, "bgerror", NULL, TCL_GLOBAL_ONLY) == NULL) {
-                    Tcl_WriteChars(errChannel, assocPtr->firstBgPtr->errorInfo, -1);
-                    Tcl_WriteChars(errChannel, "\n", -1);
-                } else {
-                    Tcl_WriteChars(errChannel,
-                            "bgerror failed to handle background error.\n",
-                            -1);
-                    Tcl_WriteChars(errChannel, "    Original error: ", -1);
-                    Tcl_WriteChars(errChannel, assocPtr->firstBgPtr->errorMsg,
-                            -1);
-                    Tcl_WriteChars(errChannel, "\n", -1);
-                    Tcl_WriteChars(errChannel, "    Error in bgerror: ", -1);
-                    Tcl_WriteChars(errChannel, string, len);
-                    Tcl_WriteChars(errChannel, "\n", -1);
-                }
-                Tcl_Flush(errChannel);
-            }
-	} else if (code == TCL_BREAK) {
-
-	    /*
-	     * Break means cancel any remaining error reports for this
-	     * interpreter.
-	     */
-
-	    for (errPtr = assocPtr->firstBgPtr; errPtr != NULL;
-		    errPtr = errPtr->nextPtr) {
-		if (errPtr->interp == interp) {
-		    errPtr->interp = NULL;
+		Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR);
+		if (errChannel != (Tcl_Channel) NULL) {
+		    Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
+
+		    Tcl_IncrRefCount(resultPtr);
+		    if (Tcl_FindCommand(interp, "bgerror",
+			    NULL, TCL_GLOBAL_ONLY) == NULL) {
+			Tcl_WriteObj(errChannel, errPtr->errorInfo);
+			Tcl_WriteChars(errChannel, "\n", -1);
+                    } else {
+			Tcl_WriteChars(errChannel,
+				"bgerror failed to handle background error.\n",
+				-1);
+			Tcl_WriteChars(errChannel, "    Original error: ", -1);
+			Tcl_WriteObj(errChannel, errPtr->errorMsg);
+			Tcl_WriteChars(errChannel, "\n", -1);
+			Tcl_WriteChars(errChannel,
+				"    Error in bgerror: ", -1);
+			Tcl_WriteObj(errChannel, resultPtr);
+			Tcl_WriteChars(errChannel, "\n", -1);
+                    }
+		    Tcl_DecrRefCount(resultPtr);
+                    Tcl_Flush(errChannel);
 		}
 	    }
 	}
@@ -353,28 +335,37 @@
 	 * Discard the command and the information about the error report.
 	 */
 
-doneWithInterp:
-	if (objv[1]) {
-	    Tcl_DecrRefCount(objv[1]);
-	    objv[1] = NULL;
-	}
+	Tcl_DecrRefCount(objv[1]);
+	Tcl_DecrRefCount(errPtr->errorMsg);
+	Tcl_DecrRefCount(errPtr->errorInfo);
+	Tcl_DecrRefCount(errPtr->errorCode);
+	assocPtr->firstBgPtr = errPtr->nextPtr;
+	ckfree((char *) errPtr);
 
-	if (assocPtr->firstBgPtr) {
-	    ckfree(assocPtr->firstBgPtr->errorMsg);
-	    ckfree(assocPtr->firstBgPtr->errorInfo);
-	    Tcl_DecrRefCount(assocPtr->firstBgPtr->errorCode);
-	    errPtr = assocPtr->firstBgPtr->nextPtr;
-	    ckfree((char *) assocPtr->firstBgPtr);
-	    assocPtr->firstBgPtr = errPtr;
+	if (code == TCL_BREAK) {
+	    /*
+	     * Break means cancel any remaining error reports for this
+	     * interpreter.
+	     */
+	    break;
 	}
         
-        if (interp != NULL) {
-            Tcl_Release((ClientData) interp);
-        }
     }
+
+    /* Cleanup any error reports we didn't do (due to a TCL_BREAK) */
+    while (assocPtr->firstBgPtr != NULL) {
+	errPtr = assocPtr->firstBgPtr;
+	assocPtr->firstBgPtr = errPtr->nextPtr;
+	Tcl_DecrRefCount(errPtr->errorMsg);
+	Tcl_DecrRefCount(errPtr->errorInfo);
+	Tcl_DecrRefCount(errPtr->errorCode);
+	ckfree((char *) errPtr);
+    }
+
     assocPtr->lastBgPtr = NULL;
     Tcl_DecrRefCount(objv[0]);
 
+    Tcl_Release((ClientData) interp);
     Tcl_Release((ClientData) assocPtr);
 }
 
@@ -409,8 +400,8 @@
     while (assocPtr->firstBgPtr != NULL) {
 	errPtr = assocPtr->firstBgPtr;
 	assocPtr->firstBgPtr = errPtr->nextPtr;
-	ckfree(errPtr->errorMsg);
-	ckfree(errPtr->errorInfo);
+	Tcl_DecrRefCount(errPtr->errorMsg);
+	Tcl_DecrRefCount(errPtr->errorInfo);
 	Tcl_DecrRefCount(errPtr->errorCode);
 	ckfree((char *) errPtr);
     }
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.156
diff -u -r1.156 tclExecute.c
--- generic/tclExecute.c	8 Oct 2004 15:39:53 -0000	1.156
+++ generic/tclExecute.c	15 Oct 2004 03:55:07 -0000
@@ -527,12 +527,6 @@
     eePtr->tosPtr = stackPtr - 1;
     eePtr->endPtr = stackPtr + (TCL_STACK_INITIAL_SIZE - 2);
 
-    eePtr->errorInfo = Tcl_NewStringObj("::errorInfo", -1);
-    Tcl_IncrRefCount(eePtr->errorInfo);
-
-    eePtr->errorCode = Tcl_NewStringObj("::errorCode", -1);
-    Tcl_IncrRefCount(eePtr->errorCode);
-
     Tcl_MutexLock(&execMutex);
     if (!execInitialized) {
 	TclInitAuxDataTypeTable();
@@ -571,8 +565,6 @@
     } else {
 	Tcl_Panic("ERROR: freeing an execEnv whose stack is still in use.\n");
     }
-    TclDecrRefCount(eePtr->errorInfo);
-    TclDecrRefCount(eePtr->errorCode);
     ckfree((char *) eePtr);
 }
 
@@ -5142,15 +5134,16 @@
  *
  * IllegalExprOperandType --
  *
- *	Used by TclExecuteByteCode to add an error message to errorInfo
- *	when an illegal operand type is detected by an expression
- *	instruction. The argument opndPtr holds the operand object in error.
+ *	Used by TclExecuteByteCode to append an error message to
+ *	the interp result when an illegal operand type is detected by an
+ *	expression instruction. The argument opndPtr holds the operand
+ *	object in error.
  *
  * Results:
  *	None.
  *
  * Side effects:
- *	An error message is appended to errorInfo.
+ *	An error message is appended to the interp result.
  *
  *----------------------------------------------------------------------
  */
Index: generic/tclIOUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIOUtil.c,v
retrieving revision 1.111
diff -u -r1.111 tclIOUtil.c
--- generic/tclIOUtil.c	7 Oct 2004 14:50:22 -0000	1.111
+++ generic/tclIOUtil.c	15 Oct 2004 03:55:16 -0000
@@ -1783,23 +1783,23 @@
  *
  *	This procedure is typically called after UNIX kernel calls
  *	return errors.  It stores machine-readable information about
- *	the error in $errorCode returns an information string for
- *	the caller's use.
+ *	the error in errorCode field of interp and returns an
+ *	information string for the caller's use.
  *
  * Results:
  *	The return value is a human-readable string describing the
  *	error.
  *
  * Side effects:
- *	The global variable $errorCode is reset.
+ *	The errorCode field of the interp is set.
  *
  *----------------------------------------------------------------------
  */
 
 CONST char *
 Tcl_PosixError(interp)
-    Tcl_Interp *interp;		/* Interpreter whose $errorCode variable
-				 * is to be changed. */
+    Tcl_Interp *interp;		/* Interpreter whose errorCode field 
+				 * is to be set. */
 {
     CONST char *id, *msg;
 
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.180
diff -u -r1.180 tclInt.h
--- generic/tclInt.h	5 Oct 2004 18:14:27 -0000	1.180
+++ generic/tclInt.h	15 Oct 2004 03:55:22 -0000
@@ -888,8 +888,6 @@
     Tcl_Obj **tosPtr;		/* Points to current top of stack; 
 				 * (stackPtr-1) when the stack is empty. */
     Tcl_Obj **endPtr;		/* Points to last usable item in stack. */
-    Tcl_Obj *errorInfo;
-    Tcl_Obj *errorCode;
 } ExecEnv;
 
 /*
@@ -1332,7 +1330,10 @@
     Tcl_Obj *returnLevelKey;	/* holds "-level" */
     Tcl_Obj *returnOptionsKey;	/* holds "-options" */
 
+    Tcl_Obj *errorInfo;		/* errorInfo value (now as a Tcl_Obj) */
+    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 */
 
     /*
      * Resource limiting framework support (TIP#143).
@@ -1395,11 +1396,8 @@
  *			don't process any more commands for it, and destroy
  *			the structure as soon as all nested invocations of
  *			Tcl_Eval are done.
- * ERR_IN_PROGRESS:	Non-zero means an error unwind is already in
- *			progress. Zero means a command proc has been
- *			invoked since last error occured.
  * ERR_ALREADY_LOGGED:	Non-zero means information has already been logged
- *			in $errorInfo for the current Tcl_Eval instance,
+ *			in iPtr->errorInfo for the current Tcl_Eval instance,
  *			so Tcl_Eval needn't log it (used to implement the
  *			"error message log" command).
  * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler
@@ -1418,7 +1416,6 @@
  */
 
 #define DELETED				    1
-#define ERR_IN_PROGRESS			    2
 #define ERR_ALREADY_LOGGED		    4
 #define DONT_COMPILE_CMDS_INLINE	 0x20
 #define RAND_SEED_INITIALIZED		 0x40
Index: generic/tclInterp.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInterp.c,v
retrieving revision 1.46
diff -u -r1.46 tclInterp.c
--- generic/tclInterp.c	6 Oct 2004 14:59:02 -0000	1.46
+++ generic/tclInterp.c	15 Oct 2004 03:55:29 -0000
@@ -59,7 +59,7 @@
 
 static char initScript[] = "if {[info proc tclInit]==\"\"} {\n\
   proc tclInit {} {\n\
-    global tcl_libPath tcl_library errorInfo\n\
+    global tcl_libPath tcl_library\n\
     global env tclDefaultLibrary\n\
     rename tclInit {}\n\
     set errors {}\n\
@@ -84,10 +84,10 @@
 	set tcl_library $i\n\
 	set tclfile [file join $i init.tcl]\n\
 	if {[file exists $tclfile]} {\n\
-	    if {![catch {uplevel #0 [list source $tclfile]} msg]} {\n\
+	    if {![catch {uplevel #0 [list source $tclfile]} msg opt]} {\n\
 		return\n\
 	    } else {\n\
-		append errors \"$tclfile: $msg\n$errorInfo\n\"\n\
+		append errors \"$tclfile: $msg\n$opt(-errorinfo)\n\"\n\
 	    }\n\
 	}\n\
     }\n\
Index: generic/tclMain.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclMain.c,v
retrieving revision 1.27
diff -u -r1.27 tclMain.c
--- generic/tclMain.c	11 Jun 2004 21:30:08 -0000	1.27
+++ generic/tclMain.c	15 Oct 2004 03:55:30 -0000
@@ -438,7 +438,8 @@
 
 		/*
 		 * The following statement guarantees that the errorInfo
-		 * variable is set properly.
+		 * variable is set properly when the error has to do with
+		 * the opening or reading of the file.
 		 */
 
 		Tcl_AddErrorInfo(interp, "");
Index: generic/tclNamesp.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclNamesp.c,v
retrieving revision 1.61
diff -u -r1.61 tclNamesp.c
--- generic/tclNamesp.c	6 Oct 2004 15:59:24 -0000	1.61
+++ generic/tclNamesp.c	15 Oct 2004 03:55:41 -0000
@@ -175,9 +175,15 @@
 static char *		ErrorCodeRead _ANSI_ARGS_(( ClientData clientData,
 			    Tcl_Interp *interp, CONST char *name1,
 			    CONST char *name2, int flags));
+static char *		ErrorInfoRead _ANSI_ARGS_(( ClientData clientData,
+			    Tcl_Interp *interp, CONST char *name1,
+			    CONST char *name2, int flags));
 static char *		EstablishErrorCodeTraces _ANSI_ARGS_((
 			    ClientData clientData, Tcl_Interp *interp,
 			    CONST char *name1, CONST char *name2, int flags));
+static char *		EstablishErrorInfoTraces _ANSI_ARGS_((
+			    ClientData clientData, Tcl_Interp *interp,
+			    CONST char *name1, CONST char *name2, int flags));
 static void		FreeNsNameInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
 static int		GetNamespaceFromObj _ANSI_ARGS_((
 			    Tcl_Interp *interp, Tcl_Obj *objPtr,
@@ -525,7 +531,7 @@
  * EstablishErrorCodeTraces --
  *
  *	Creates traces on the ::errorCode variable to keep its value
- *	consistent with the expectation of legacy code.
+ *	consistent with the expectations of legacy code.
  *
  * Results:
  *	None.
@@ -535,6 +541,7 @@
  *
  *----------------------------------------------------------------------
  */
+
 static char *
 EstablishErrorCodeTraces(clientData, interp, name1, name2, flags)
     ClientData clientData;
@@ -549,6 +556,23 @@
 	    EstablishErrorCodeTraces, (ClientData) NULL);
     return NULL;
 }
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ErrorCodeRead --
+ *
+ *	Called when the ::errorCode variable is read.  Copies the
+ *	current value of the interp's errorCode field into ::errorCode.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
 
 static char *
 ErrorCodeRead(clientData, interp, name1, name2, flags)
@@ -562,8 +586,72 @@
 
     if (flags & TCL_INTERP_DESTROYED) return NULL;
     if (iPtr->errorCode == NULL) return NULL;
-    Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorCode, NULL,
-	    iPtr->errorCode, TCL_GLOBAL_ONLY);
+    Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL, iPtr->errorCode, TCL_GLOBAL_ONLY);
+    return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EstablishErrorInfoTraces --
+ *
+ *	Creates traces on the ::errorInfo variable to keep its value
+ *	consistent with the expectations of legacy code.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Read and unset traces are established on ::errorInfo.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+EstablishErrorInfoTraces(clientData, interp, name1, name2, flags)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    CONST char *name1;
+    CONST char *name2;
+    int flags;
+{
+    Tcl_TraceVar(interp, "errorInfo", TCL_GLOBAL_ONLY | TCL_TRACE_READS,
+	    ErrorInfoRead, (ClientData) NULL);
+    Tcl_TraceVar(interp, "errorInfo", TCL_GLOBAL_ONLY | TCL_TRACE_UNSETS,
+	    EstablishErrorInfoTraces, (ClientData) NULL);
+    return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ErrorInfoRead --
+ *
+ *	Called when the ::errorInfo variable is read.  Copies the
+ *	current value of the interp's errorInfo field into ::errorInfo.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+ErrorInfoRead(clientData, interp, name1, name2, flags)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    CONST char *name1;
+    CONST char *name2;
+    int flags;
+{
+    Interp *iPtr = (Interp *)interp;
+
+    if (flags & TCL_INTERP_DESTROYED) return NULL;
+    if (iPtr->errorInfo == NULL) return NULL;
+    Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL, iPtr->errorInfo, TCL_GLOBAL_ONLY);
     return NULL;
 }
 
@@ -705,9 +793,10 @@
     } else {
 	/* 
 	 * In the global namespace create traces to maintain the
-	 * ::errorCode variable.
+	 * ::errorInfo and ::errorCode variables.
 	 */
 	iPtr->globalNsPtr = nsPtr;
+	EstablishErrorInfoTraces(NULL, interp, NULL, NULL, 0);
 	EstablishErrorCodeTraces(NULL, interp, NULL, NULL, 0);
     }
 
@@ -829,11 +918,11 @@
         TclTeardownNamespace(nsPtr);
 
         if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
-            /*
+	    /*
 	     * If this is the global namespace, then it may have residual
-             * "errorInfo" and "errorCode" variables for errors that
-             * occurred while it was being torn down.  Try to clear the
-             * variable list one last time.
+	     * "errorInfo" and "errorCode" variables for errors that
+	     * occurred while it was being torn down.  Try to clear the
+	     * variable list one last time.
 	     */
 
             TclDeleteVars((Interp *) nsPtr->interp, &nsPtr->varTable);
@@ -852,7 +941,8 @@
                 nsPtr->flags |= NS_DEAD;
             }
         } else {
-	    /* Restore the ::errorCode traces */
+	    /* Restore the ::errorInfo and ::errorCode traces */
+	    EstablishErrorInfoTraces(NULL, nsPtr->interp, NULL, NULL, 0);
 	    EstablishErrorCodeTraces(NULL, nsPtr->interp, NULL, NULL, 0);
 	}
     }
@@ -868,9 +958,7 @@
  *	commands, variables, and child namespaces.
  *
  *	This is kept separate from Tcl_DeleteNamespace so that the global
- *	namespace can be handled specially. Global variables like
- *	"errorInfo" and "errorCode" need to remain intact while other
- *	namespaces and commands are torn down, in case any errors occur.
+ *	namespace can be handled specially. 
  *
  * Results:
  *	None.
@@ -878,8 +966,6 @@
  * Side effects:
  *	Removes this namespace from its parent's child namespace hashtable.
  *	Deletes all commands, variables and namespaces in this namespace.
- *	If this is the global namespace, the "errorInfo" and "errorCode"
- *	variables are left alone and deleted later.
  *
  *----------------------------------------------------------------------
  */
@@ -894,47 +980,17 @@
     Tcl_HashSearch search;
     Tcl_Namespace *childNsPtr;
     Tcl_Command cmd;
-    Namespace *globalNsPtr =
-	    (Namespace *) Tcl_GetGlobalNamespace((Tcl_Interp *) iPtr);
     int i;
 
     /*
      * Start by destroying the namespace's variable table,
      * since variables might trigger traces.
+     * Variable table should be cleared but not freed!
+     * TclDeleteVars frees it, so we reinitialize it afterwards.
      */
 
-    if (nsPtr == globalNsPtr) {
-	/*
-	 * This is the global namespace.  Tearing it down will destroy the
-	 * ::errorInfo variable.  We save and restore it 
-	 * in case there are any errors in progress, so the error details
-	 * it contains will not be lost.  See test namespace-8.5
-	 */
-
-	Tcl_Obj *errorInfo = Tcl_GetVar2Ex(nsPtr->interp, "errorInfo",
-		NULL, TCL_GLOBAL_ONLY);
-			                
-	if (errorInfo) {
-	    Tcl_IncrRefCount(errorInfo);
-	}   
-
-	TclDeleteVars(iPtr, &nsPtr->varTable);
-	Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
-
-	if (errorInfo) {
-	    Tcl_SetVar2Ex(nsPtr->interp, "errorInfo", NULL,
-		    errorInfo, TCL_GLOBAL_ONLY);
-	    Tcl_DecrRefCount(errorInfo);
-	}   
-    } else {
-	/*
-	 * Variable table should be cleared but not freed! TclDeleteVars
-	 * frees it, so we reinitialize it afterwards.
-	 */
-
-        TclDeleteVars(iPtr, &nsPtr->varTable);
-        Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
-    }
+    TclDeleteVars(iPtr, &nsPtr->varTable);
+    Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
 
     /*
      * Remove the namespace from its parent's child hashtable.
Index: generic/tclProc.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclProc.c,v
retrieving revision 1.59
diff -u -r1.59 tclProc.c
--- generic/tclProc.c	6 Oct 2004 10:11:05 -0000	1.59
+++ generic/tclProc.c	15 Oct 2004 03:55:44 -0000
@@ -1295,7 +1295,7 @@
  * Side effects:
  *	If the result returned is TCL_ERROR, traceback information about
  *	the procedure just executed is appended to the interpreter's
- *	"errorInfo" variable.
+ *	errorInfo field.
  *
  *----------------------------------------------------------------------
  */
@@ -1439,7 +1439,7 @@
  *	the procedure, instead of TCL_RETURN.
  *
  * Side effects:
- *	The errorInfo and errorCode variables may get modified.
+ *	The errorInfo and errorCode fields may get set.
  *
  *----------------------------------------------------------------------
  */
@@ -1481,9 +1481,8 @@
 	Tcl_DictObjGet(NULL, iPtr->returnOpts,
 		iPtr->returnErrorinfoKey, &valuePtr);
 	if (valuePtr != NULL) {
-	    Tcl_ObjSetVar2((Tcl_Interp *) iPtr, iPtr->execEnvPtr->errorInfo,
-	            NULL, valuePtr, TCL_GLOBAL_ONLY);
-	    iPtr->flags |= ERR_IN_PROGRESS;
+	    iPtr->errorInfo = valuePtr;
+	    Tcl_IncrRefCount(iPtr->errorInfo);
 	}
     }
     return code;
Index: generic/tclResult.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclResult.c,v
retrieving revision 1.14
diff -u -r1.14 tclResult.c
--- generic/tclResult.c	6 Oct 2004 15:59:25 -0000	1.14
+++ generic/tclResult.c	15 Oct 2004 03:55:46 -0000
@@ -732,12 +732,20 @@
     iPtr->result = iPtr->resultSpace;
     iPtr->resultSpace[0] = 0;
     if (iPtr->errorCode) {
-	Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorCode, NULL,
+	/* Legacy support */
+	Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL,
 		iPtr->errorCode, TCL_GLOBAL_ONLY);
 	Tcl_DecrRefCount(iPtr->errorCode);
 	iPtr->errorCode = NULL;
     }
-    iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS);
+    if (iPtr->errorInfo) {
+	/* Legacy support*/
+	Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
+		iPtr->errorInfo, TCL_GLOBAL_ONLY);
+	Tcl_DecrRefCount(iPtr->errorInfo);
+	iPtr->errorInfo = NULL;
+    }
+    iPtr->flags &= ~ERR_ALREADY_LOGGED;
 }
 
 /*
@@ -794,26 +802,23 @@
  *	None.
  *
  * Side effects:
- *	The errorCode global variable is modified to hold all of the
+ *	The errorCode field of the interp is modified to hold all of the
  *	arguments to this procedure, in a list form with each argument
- *	becoming one element of the list.  A flag is set internally
- *	to remember that errorCode has been set, so the variable doesn't
- *	get set automatically when the error is returned.
+ *	becoming one element of the list.  
  *
  *----------------------------------------------------------------------
  */
 
 void
 Tcl_SetErrorCodeVA (interp, argList)
-    Tcl_Interp *interp;		/* Interpreter in which to access the errorCode
-				 * variable. */
+    Tcl_Interp *interp;		/* Interpreter in which to set errorCode */
     va_list argList;		/* Variable argument list. */
 {
     Tcl_Obj *errorObj = Tcl_NewObj();
 
     /*
      * Scan through the arguments one at a time, appending them to
-     * $errorCode as list elements.
+     * the errorCode field as list elements.
      */
 
     while (1) {
@@ -838,11 +843,9 @@
  *	None.
  *
  * Side effects:
- *	The errorCode global variable is modified to hold all of the
+ *	The errorCode field of the interp is modified to hold all of the
  *	arguments to this procedure, in a list form with each argument
- *	becoming one element of the list.  A flag is set internally
- *	to remember that errorCode has been set, so the variable doesn't
- *	get set automatically when the error is returned.
+ *	becoming one element of the list.  
  *
  *----------------------------------------------------------------------
  */
@@ -855,7 +858,7 @@
 
     /*
      * Scan through the arguments one at a time, appending them to
-     * $errorCode as list elements.
+     * the errorCode field as list elements.
      */
 
     interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
@@ -876,10 +879,7 @@
  *	None.
  *
  * Side effects:
- *	The errorCode global variable is modified to be the new value.
- *	A flag is set internally to remember that errorCode has been
- *	set, so the variable doesn't get set automatically when the
- *	error is returned.
+ *	The errorCode field of the interp is set to the new value.
  *
  *----------------------------------------------------------------------
  */
@@ -917,9 +917,9 @@
  *
  * Results:
  *	The target interp's result is set to a copy of the source interp's
- *	result.  The source's error information "$errorInfo" may be
- *	appended to the target's error information and the source's error
- *	code "$errorCode" may be stored in the target's error code.
+ *	result.  The source's errorInfo field may be transferred to the
+ *	target's errorInfo field, and the source's errorCode field may be
+ *	transferred to the target's errorCode field.
  *
  * Side effects:
  *	None.
@@ -963,17 +963,13 @@
         
         Tcl_ResetResult(targetInterp);
         
-	objPtr = Tcl_GetVar2Ex(sourceInterp, "errorInfo", NULL,
-		TCL_GLOBAL_ONLY);
-	if (objPtr) {
-	    Tcl_SetVar2Ex(targetInterp, "errorInfo", NULL, objPtr,
-		    TCL_GLOBAL_ONLY);
-	    ((Interp *) targetInterp)->flags |= ERR_IN_PROGRESS;
+	if (iPtr->errorInfo) {
+	    ((Interp *) targetInterp)->errorInfo = iPtr->errorInfo;
+	    Tcl_IncrRefCount(((Interp *) targetInterp)->errorInfo);
 	}
 
-	objPtr = ((Interp *) sourceInterp)->errorCode;
-	if (objPtr) {
-	    Tcl_SetObjErrorCode(targetInterp, objPtr);
+	if (iPtr->errorCode) {
+	    Tcl_SetObjErrorCode(targetInterp, iPtr->errorCode);
 	}
     }
 
Index: generic/tclTrace.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclTrace.c,v
retrieving revision 1.15
diff -u -r1.15 tclTrace.c
--- generic/tclTrace.c	6 Oct 2004 15:59:25 -0000	1.15
+++ generic/tclTrace.c	15 Oct 2004 03:55:52 -0000
@@ -2413,8 +2413,8 @@
  *      Returns TCL_OK to indicate normal operation.  Returns TCL_ERROR
  *      if invocation of a trace procedure indicated an error.  When
  *      TCL_ERROR is returned and leaveErrMsg is true, then the
- *      ::errorInfo variable of iPtr has information about the error
- *      appended to it.
+ *      errorInfo field of iPtr has information about the error
+ *      placed in it.
  *
  * Side effects:
  *	Almost anything can happen, depending on trace; this procedure
@@ -2450,10 +2450,13 @@
     int copiedName;
     int code = TCL_OK;
     int disposeFlags = 0;
-    int saveErrFlags = iPtr->flags
-	    & (ERR_IN_PROGRESS | ERR_ALREADY_LOGGED);
+    int saveErrFlags = iPtr->flags & ERR_ALREADY_LOGGED;
+    Tcl_Obj *saveErrInfo = iPtr->errorInfo;
     Tcl_Obj *saveErrCode = iPtr->errorCode;
 
+    if (saveErrInfo) {
+	Tcl_IncrRefCount(saveErrInfo);
+    }
     if (saveErrCode) {
 	Tcl_IncrRefCount(saveErrCode);
     }
@@ -2581,12 +2584,21 @@
     done:
     if (code == TCL_OK) {
 	iPtr->flags |= saveErrFlags;
+	if (iPtr->errorInfo) {
+	    Tcl_DecrRefCount(iPtr->errorInfo);
+	}
+	iPtr->errorInfo = saveErrInfo;
 	if (iPtr->errorCode) {
 	    Tcl_DecrRefCount(iPtr->errorCode);
 	}
 	iPtr->errorCode = saveErrCode;
-    } else if (saveErrCode) {
-	Tcl_DecrRefCount(saveErrCode);
+    } else {
+	if (saveErrInfo) {
+	    Tcl_DecrRefCount(saveErrInfo);
+	}
+	if (saveErrCode) {
+	    Tcl_DecrRefCount(saveErrCode);
+	}
     }
     if (code == TCL_ERROR) {
 	if (leaveErrMsg) {