Tcl Source Code

Artifact [a4e82adca4]
Login

Artifact a4e82adca4427e2b5ab3fa923fbd09328949f87d:

Attachment "core84.patch" to ticket [800106ffff] added by vincentdarley 2003-10-14 00:16:08.
? core84.patch
Index: generic/tcl.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tcl.h,v
retrieving revision 1.153.2.7
diff -u -r1.153.2.7 tcl.h
--- generic/tcl.h	2 Oct 2003 23:07:33 -0000	1.153.2.7
+++ generic/tcl.h	13 Oct 2003 17:15:00 -0000
@@ -1591,6 +1591,7 @@
 #define TCL_GLOB_TYPE_FILE		(1<<4)
 #define TCL_GLOB_TYPE_LINK		(1<<5)
 #define TCL_GLOB_TYPE_SOCK		(1<<6)
+#define TCL_GLOB_TYPE_MOUNT		(1<<7)
 
 #define TCL_GLOB_PERM_RONLY		(1<<0)
 #define TCL_GLOB_PERM_HIDDEN		(1<<1)
Index: generic/tclIOUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIOUtil.c,v
retrieving revision 1.77.2.10
diff -u -r1.77.2.10 tclIOUtil.c
--- generic/tclIOUtil.c	6 Oct 2003 09:49:20 -0000	1.77.2.10
+++ generic/tclIOUtil.c	13 Oct 2003 17:15:01 -0000
@@ -102,6 +102,10 @@
 
 static FilesystemRecord* FsGetFirstFilesystem(void);
 static void FsThrExitProc(ClientData cd);
+static Tcl_Obj* FsListMounts          _ANSI_ARGS_((Tcl_Obj *pathPtr, 
+						   CONST char *pattern));
+static Tcl_Obj* FsAddMountsToGlobResult  _ANSI_ARGS_((Tcl_Obj *result, 
+	   Tcl_Obj *pathPtr, CONST char *pattern, Tcl_GlobTypeData *types));
 
 #ifdef TCL_THREADS
 static void FsRecacheFilesystemList(void);
@@ -1008,7 +1012,12 @@
     if (fsPtr != NULL) {
 	Tcl_FSMatchInDirectoryProc *proc = fsPtr->matchInDirectoryProc;
 	if (proc != NULL) {
-	    return (*proc)(interp, result, pathPtr, pattern, types);
+	    int ret = (*proc)(interp, result, pathPtr, pattern, types);
+	    if (ret == TCL_OK && pattern != NULL) {
+		result = FsAddMountsToGlobResult(result, pathPtr, 
+						 pattern, types);
+	    }
+	    return ret;
 	}
     } else {
 	Tcl_Obj* cwd;
@@ -1053,6 +1062,9 @@
 		if (ret == TCL_OK) {
 		    int resLength;
 
+		    tmpResultPtr = FsAddMountsToGlobResult(tmpResultPtr, cwd,
+							   pattern, types);
+
 		    ret = Tcl_ListObjLength(interp, tmpResultPtr, &resLength);
 		    if (ret == TCL_OK) {
 			int i;
@@ -1079,6 +1091,92 @@
 /*
  *----------------------------------------------------------------------
  *
+ * FsAddMountsToGlobResult --
+ *
+ *	This routine is used by the globbing code to take the results
+ *	of a directory listing and add any mounted paths to that
+ *	listing.  This is required so that simple things like 
+ *	'glob *' merge mounts and listings correctly.
+ *	
+ * Results: 
+ *	
+ *	The passed in 'result' may be modified (in place, if
+ *	necessary), and the correct list is returned.
+ *
+ * Side effects:
+ *	None.
+ *
+ *---------------------------------------------------------------------- 
+ */
+static Tcl_Obj*
+FsAddMountsToGlobResult(result, pathPtr, pattern, types)
+    Tcl_Obj *result;    /* The current list of matching paths */
+    Tcl_Obj *pathPtr;   /* The directory in question */
+    CONST char *pattern;
+    Tcl_GlobTypeData *types;
+{
+    int mLength, gLength, i;
+    int dir = (types == NULL || (types->type & TCL_GLOB_TYPE_DIR));
+    Tcl_Obj *mounts = FsListMounts(pathPtr, pattern);
+
+    if (mounts == NULL) return result; 
+
+    if (Tcl_ListObjLength(NULL, mounts, &mLength) != TCL_OK || mLength == 0) {
+	goto endOfMounts;
+    }
+    if (Tcl_ListObjLength(NULL, result, &gLength) != TCL_OK) {
+	goto endOfMounts;
+    }
+    for (i = 0; i < mLength; i++) {
+	Tcl_Obj *mElt;
+	int j;
+	int found = 0;
+	
+	Tcl_ListObjIndex(NULL, mounts, i, &mElt);
+
+	for (j = 0; j < gLength; j++) {
+	    Tcl_Obj *gElt;
+	    Tcl_ListObjIndex(NULL, result, j, &gElt);
+	    if (Tcl_FSEqualPaths(mElt, gElt)) {
+		found = 1;
+		if (!dir) {
+		    /* We don't want to list this */
+		    if (Tcl_IsShared(result)) {
+			Tcl_Obj *newList;
+			newList = Tcl_DuplicateObj(result);
+			Tcl_DecrRefCount(result);
+			result = newList;
+		    }
+		    Tcl_ListObjReplace(NULL, result, j, 1, 0, NULL);
+		    gLength--;
+		}
+		/* Break out of for loop */
+		break;
+	    }
+	}
+	if (!found && dir) {
+	    if (Tcl_IsShared(result)) {
+		Tcl_Obj *newList;
+		newList = Tcl_DuplicateObj(result);
+		Tcl_DecrRefCount(result);
+		result = newList;
+	    }
+	    Tcl_ListObjAppendElement(NULL, result, mElt);
+	    /* 
+	     * No need to increment gLength, since we
+	     * don't want to compare mounts against
+	     * mounts.
+	     */
+	}
+    }
+  endOfMounts:
+    Tcl_DecrRefCount(mounts);
+    return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
  * Tcl_FSMountsChanged --
  *
  *    Notify the filesystem that the available mounted filesystems
@@ -3016,6 +3114,59 @@
 	    if (thisFsVolumes != NULL) {
 		Tcl_ListObjAppendList(NULL, resultPtr, thisFsVolumes);
 		Tcl_DecrRefCount(thisFsVolumes);
+	    }
+	}
+	fsRecPtr = fsRecPtr->nextPtr;
+    }
+    
+    return resultPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FsListMounts --
+ *
+ *	List all mounts within the given directory, which match the
+ *	given pattern.
+ *
+ * Results:
+ *	The list of mounts, in a list object which has refCount 0, or
+ *	NULL if we didn't even find any filesystems to try to list
+ *	mounts.
+ *
+ * Side effects:
+ *	None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static Tcl_Obj*
+FsListMounts(pathPtr, pattern)
+    Tcl_Obj *pathPtr;	        /* Contains path to directory to search. */
+    CONST char *pattern;	/* Pattern to match against. */
+{
+    FilesystemRecord *fsRecPtr;
+    Tcl_GlobTypeData mountsOnly = { TCL_GLOB_TYPE_MOUNT, 0, NULL, NULL };
+    Tcl_Obj *resultPtr = NULL;
+    
+    /*
+     * Call each of the "listMounts" functions in succession.
+     * A non-NULL return value indicates the particular function has
+     * succeeded.  We call all the functions registered, since we want
+     * a list from each filesystems.
+     */
+
+    fsRecPtr = FsGetFirstFilesystem();
+    while (fsRecPtr != NULL) {
+	if (fsRecPtr != &nativeFilesystemRecord) {
+	    Tcl_FSMatchInDirectoryProc *proc = 
+				  fsRecPtr->fsPtr->matchInDirectoryProc;
+	    if (proc != NULL) {
+		if (resultPtr == NULL) {
+		    resultPtr = Tcl_NewObj();
+		}
+		(*proc)(NULL, resultPtr, pathPtr, pattern, &mountsOnly);
 	    }
 	}
 	fsRecPtr = fsRecPtr->nextPtr;
Index: generic/tclTest.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclTest.c,v
retrieving revision 1.62.2.2
diff -u -r1.62.2.2 tclTest.c
--- generic/tclTest.c	8 Oct 2003 14:21:20 -0000	1.62.2.2
+++ generic/tclTest.c	13 Oct 2003 17:15:02 -0000
@@ -6091,16 +6091,21 @@
 static int
 TestReportMatchInDirectory(interp, resultPtr, dirPtr, pattern, types)
     Tcl_Interp *interp;		/* Interpreter to receive results. */
-    Tcl_Obj *resultPtr;		/* Directory separators to pass to TclDoGlob. */
+    Tcl_Obj *resultPtr;		/* Object to lappend results. */
     Tcl_Obj *dirPtr;	        /* Contains path to directory to search. */
     CONST char *pattern;	/* Pattern to match against. */
     Tcl_GlobTypeData *types;	/* Object containing list of acceptable types.
 				 * May be NULL. */
 {
-    TestReport("matchindirectory",dirPtr, NULL);
-    return Tcl_FSMatchInDirectory(interp, resultPtr, 
-				  TestReportGetNativePath(dirPtr), pattern, 
-				  types);
+    if (types != NULL && types->type & TCL_GLOB_TYPE_MOUNT) {
+	TestReport("matchmounts",dirPtr, NULL);
+	return TCL_OK;
+    } else {
+	TestReport("matchindirectory",dirPtr, NULL);
+	return Tcl_FSMatchInDirectory(interp, resultPtr, 
+				      TestReportGetNativePath(dirPtr), pattern, 
+				      types);
+    }
 }
 static int
 TestReportChdir(dirName)