Tcl Source Code

Artifact [3a515c0341]
Login

Artifact 3a515c03411225e24b85a906859f463c743386a2:

Attachment "execErr.patch" to ticket [536997ffff] added by msofer 2002-03-30 09:28:35.
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.51
diff -u -r1.51 tclExecute.c
--- generic/tclExecute.c	29 Mar 2002 21:01:12 -0000	1.51
+++ generic/tclExecute.c	30 Mar 2002 01:52:26 -0000
@@ -824,10 +824,6 @@
 {
     register Interp *iPtr = (Interp *) interp;
     register ByteCode* codePtr;		/* Tcl Internal type of bytecode. */
-    int oldCount = iPtr->cmdCount;	/* Used to tell whether any commands
-					 * at all were executed. */
-    char *script;
-    int numSrcBytes;
     int result;
     Namespace *namespacePtr;
 
@@ -882,94 +878,48 @@
                     panic("Tcl_EvalObj: compiled script jumped interps");
                 }
 	        codePtr->compileEpoch = iPtr->compileEpoch;
+		goto doExecuteBC;
             } else {
                 tclByteCodeType.freeIntRepProc(objPtr);
             }
+	} else {
+	    goto doExecuteBC;
 	}
     }
-    if (objPtr->typePtr != &tclByteCodeType) {
-	iPtr->errorLine = 1; 
-	result = tclByteCodeType.setFromAnyProc(interp, objPtr);
-	if (result != TCL_OK) {
-	    return result;
-	}
-    } else {
-	codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
-	if (((Interp *) *codePtr->interpHandle != iPtr)
-	        || (codePtr->compileEpoch != iPtr->compileEpoch)) {
-	    (*tclByteCodeType.freeIntRepProc)(objPtr);
-	    iPtr->errorLine = 1; 
-	    result = (*tclByteCodeType.setFromAnyProc)(interp, objPtr);
-	    if (result != TCL_OK) {
-		return result;
-	    }
-	}
+
+    iPtr->errorLine = 1; 
+    result = tclByteCodeType.setFromAnyProc(interp, objPtr);
+    if (result != TCL_OK) {
+	return result;
     }
     codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
 
     /*
-     * Extract then reset the compilation flags in the interpreter.
      * Resetting the flags must be done after any compilation.
      */
 
     iPtr->evalFlags = 0;
 
     /*
-     * Execute the commands. If the code was compiled from an empty string,
-     * don't bother executing the code.
-     */
-
-    numSrcBytes = codePtr->numSrcBytes;
-    if ((numSrcBytes > 0) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
-	/*
-	 * Increment the code's ref count while it is being executed. If
-	 * afterwards no references to it remain, free the code.
-	 */
-	
-	codePtr->refCount++;
-	iPtr->numLevels++;
-	result = TclExecuteByteCode(interp, codePtr);
-	iPtr->numLevels--;
-	codePtr->refCount--;
-	if (codePtr->refCount <= 0) {
-	    TclCleanupByteCode(codePtr);
-	}
-    } else {
-	result = TCL_OK;
-    }
-
-    /*
-     * If no commands at all were executed, check for asynchronous
-     * handlers so that they at least get one change to execute.
-     * This is needed to handle event loops written in Tcl with
-     * empty bodies.
+     * Execute the commands. Increment the code's ref count while 
+     * it is being executed. If afterwards no references to it remain, 
+     * free the code. Set the interpreter's termOffset member to the 
+     * offset of the character just after the last one executed. We 
+     * approximate the offset of the last character executed by using 
+     * the number of characters compiled. 
      */
 
-    if ((oldCount == iPtr->cmdCount) && Tcl_AsyncReady()) {
-	result = Tcl_AsyncInvoke(interp, result);
-    
-
-	/*
-	 * If an error occurred, record information about what was being
-	 * executed when the error occurred.
-	 */
-	
-	if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
-	    script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
-	    Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
-	}
+    doExecuteBC:
+    codePtr->refCount++;
+    iPtr->numLevels++;
+    result = TclExecuteByteCode(interp, codePtr);
+    iPtr->numLevels--;
+    iPtr->termOffset = codePtr->numSrcBytes;
+    codePtr->refCount--;
+    if (codePtr->refCount <= 0) {
+	TclCleanupByteCode(codePtr);
     }
-
-    /*
-     * Set the interpreter's termOffset member to the offset of the
-     * character just after the last one executed. We approximate the offset
-     * of the last character executed by using the number of characters
-     * compiled. 
-     */
-
-    iPtr->termOffset = numSrcBytes;
     iPtr->flags &= ~ERR_ALREADY_LOGGED;
-
     return result;
 }
 
@@ -1022,6 +972,7 @@
     char *bytes;
     int length;
     long i = 0;			/* Init. avoids compiler warning. */
+    int asyncCalled = 0;
 #ifndef TCL_WIDE_INT_IS_LONG
     Tcl_WideInt w;
 #endif
@@ -1283,6 +1234,7 @@
 		Tcl_ResetResult(interp);
 		DECACHE_STACK_INFO();
 		result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0);
+		asyncCalled = 1;
 		CACHE_STACK_INFO();
 
 		/*
@@ -1398,6 +1350,7 @@
 	    objPtr = POP_OBJECT();
 	    DECACHE_STACK_INFO();
 	    result = TclCompEvalObj(interp, objPtr);
+	    asyncCalled = 1;
 	    CACHE_STACK_INFO();
 	    if (result == TCL_OK) {
 		/*
@@ -4383,15 +4336,34 @@
 	panic("TclExecuteByteCode execution failure: end stack top < start stack top");
     }
 	
+    done:
     /*
      * Free the catch stack array if malloc'ed storage was used.
      */
 
-    done:
     if (catchStackPtr != catchStackStorage) {
 	ckfree((char *) catchStackPtr);
     }
     eePtr->stackTop = initStackTop;
+
+    /*
+     * If no commands at all were executed, check for asynchronous
+     * handlers so that they at least get one change to execute.
+     * This is needed to handle event loops written in Tcl with
+     * empty bodies. 
+     */
+
+    if ((!asyncCalled) && Tcl_AsyncReady()) {
+	result = Tcl_AsyncInvoke(interp, result);
+	if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
+	    bytes = GetSrcInfoForPc(pc, codePtr, &length);
+	    if (bytes != NULL) {
+		Tcl_LogCommandInfo(interp, codePtr->source, bytes, length);
+		iPtr->flags |= ERR_ALREADY_LOGGED;
+	    }
+	}
+    }    
+
     return result;
 #undef STATIC_CATCH_STACK_SIZE
 }