Tcl Source Code

Artifact [d7eaef9221]
Login

Artifact d7eaef9221ec5407bc099bcf8529a4fc6287aa5e:

Attachment "1017299.patch" to ticket [1017299fff] added by dgp 2004-09-10 00:02:33.
Index: generic/tclNamesp.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclNamesp.c,v
retrieving revision 1.49
diff -u -r1.49 tclNamesp.c
--- generic/tclNamesp.c	9 Sep 2004 15:44:23 -0000	1.49
+++ generic/tclNamesp.c	9 Sep 2004 16:55:55 -0000
@@ -1273,7 +1273,7 @@
     char *cmdName;
     register Tcl_HashEntry *hPtr;
     Tcl_HashSearch search;
-    Command *cmdPtr, *realCmdPtr;
+    Command *cmdPtr;
     ImportRef *refPtr;
     Tcl_Command autoCmd, importedCmd;
     ImportedCmdData *dataPtr;
@@ -1373,6 +1373,7 @@
 	     * pattern. Check whether it was exported. If it wasn't,
 	     * we ignore it.
 	     */
+	    Tcl_HashEntry *found;
 
 	    wasExported = 0;
 	    for (i = 0;  i < importNsPtr->numExportPatterns;  i++) {
@@ -1390,8 +1391,9 @@
 	     * in the current namespace that refers to cmdPtr.
 	     */
 
-            if ((Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName) == NULL)
-		    || allowOverwrite) {
+
+            found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
+            if ((found == NULL) || allowOverwrite) {
 		/*
 		 * Create the imported command and its client data.
 		 * To create the new command in the current namespace, 
@@ -1409,25 +1411,30 @@
 
 		/*
 		 * Check whether creating the new imported command in the
-		 * current namespace would create a cycle of imported->real
-		 * command references that also would destroy an existing
-		 * "real" command already in the current namespace.
+		 * current namespace would create a cycle of imported
+		 * command references.
 		 */
 
 		cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
-		if (cmdPtr->deleteProc == DeleteImportedCmd) {
-		    realCmdPtr = (Command *) TclGetOriginalCommand(
-			    (Tcl_Command) cmdPtr);
-		    if ((realCmdPtr != NULL)
-			    && (realCmdPtr->nsPtr == currNsPtr)
-			    && (Tcl_FindHashEntry(&currNsPtr->cmdTable,
-			            cmdName) != NULL)) {
-			Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
-			        "import pattern \"", pattern,
-				"\" would create a loop containing command \"",
-				Tcl_DStringValue(&ds), "\"", (char *) NULL);
-			Tcl_DStringFree(&ds);
-			return TCL_ERROR;
+		if ((found != NULL)
+			&& cmdPtr->deleteProc == DeleteImportedCmd) {
+
+		    Command *overwrite = (Command *) Tcl_GetHashValue(found);
+		    Command *link = cmdPtr;
+		    while (link->deleteProc == DeleteImportedCmd) {
+			ImportedCmdData *dataPtr;
+		       
+			dataPtr = (ImportedCmdData *) link->objClientData;
+			link = dataPtr->realCmdPtr;
+			if (overwrite == link) {
+			    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+				    "import pattern \"", pattern,
+				    "\" would create a loop containing ",
+				    "command \"", Tcl_DStringValue(&ds),
+				    "\"", (char *) NULL);
+			    Tcl_DStringFree(&ds);
+			    return TCL_ERROR;
+			}
 		    }
 		}
 
Index: tests/namespace.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/namespace.test,v
retrieving revision 1.35
diff -u -r1.35 namespace.test
--- tests/namespace.test	9 Sep 2004 15:44:23 -0000	1.35
+++ tests/namespace.test	9 Sep 2004 16:55:57 -0000
@@ -244,6 +244,50 @@
          [test_ns_export::cmd1 j k l]
 } {{cmd1: a b c} {cmd1: d e f} {} ::test_ns_export::cmd1 ::test_ns_export::cmd1 {new1: g h i} {new1: j k l}}
 
+test namespace-9.8 {Tcl_Import: Bug 1017299} -setup {
+    namespace eval one {
+	namespace export cmd
+	proc cmd {} {}
+    }
+    namespace eval two {
+	namespace export cmd
+	proc other args {}
+    }
+    namespace eval two \
+	    [list namespace import [namespace current]::one::cmd]
+    namespace eval three \
+	    [list namespace import [namespace current]::two::cmd]
+    namespace eval three {
+	rename cmd other
+	namespace export other
+    }
+} -body {
+    namespace eval two [list namespace import -force \
+	    [namespace current]::three::other]
+    namespace origin two::other
+} -cleanup {
+    namespace delete one two three
+} -match glob -result *::one::cmd
+
+test namespace-9.9 {Tcl_Import: Bug 1017299} -setup {
+    namespace eval one {
+	namespace export cmd
+	proc cmd {} {}
+    }
+    namespace eval two namespace export cmd
+    namespace eval two \
+	    [list namespace import [namespace current]::one::cmd]
+    namespace eval three namespace export cmd
+    namespace eval three \
+	    [list namespace import [namespace current]::two::cmd]
+} -body {
+    namespace eval two [list namespace import -force \
+	    [namespace current]::three::cmd]
+    namespace origin two::cmd
+} -cleanup {
+    namespace delete one two three
+} -returnCodes error -match glob -result {import pattern * would create a loop*}
+
 test namespace-10.1 {Tcl_ForgetImport, check for valid namespaces} {
     catch {namespace delete {expand}[namespace children :: test_ns_*]}
     list [catch {namespace forget xyzzy::*} msg] $msg