Tcl Source Code

Artifact [98d02cd7a4]
Login

Artifact 98d02cd7a43aa6b2cb66933fd6e1bd935cad7ceb:

Attachment "1444291.patch" to ticket [1444291fff] added by dgp 2006-03-07 04:39:28.
Index: generic/tclBasic.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclBasic.c,v
retrieving revision 1.75.2.20
diff -u -r1.75.2.20 tclBasic.c
--- generic/tclBasic.c	28 Feb 2006 15:44:35 -0000	1.75.2.20
+++ generic/tclBasic.c	6 Mar 2006 21:37:11 -0000
@@ -2984,6 +2984,7 @@
     int code = TCL_OK;
     int traceCode = TCL_OK;
     int checkTraces = 1;
+    Namespace *savedNsPtr = NULL;
 
     if (TclInterpReady(interp) == TCL_ERROR) {
 	return TCL_ERROR;
@@ -2993,6 +2994,15 @@
 	return TCL_OK;
     }
 
+    /* Configure evaluation context to match the requested flags */
+    savedVarFramePtr = iPtr->varFramePtr;
+    if (flags & TCL_EVAL_GLOBAL) {
+	iPtr->varFramePtr = NULL;
+    } else if ((flags & TCL_EVAL_INVOKE) && iPtr->varFramePtr) {
+	savedNsPtr = iPtr->varFramePtr->nsPtr;
+	iPtr->varFramePtr->nsPtr = iPtr->globalNsPtr;
+    }
+
     /*
      * If any execution traces rename or delete the current command,
      * we may need (at most) two passes here.
@@ -3005,19 +3015,8 @@
          * word array with "unknown" as the first word and the original
          * command words as arguments.  Then call ourselves recursively
          * to execute it.
-	 *
-	 * If caller requests, or if we're resolving the target end of
-	 * an interpeter alias (TCL_EVAL_INVOKE), be sure to do command
-	 * name resolution in the global namespace.
          */
-
-	savedVarFramePtr = iPtr->varFramePtr;
-	if (flags & (TCL_EVAL_INVOKE | TCL_EVAL_GLOBAL)) {
-	    iPtr->varFramePtr = NULL;
-	}
         cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
-	iPtr->varFramePtr = savedVarFramePtr;
-
         if (cmdPtr == NULL) {
 	    newObjv = (Tcl_Obj **) ckalloc((unsigned)
 		((objc + 1) * sizeof (Tcl_Obj *)));
@@ -3035,13 +3034,19 @@
 	    } else {
 	        iPtr->numLevels++;
 	        code = TclEvalObjvInternal(interp, objc+1, newObjv,
-			command, length, flags);
+			command, length, 0);
 	        iPtr->numLevels--;
 	    }
 	    Tcl_DecrRefCount(newObjv[0]);
 	    ckfree((char *) newObjv);
+	    if (savedNsPtr) {
+		iPtr->varFramePtr->nsPtr = savedNsPtr;
+	    }
 	    goto done;
         }
+	if (savedNsPtr) {
+	    iPtr->varFramePtr->nsPtr = savedNsPtr;
+	}
     
         /*
          * Call trace procedures if needed.
@@ -3054,10 +3059,6 @@
              * any existing traces, then the set checkTraces to 0 and
              * go through this while loop one more time.
              */
-	    savedVarFramePtr = iPtr->varFramePtr;
-	    if (flags & TCL_EVAL_GLOBAL) {
-		iPtr->varFramePtr = NULL;
-	    }
             if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
                 traceCode = TclCheckInterpTraces(interp, command, length,
                                cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
@@ -3067,7 +3068,6 @@
                 traceCode = TclCheckExecutionTraces(interp, command, length,
                                cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
             }
-	    iPtr->varFramePtr = savedVarFramePtr;
             cmdPtr->refCount--;
             if (cmdEpoch != cmdPtr->cmdEpoch) {
                 /* The command has been modified in some way */
@@ -3084,12 +3084,7 @@
     cmdPtr->refCount++;
     iPtr->cmdCount++;
     if ( code == TCL_OK && traceCode == TCL_OK) {
-	savedVarFramePtr = iPtr->varFramePtr;
-	if (flags & TCL_EVAL_GLOBAL) {
-	    iPtr->varFramePtr = NULL;
-	}
 	code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
-	iPtr->varFramePtr = savedVarFramePtr;
     }
     if (Tcl_AsyncReady()) {
 	code = Tcl_AsyncInvoke(interp, code);
@@ -3101,10 +3096,6 @@
     if (!(cmdPtr->flags & CMD_IS_DELETED)) {
 	int saveErrFlags = iPtr->flags 
 		& (ERR_IN_PROGRESS | ERR_ALREADY_LOGGED | ERROR_CODE_SET);
-	savedVarFramePtr = iPtr->varFramePtr;
-	if (flags & TCL_EVAL_GLOBAL) {
-	    iPtr->varFramePtr = NULL;
-	}
         if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) {
             traceCode = TclCheckExecutionTraces (interp, command, length,
                    cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
@@ -3113,7 +3104,6 @@
             traceCode = TclCheckInterpTraces(interp, command, length,
                    cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
         }
-	iPtr->varFramePtr = savedVarFramePtr;
 	if (traceCode == TCL_OK) {
 	    iPtr->flags |= saveErrFlags;
 	}
@@ -3143,6 +3133,7 @@
     }
 
     done:
+    iPtr->varFramePtr = savedVarFramePtr;
     return code;
 }
 
Index: tests/parse.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/parse.test,v
retrieving revision 1.11.2.3
diff -u -r1.11.2.3 parse.test
--- tests/parse.test	28 Feb 2006 15:44:36 -0000	1.11.2.3
+++ tests/parse.test	6 Mar 2006 21:37:12 -0000
@@ -312,7 +312,27 @@
     rename ::unknown {}
     rename unknown.save ::unknown
     set ::info
-} [subst {[set level 2; incr level [info level]] namespace 1 global 1 global}]
+} [subst {[set level 2; incr level [info level]] global 1 global 1 global}]
+test parse-8.12 {Tcl_EvalObjv procedure, TCL_EVAL_INVOKE} {
+    set ::auto_index(noSuchCommand) {
+	proc noSuchCommand {} {lappend ::info global}
+    }
+    set ::auto_index(::[string trimleft [namespace current]::test_ns_1::noSuchCommand :]) [list \
+	proc [namespace current]::test_ns_1::noSuchCommand {} {
+	    lappend ::info ns
+	}]
+    catch {rename ::noSuchCommand {}}
+    set ::slave [interp create]
+    $::slave alias bar noSuchCommand
+    set ::info {}
+    namespace eval test_ns_1 {
+	$::slave eval bar
+    }
+    namespace delete test_ns_1
+    interp delete $::slave
+    catch {rename ::noSuchCommand {}}
+    set ::info
+} global
 
 test parse-9.1 {Tcl_LogCommandInfo, line numbers} {
     catch {unset x}