? NSK1200002852A
Index: generic/tcl.decls
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tcl.decls,v
retrieving revision 1.172
diff -r1.172 tcl.decls
2307a2308,2321
> # TIP #357 (Export TclLoadFile and TclpFindSymbol) kbk
> declare 627 generic {
>     int Tcl_LoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
> 		     const char *symv[], int flags, void* procPtrs,
> 		     Tcl_LoadHandle* handlePtr)
> }
> declare 628 generic {
>     void* Tcl_FindSymbol(Tcl_Interp* interp, Tcl_LoadHandle handle,
> 			 const char* symbol)
> }
> declare 629 generic {
>     int Tcl_FSUnloadFile(Tcl_Interp* interp, Tcl_LoadHandle handlePtr)
> }
> 
Index: generic/tclDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclDecls.h,v
retrieving revision 1.174
diff -r1.174 tclDecls.h
3686a3687,3705
> #ifndef Tcl_LoadFile_TCL_DECLARED
> #define Tcl_LoadFile_TCL_DECLARED
> /* 627 */
> EXTERN int		Tcl_LoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
> 				const char *symv[], int flags, void*procPtrs,
> 				Tcl_LoadHandle*handlePtr);
> #endif
> #ifndef Tcl_FindSymbol_TCL_DECLARED
> #define Tcl_FindSymbol_TCL_DECLARED
> /* 628 */
> EXTERN void*		Tcl_FindSymbol(Tcl_Interp*interp,
> 				Tcl_LoadHandle handle, const char*symbol);
> #endif
> #ifndef Tcl_FSUnloadFile_TCL_DECLARED
> #define Tcl_FSUnloadFile_TCL_DECLARED
> /* 629 */
> EXTERN int		Tcl_FSUnloadFile(Tcl_Interp*interp,
> 				Tcl_LoadHandle handlePtr);
> #endif
4348a4368,4370
>     int (*tcl_LoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *symv[], int flags, void*procPtrs, Tcl_LoadHandle*handlePtr); /* 627 */
>     void* (*tcl_FindSymbol) (Tcl_Interp*interp, Tcl_LoadHandle handle, const char*symbol); /* 628 */
>     int (*tcl_FSUnloadFile) (Tcl_Interp*interp, Tcl_LoadHandle handlePtr); /* 629 */
6886a6909,6920
> #ifndef Tcl_LoadFile
> #define Tcl_LoadFile \
> 	(tclStubsPtr->tcl_LoadFile) /* 627 */
> #endif
> #ifndef Tcl_FindSymbol
> #define Tcl_FindSymbol \
> 	(tclStubsPtr->tcl_FindSymbol) /* 628 */
> #endif
> #ifndef Tcl_FSUnloadFile
> #define Tcl_FSUnloadFile \
> 	(tclStubsPtr->tcl_FSUnloadFile) /* 629 */
> #endif
Index: generic/tclIOUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIOUtil.c,v
retrieving revision 1.170
diff -r1.170 tclIOUtil.c
44a45,48
> static void*		DivertFindSymbol(Tcl_Interp* interp,
> 					 Tcl_LoadHandle loadHandle,
> 					 const char* symbol);
> static void		DivertUnloadFile(Tcl_LoadHandle loadHandle);
2970,2972c2974,2975
<     const char *symbols[2];
<     Tcl_PackageInitProc **procPtrs[2];
<     ClientData clientData;
---
>     const char *symbols[3];
>     void *procPtrs[2];
2981,2982c2984
<     procPtrs[0] = proc1Ptr;
<     procPtrs[1] = proc2Ptr;
---
>     symbols[2] = NULL;
2988,3000c2990,2996
<     res = TclLoadFile(interp, pathPtr, 2, symbols, procPtrs, handlePtr,
< 	    &clientData, unloadProcPtr);
< 
<     /*
<      * Due to an unfortunate mis-design in Tcl 8.4 fs, when loading a shared
<      * library, we don't keep the loadHandle (for TclpFindSymbol) and the
<      * clientData (for the unloadProc) separately. In fact we effectively
<      * throw away the loadHandle and only use the clientData. It just so
<      * happens, for the native filesystem only, that these two are identical.
<      *
<      * This also means that the signatures Tcl_FSUnloadFileProc and
<      * Tcl_FSLoadFileProc are both misleading.
<      */
---
>     res = Tcl_LoadFile(interp, pathPtr, symbols, 0, procPtrs, handlePtr);
>     if (res == TCL_OK) {
> 	*proc1Ptr = (Tcl_PackageInitProc*) procPtrs[0];
> 	*proc2Ptr = (Tcl_PackageInitProc*) procPtrs[1];
>     } else {
> 	*proc1Ptr = *proc2Ptr = NULL;
>     }
3002d2997
<     *handlePtr = clientData;
3009c3004
<  * TclLoadFile --
---
>  * Tcl_LoadFile --
3023,3028d3017
<  *	This function is currently private to Tcl. It may be exported in the
<  *	future and its interface fixed (but we should clean up the
<  *	loadHandle/clientData confusion at that time -- see the above comments
<  *	in Tcl_FSLoadFile for details). For a public function, see
<  *	Tcl_FSLoadFile.
<  *
3035c3024
<  *	passing the clientData to the unloadProc.
---
>  *	calling TclFS_UnloadFile.
3041c3030
< TclLoadFile(
---
> Tcl_LoadFile(
3045,3046d3033
<     int symc,			/* Number of symbols/procPtrs in the next two
< 				 * arrays. */
3049,3050c3036,3037
<     Tcl_PackageInitProc **procPtrs[],
< 				/* Where to return the addresses corresponding
---
>     int flags,			/* Flags (unused) */
>     void *procVPtrs,		/* Where to return the addresses corresponding
3052c3039
<     Tcl_LoadHandle *handlePtr,	/* Filled with token for shared library
---
>     Tcl_LoadHandle *handlePtr)	/* Filled with token for shared library
3055,3061d3041
<     ClientData *clientDataPtr,	/* Filled with token for dynamically loaded
< 				 * file which will be passed back to
< 				 * (*unloadProcPtr)() to unload the file. */
<     Tcl_FSUnloadFileProc **unloadProcPtr)
< 				/* Filled with address of Tcl_FSUnloadFileProc
< 				 * function which should be used for this
< 				 * file. */
3062a3043
>     void** procPtrs = (void**) procVPtrs;
3064a3046
>     Tcl_FSUnloadFileProc* unloadProcPtr;
3067c3049
<     ClientData newClientData = NULL;
---
>     Tcl_LoadHandle divertedLoadHandle = NULL;
3070a3053
>     int i;
3079c3062
< 		unloadProcPtr);
---
> 		&unloadProcPtr);
3085,3090d3067
< 
< 	    /*
< 	     * Copy this across, since both are equal for the native fs.
< 	     */
< 
< 	    *clientDataPtr = *handlePtr;
3150c3127
< 		unloadProcPtr);
---
> 		&unloadProcPtr);
3166,3171c3143
<     copyToPtr = TclpTempFileName();
<     if (copyToPtr == NULL) {
< 	Tcl_AppendResult(interp, "couldn't create temporary file: ",
< 		Tcl_PosixError(interp), NULL);
< 	return TCL_ERROR;
<     }
---
>     copyToPtr = TclpTempFileNameForLibrary(interp, pathPtr);
3226,3227c3198,3199
<     retVal = TclLoadFile(interp, copyToPtr, symc, symbols, procPtrs,
< 	    &newLoadHandle, &newClientData, &newUnloadProcPtr);
---
>     retVal = Tcl_LoadFile(interp, copyToPtr, symbols, 0, procPtrs,
> 			 &newLoadHandle);
3254,3255d3225
< 	*clientDataPtr = newClientData;
< 	*unloadProcPtr = newUnloadProcPtr;
3310,3312c3280,3287
<     *handlePtr = newLoadHandle;
<     *clientDataPtr = tvdlPtr;
<     *unloadProcPtr = TclFSUnloadTempFile;
---
> 
>     
>     divertedLoadHandle = (Tcl_LoadHandle)
> 	ckalloc(sizeof (struct Tcl_LoadHandle_));
>     divertedLoadHandle->clientData = (ClientData) tvdlPtr;
>     divertedLoadHandle->findSymbolProcPtr = DivertFindSymbol;
>     divertedLoadHandle->unloadFileProcPtr = DivertUnloadFile;
>     *handlePtr = divertedLoadHandle;
3318,3323c3293,3309
<     {
< 	int i;
< 
< 	for (i=0 ; i<symc ; i++) {
< 	    if (symbols[i] != NULL) {
< 		*procPtrs[i] = TclpFindSymbol(interp, *handlePtr, symbols[i]);
---
>     /* 
>      * At this point, *handlePtr is already set up to the handle for the
>      * loaded library. We now try to resolve the symbols.
>      */
>     if (symbols != NULL) {
> 	for (i=0 ; symbols[i] != NULL; i++) {
> 	    procPtrs[i] = Tcl_FindSymbol(interp, *handlePtr, symbols[i]);
> 	    if (procPtrs[i] == NULL) {
> 		/* 
> 		 * At least one symbol in the list was not found.
> 		 * Unload the file, and report the problem back to the 
> 		 * caller. (Tcl_FindSymbol should already have left an
> 		 * appropriate error message.)
> 		 */	
> 		(*handlePtr)->unloadFileProcPtr(*handlePtr);
> 		*handlePtr = NULL;
> 		return TCL_ERROR;
3330a3317,3423
>  *-----------------------------------------------------------------------------
>  *
>  * DivertFindSymbol --
>  *	
>  *	Find a symbol in a shared library loaded by copy-from-VFS.
>  *
>  *-----------------------------------------------------------------------------
>  */
> 
> static void*
> DivertFindSymbol(Tcl_Interp* interp, 	    /* Tcl interpreter */
> 		 Tcl_LoadHandle loadHandle, /* Handle to the diverted module */
> 		 const char* symbol)	    /* Symbol to resolve */
> {
>     FsDivertLoad* tvdlPtr = (FsDivertLoad*) (loadHandle->clientData);
>     Tcl_LoadHandle originalHandle = tvdlPtr->loadHandle;
>     return originalHandle->findSymbolProcPtr(interp, originalHandle, symbol);
> }
> 
> /*
>  *-----------------------------------------------------------------------------
>  *
>  * DivertUnloadFile --
>  *
>  *	Unloads a file that has been loaded by copying from VFS to the
>  *	native filesystem.
>  *
>  * Parameters:
>  *	loadHandle -- Handle of the file to unload
>  *
>  *-----------------------------------------------------------------------------
>  */
> 
> static void
> DivertUnloadFile(Tcl_LoadHandle loadHandle)
> {
>     FsDivertLoad* tvdlPtr = (FsDivertLoad*) (loadHandle->clientData);
>     Tcl_LoadHandle originalHandle = tvdlPtr->loadHandle;
> 
>     /*
>      * This test should never trigger, since we give the client data in the
>      * function above.
>      */
> 
>     if (tvdlPtr == NULL) {
> 	return;
>     }
> 
>     /*
>      * Call the real 'unloadfile' proc we actually used. It is very important
>      * that we call this first, so that the shared library is actually
>      * unloaded by the OS. Otherwise, the following 'delete' may well fail
>      * because the shared library is still in use.
>      */
> 
>     originalHandle->unloadFileProcPtr(originalHandle);
> 
>     /* What filesystem contains the temp copy of the library? */
> 
>     if (tvdlPtr->divertedFilesystem == NULL) {
> 	/*
> 	 * It was the native filesystem, and we have a special function
> 	 * available just for this purpose, which we know works even at this
> 	 * late stage.
> 	 */
> 
> 	TclpDeleteFile(tvdlPtr->divertedFileNativeRep);
> 	NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep);
>     } else {
> 	/*
> 	 * Remove the temporary file we created. Note, we may crash here
> 	 * because encodings have been taken down already.
> 	 */
> 
> 	if (tvdlPtr->divertedFilesystem->deleteFileProc(tvdlPtr->divertedFile)
> 		!= TCL_OK) {
> 	    /*
> 	     * The above may have failed because the filesystem, or something
> 	     * it depends upon (e.g. encodings) have been taken down because
> 	     * Tcl is exiting.
> 	     *
> 	     * We may need to work out how to delete this file more robustly
> 	     * (or give the filesystem the information it needs to delete the
> 	     * file more robustly).
> 	     *
> 	     * In particular, one problem might be that the filesystem cannot
> 	     * extract the information it needs from the above path object
> 	     * because Tcl's entire filesystem apparatus (the code in this
> 	     * file) has been finalized, and it refuses to pass the internal
> 	     * representation to the filesystem.
> 	     */
> 	}
> 
> 	/*
> 	 * And free up the allocations. This will also of course remove a
> 	 * refCount from the Tcl_Filesystem to which this file belongs, which
> 	 * could then free up the filesystem if we are exiting.
> 	 */
> 
> 	Tcl_DecrRefCount(tvdlPtr->divertedFile);
>     }
> 
>     ckfree((void*)tvdlPtr);
>     ckfree((void*)loadHandle);
> }
> 
> /*
3369,3370c3462,3516
<     *proc1Ptr = TclpFindSymbol(interp, handle, sym1);
<     *proc2Ptr = TclpFindSymbol(interp, handle, sym2);
---
>     *proc1Ptr = Tcl_FindSymbol(interp, handle, sym1);
>     *proc2Ptr = Tcl_FindSymbol(interp, handle, sym2);
>     return TCL_OK;
> }
> 
> /*
>  *-----------------------------------------------------------------------------
>  *
>  * Tcl_FindSymbol --
>  *
>  *	Find a symbol in a loaded library
>  *
>  * Results:
>  *	Returns a pointer to the symbol if found. If not found, returns
>  *	NULL and leaves an error message in the interpreter result.
>  *
>  * This function was once filesystem-specific, but has been made portable
>  * by having TclpDlopen return a structure that includes procedure pointers.
>  *
>  *-----------------------------------------------------------------------------
>  */
> 
> void*
> Tcl_FindSymbol(Tcl_Interp* interp,	  /* Tcl interpreter */
> 	       Tcl_LoadHandle loadHandle, /* Handle to the loaded library */
> 	       const char* symbol)        /* Name of the symbol to resolve */
> {
>     return (*(loadHandle->findSymbolProcPtr))(interp, loadHandle, symbol);
> }
> 
> /*
>  *-----------------------------------------------------------------------------
>  *
>  * Tcl_FSUnloadFile --
>  *
>  *	Unloads a library given its handle. Checks first that the library
>  *	supports unloading.
>  *
>  *-----------------------------------------------------------------------------
>  */
> 
> int
> Tcl_FSUnloadFile(Tcl_Interp* interp, /* Tcl interpreter */
> 		 Tcl_LoadHandle handle) /* Handle of the file to unload */
> {
>     if (handle->unloadFileProcPtr == NULL) {
> 	if (interp != NULL) {
> 	    Tcl_SetObjResult(interp,
> 			     Tcl_NewStringObj("cannot unload: filesystem "
> 					      "does not support unloading",
> 					      -1));
> 	}
> 	return TCL_ERROR;
>     } else {
> 	TclpUnloadFile(handle);
3371a3518,3539
>     }
> }
> 
> /*
>  *-----------------------------------------------------------------------------
>  *
>  * TclpUnloadFile --
>  *
>  *	Unloads a library given its handle
>  *
>  * This function was once filesystem-specific, but has been made portable
>  * by having TclpDlopen return a structure that includes procedure pointers.
>  *
>  *-----------------------------------------------------------------------------
>  */
> 
> void
> TclpUnloadFile(Tcl_LoadHandle handle)
> {
>     if (handle->unloadFileProcPtr != NULL) {
> 	(*(handle->unloadFileProcPtr))(handle);
>     }
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.464
diff -r1.464 tclInt.h
2774a2775,2793
> /* TIP #357 - Structure doing the bookkeeping of handles for Tcl_LoadFile
>  *            and Tcl_FindSymbol. This structure corresponds to an opaque
>  *            typedef in tcl.h */
> 
> typedef void* TclFindSymbolProc(Tcl_Interp* interp, Tcl_LoadHandle loadHandle,
> 				const char* symbol);
> struct Tcl_LoadHandle_ {
>     ClientData clientData;	/* Client data is the load handle in the
> 				 * native filesystem if a module was loaded
> 				 * there, or an opaque pointer to a structure
> 				 * for further bookkeeping on load-from-VFS
> 				 * and load-from-memory */
>     TclFindSymbolProc* findSymbolProcPtr;
> 				/* Procedure that resolves symbols in a
> 				 * loaded module */
>     Tcl_FSUnloadFileProc* unloadFileProcPtr;
> 				/* Procedure that unloads a loaded module */
> };
> 
2923,2928d2941
< MODULE_SCOPE int	TclLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
< 			    int symc, const char *symbols[],
< 			    Tcl_PackageInitProc **procPtrs[],
< 			    Tcl_LoadHandle *handlePtr,
< 			    ClientData *clientDataPtr,
< 			    Tcl_FSUnloadFileProc **unloadProcPtr);
2965a2979
> MODULE_SCOPE Tcl_Obj *  TclpTempFileNameForLibrary(Tcl_Interp *interp, Tcl_Obj* pathPtr);
3018d3031
< MODULE_SCOPE void	TclpUnloadFile(Tcl_LoadHandle loadHandle);
3059,3060d3071
< MODULE_SCOPE Tcl_PackageInitProc *TclpFindSymbol(Tcl_Interp *interp,
< 			    Tcl_LoadHandle loadHandle, const char *symbol);
Index: generic/tclLoad.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclLoad.c,v
retrieving revision 1.24
diff -r1.24 tclLoad.c
60,64d59
<     Tcl_FSUnloadFileProc *unLoadProcPtr;
< 				/* Function to use to unload this package. If
< 				 * NULL, then we do not attempt to unload the
< 				 * package. If fileName is NULL, then this
< 				 * field is irrelevant. */
134d128
<     Tcl_PackageInitProc *initProc, *safeInitProc, *unloadProc, *safeUnloadProc;
137,139c131,132
<     const char *symbols[4];
<     Tcl_PackageInitProc **procPtrs[4];
<     ClientData clientData;
---
>     const char *symbols[2];
>     void* procPtrs[1];
142d134
<     Tcl_FSUnloadFileProc *unLoadProcPtr = NULL;
362,368c354
< 	symbols[1] = Tcl_DStringValue(&safeInitName);
< 	symbols[2] = Tcl_DStringValue(&unloadName);
< 	symbols[3] = Tcl_DStringValue(&safeUnloadName);
< 	procPtrs[0] = &initProc;
< 	procPtrs[1] = &safeInitProc;
< 	procPtrs[2] = &unloadProc;
< 	procPtrs[3] = &safeUnloadProc;
---
> 	symbols[1] = NULL;
371,372c357
< 	code = TclLoadFile(interp, objv[1], 4, symbols, procPtrs,
< 		&loadHandle, &clientData, &unLoadProcPtr);
---
> 	code = Tcl_LoadFile(interp, objv[1], symbols, 0, procPtrs, &loadHandle);
374d358
< 	loadHandle = clientData;
379,388d362
< 	if (*procPtrs[0] /* initProc */ == NULL) {
< 	    Tcl_AppendResult(interp, "couldn't find procedure ",
< 		    Tcl_DStringValue(&initName), NULL);
< 	    if (unLoadProcPtr != NULL) {
< 		unLoadProcPtr(loadHandle);
< 	    }
< 	    code = TCL_ERROR;
< 	    goto done;
< 	}
< 
401,405c375,382
< 	pkgPtr->unLoadProcPtr	   = unLoadProcPtr;
< 	pkgPtr->initProc	   = *procPtrs[0];
< 	pkgPtr->safeInitProc	   = *procPtrs[1];
< 	pkgPtr->unloadProc	   = (Tcl_PackageUnloadProc *) *procPtrs[2];
< 	pkgPtr->safeUnloadProc	   = (Tcl_PackageUnloadProc *) *procPtrs[3];
---
> 	pkgPtr->initProc	   = (Tcl_PackageInitProc*) procPtrs[0];
> 	pkgPtr->safeInitProc	   = (Tcl_PackageInitProc*)
> 	    Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&safeInitName));
> 	pkgPtr->unloadProc	   = (Tcl_PackageUnloadProc*)
> 	    Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&unloadName));
> 	pkgPtr->safeUnloadProc	   = (Tcl_PackageUnloadProc *) 
> 	    Tcl_FindSymbol(interp, loadHandle,
> 			   Tcl_DStringValue(&safeUnloadName));
412a390,394
> 	/*
> 	 * The Tcl_FindSymbol calls may have left a spurious error message
> 	 * in the interpreter result.
> 	 */
> 	Tcl_ResetResult(interp);
790d771
< 	    Tcl_FSUnloadFileProc *unLoadProcPtr = pkgPtr->unLoadProcPtr;
792d772
< 	    if (unLoadProcPtr != NULL) {
794,797c774
< 		if ((pkgPtr->unloadProc != NULL) || (unLoadProcPtr == TclFSUnloadTempFile)) {
< 		    unLoadProcPtr(pkgPtr->loadHandle);
< 		}
< 
---
> 	    if (Tcl_FSUnloadFile(interp, pkgPtr->loadHandle) == TCL_OK) {
842,844d818
< 		Tcl_AppendResult(interp, "file \"", fullFileName,
< 			"\" cannot be unloaded: filesystem does not support unloading",
< 			NULL);
1149,1154c1123
< 	    Tcl_FSUnloadFileProc *unLoadProcPtr = pkgPtr->unLoadProcPtr;
< 	    if ((unLoadProcPtr != NULL)
< 		    && ((pkgPtr->unloadProc != NULL)
< 		    || (unLoadProcPtr == TclFSUnloadTempFile))) {
< 		unLoadProcPtr(pkgPtr->loadHandle);
< 	    }
---
> 	    Tcl_FSUnloadFile(NULL, pkgPtr->loadHandle);
Index: generic/tclLoadNone.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclLoadNone.c,v
retrieving revision 1.13
diff -r1.13 tclLoadNone.c
4c4
<  *	This procedure provides a version of the TclLoadFile for use in
---
>  *	This procedure provides a version of the TclpDlopen for use in
58,84d57
<  * TclpFindSymbol --
<  *
<  *	Looks up a symbol, by name, through a handle associated with a
<  *	previously loaded piece of code (shared library). This version of this
<  *	routine should never be called because the associated TclpDlopen()
<  *	function always returns an error.
<  *
<  * Results:
<  *	Returns a pointer to the function associated with 'symbol' if it is
<  *	found. Otherwise returns NULL and may leave an error message in the
<  *	interp's result.
<  *
<  *----------------------------------------------------------------------
<  */
< 
< Tcl_PackageInitProc *
< TclpFindSymbol(
<     Tcl_Interp *interp,
<     Tcl_LoadHandle loadHandle,
<     const char *symbol)
< {
<     return NULL;
< }
< 
< /*
<  *----------------------------------------------------------------------
<  *
113,138d85
<  *----------------------------------------------------------------------
<  *
<  * TclpUnloadFile --
<  *
<  *    This procedure is called to carry out dynamic unloading of binary code;
<  *    it is intended for use only on systems that don't support dynamic
<  *    loading (it does nothing).
<  *
<  * Results:
<  *    None.
<  *
<  * Side effects:
<  *    None.
<  *
<  *----------------------------------------------------------------------
<  */
< 
< void
< TclpUnloadFile(
<     Tcl_LoadHandle loadHandle)	/* loadHandle returned by a previous call to
< 				 * TclpDlopen(). The loadHandle is a token
< 				 * that represents the loaded file. */
< {
< }
< 
< /*
Index: generic/tclStubInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclStubInit.c,v
retrieving revision 1.188
diff -r1.188 tclStubInit.c
1116a1117,1119
>     Tcl_LoadFile, /* 627 */
>     Tcl_FindSymbol, /* 628 */
>     Tcl_FSUnloadFile, /* 629 */
Index: tests/fileSystem.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/fileSystem.test,v
retrieving revision 1.59
diff -r1.59 fileSystem.test
622c622
< test filesystem-7.1 {load from vfs} -setup {
---
> test filesystem-7.1.1 {load from vfs} -setup {
636a637,652
> test filesystem-7.1.2 {load from vfs, and then unload again} -setup {
>     set dir [pwd]
> } -constraints {win testsimplefilesystem} -body {
>     # This may cause a crash on exit
>     cd [file dirname [info nameof]]
>     set reg [lindex [glob tclreg*[info sharedlib]] 0]
>     testsimplefilesystem 1
>     # This loads reg via a complex copy-to-temp operation
>     load simplefs:/$reg Registry
>     unload simplefs:/$reg
>     testsimplefilesystem 0
>     return ok
>     # The real result of this test is what happens when Tcl exits.
> } -cleanup {
>     cd $dir
> } -result ok
Index: tests/load.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/load.test,v
retrieving revision 1.20
diff -r1.20 load.test
80,81c80,83
<     list [catch {load [file join $testDir pkgc$ext] foo} msg] $msg
< } -match glob -result {1 {*couldn't find procedure Foo_Init}}
---
>     list [catch {load [file join $testDir pkgc$ext] foo} msg] $msg $errorCode
> } -match glob \
>     -result [list 1 {cannot find symbol "Foo_Init"*} \
> 		 {TCL LOOKUP LOAD_SYMBOL *Foo_Init}]
Index: tests/unload.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/unload.test,v
retrieving revision 1.8
diff -r1.8 unload.test
42a43,46
> # Certain tests need the 'testsimplefilsystem' in tcltest
> testConstraint testsimplefilesystem \
> 	[llength [info commands testsimplefilesystem]]
> 
215a220,234
> test unload-5.1 {unload a module loaded from vfs} \
>      -constraints [list $dll $loaded testsimplefilesystem] \
>      -setup {
> 	 set dir [pwd]
> 	 cd $testDir
> 	 testsimplefilesystem 1
> 	 load simplefs:/pkgua$ext pkgua
>      } \
>     -body {
> 	list [catch {unload simplefs:/pkgua$ext} msg] $msg
>     } \
>     -result {0 {}}
> 
> 
> 
221a241,244
> 
> # Local Variables:
> # mode: tcl
> # End:
Index: unix/tclLoadDl.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclLoadDl.c,v
retrieving revision 1.19
diff -r1.19 tclLoadDl.c
36a37,42
> /* Static procedures defined within this file */
> 
> static void* FindSymbol(Tcl_Interp* interp, Tcl_LoadHandle loadHandle,
> 			const char* symbol);
> static void UnloadFile(Tcl_LoadHandle loadHandle);
> 
68a75
>     Tcl_LoadHandle newHandle;
105a113,118
>     newHandle = (Tcl_LoadHandle) ckalloc(sizeof(*newHandle));
>     newHandle->clientData = (ClientData) handle;
>     newHandle->findSymbolProcPtr = &FindSymbol;
>     newHandle->unloadFileProcPtr = &UnloadFile;
>     *unloadProcPtr = &UnloadFile;
>     *loadHandle = newHandle;
107,108d119
<     *unloadProcPtr = &TclpUnloadFile;
<     *loadHandle = (Tcl_LoadHandle) handle;
115c126
<  * TclpFindSymbol --
---
>  * FindSymbol --
128,129c139,140
< Tcl_PackageInitProc *
< TclpFindSymbol(
---
> static void *
> FindSymbol(
136c147
<     void *handle = (void *) loadHandle;
---
>     void *handle = (void *)(loadHandle->clientData);
157c168,174
< 
---
>     if (proc == NULL && interp != NULL) {
> 	Tcl_ResetResult(interp);
> 	Tcl_AppendResult(interp, "cannot find symbol \"", symbol, "\": ",
> 			 dlerror(), NULL);
> 	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol,
> 			 NULL);
>     }
164c181
<  * TclpUnloadFile --
---
>  * UnloadFile --
179,180c196,197
< void
< TclpUnloadFile(
---
> static void
> UnloadFile(
187c204
<     handle = (void *) loadHandle;
---
>     handle = (void *)(loadHandle->clientData);
188a206
>     ckfree((char*)loadHandle);
Index: unix/tclLoadDyld.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclLoadDyld.c,v
retrieving revision 1.34
diff -r1.34 tclLoadDyld.c
96a97,104
> /* Static functions defined in this file */
> 
> static void* FindSymbol(Tcl_Interp* interp, Tcl_LoadHandle loadHandle,
> 			const char* symbol);
> static void UnloadFile(Tcl_LoadHandle handle);
> 
> 
> 
169a178
>     Tcl_LoadHandle* newHandle;
310,311c319,324
< 	*loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
< 	*unloadProcPtr = &TclpUnloadFile;
---
> 	newHandle = (Tcl_LoadHandle) ckalloc(sizeof(*newHandle));
> 	newHandle->clientData = dyldLoadHandle;
> 	newHandle->findSymbolProcPtr = &FindSymbol;
> 	newHandle->unloadProcPtr = &UnloadFile;
> 	*unloadProcPtr = &UnloadFile;
> 	*loadHandle = newHandle;
332c345
<  * TclpFindSymbol --
---
>  * FindSymbol --
345,346c358,359
< MODULE_SCOPE Tcl_PackageInitProc *
< TclpFindSymbol(
---
> static void*
> FindSymbol(
351c364,365
<     Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
---
>     Tcl_DyldLoadHandle *dyldLoadHandle =
> 	(Tcl_DyldLoadHandle *) (loadHandle->clientData);
439c453
<     if (errMsg) {
---
>     if (errMsg && (interp != NULL)) {
440a455
> 	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
448c463
<  * TclpUnloadFile --
---
>  * UnloadFile --
465,466c480,481
< MODULE_SCOPE void
< TclpUnloadFile(
---
> static void
> UnloadFile(
471c486,487
<     Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
---
>     Tcl_DyldLoadHandle *dyldLoadHandle = 
> 	(Tcl_DyldLoadHandle *) (loadHandle->clientData);
506a523
>     ckfree((char*) loadHandle);
615a633
>     Tcl_LoadHandle newHandle;
760,761c778,783
<     *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
<     *unloadProcPtr = &TclpUnloadFile;
---
>     newHandle = (Tcl_LoadHandle) ckalloc(sizeof(*newHandle));
>     newHandle->clientData = dyldLoadHandle;
>     newHandle->findSymbolProcPtr = &FindSymbol;
>     newHandle->unloadFileProcPtr = &UnloadFile;
>     *loadHandle = newHandle;
>     *unloadProcPtr = &UnloadFile;
Index: unix/tclLoadNext.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclLoadNext.c,v
retrieving revision 1.16
diff -r1.16 tclLoadNext.c
17a18,24
> 
> /* Static procedures defined within this file */
> 
> static void* FindSymbol(Tcl_Interp* interp, Tcl_LoadHandle loadHandle,
> 			const char* symbol);
> static void UnloadFile(Tcl_LoadHandle loadHandle);
> 
49a57
>     Tcl_LoadHandle newHandle;
98,99c106,111
<     *loadHandle = (Tcl_LoadHandle)1; /* A dummy non-NULL value */
<     *unloadProcPtr = &TclpUnloadFile;
---
>     newHandle = (Tcl_LoadHandle) ckalloc(sizeof(*newHandle));
>     newHandle->clientData = (ClientData) 1;
>     newHandle->findSymbolProcPtr = &FindSymbol;
>     newHandle->unloadFileProcPtr = &UnloadFile;
>     *loadHandle = newHandle;
>     *unloadProcPtr = &UnloadFile;
107c119
<  * TclpFindSymbol --
---
>  * FindSymbol --
120,121c132,133
< Tcl_PackageInitProc *
< TclpFindSymbol(
---
> static void*
> FindSymbol(
134a147,152
>     if (proc == NULL && interp != NULL) {
> 	Tcl_ResetResult(interp);
> 	Tcl_AppendResult(interp, "cannot find symbol \"", symbol,
> 			 "\"", NULL);
> 	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
>     }
141c159
<  * TclpUnloadFile --
---
>  * UnloadFile --
157c175
< TclpUnloadFile(
---
> UnloadFile(
161a180
>     ckfree((char*) loadHandle);
Index: unix/tclLoadOSF.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclLoadOSF.c,v
retrieving revision 1.16
diff -r1.16 tclLoadOSF.c
40a41,46
> /* Static functions defined within this file */
> 
> static void* FindSymbol(Tcl_Interp* interp, Tcl_LoadHandle loadHandle,
> 		       const char* symbol);
> static void UnloadFile(Tcl_LoadHandle handle);
> 
71a78
>     Tcl_LoadHandle newHandle;
122,123c129,134
<     *loadHandle = pkg;
<     *unloadProcPtr = &TclpUnloadFile;
---
>     newHandle = (Tcl_LoadHandle*) ckalloc(sizeof(*newHandle));
>     newHandle->clientData = pkg;
>     newHandle->findSymbolProcPtr = &FindSymbol;
>     newHandle->unloadFileProcPtr = &UnloadFile;
>     *loadHandle = newHandle;
>     *unloadProcPtr = &UnloadFile;
130c141
<  * TclpFindSymbol --
---
>  * FindSymbol --
143,144c154,155
< Tcl_PackageInitProc *
< TclpFindSymbol(
---
> static void *
> FindSymbol(
149c160,166
<     return ldr_lookup_package((char *)loadHandle, symbol);
---
>     void* retval = ldr_lookup_package((char *)loadHandle, symbol);
>     if (retval == NULL && interp != NULL) {
> 	Tcl_ResetResult(interp);
> 	Tcl_AppendResult(interp, "cannot find symbol\"", symbol, "\"", NULL);
> 	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
>     }
>     return retval;
155c172
<  * TclpUnloadFile --
---
>  * UnloadFile --
170,171c187,188
< void
< TclpUnloadFile(
---
> static void
> UnloadFile(
175a193
>     ckfree((char*) loadHandle);
Index: unix/tclLoadShl.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclLoadShl.c,v
retrieving revision 1.19
diff -r1.19 tclLoadShl.c
27a28,35
> /* Static functions defined within this file */
> 
> static void* FindSymbol(Tcl_Interp* interp, Tcl_LoadHandle loadHandle,
> 			const char* symbol);
> static void
> UnloadFile(Tcl_LoadHandle handle);
> 
> 
59a68
>     Tcl_LoadHandle newHandle;
100,101c109,113
<     *loadHandle = (Tcl_LoadHandle) handle;
<     *unloadProcPtr = &TclpUnloadFile;
---
>     newHandle = (Tcl_LoadHandle) ckalloc(sizeof(*newHandle));
>     newHandle->clientData = handle;
>     newHandle->findSymbolProcPtr = &FindSymbol;
>     newHandle->unloadFileProcPtr = *unloadProcPtr = &UnloadFile;
>     *loadHandle = newHandle;
108c120
<  * TclpFindSymbol --
---
>  * Tcl_FindSymbol --
121,122c133,134
< Tcl_PackageInitProc *
< TclpFindSymbol(
---
> static void*
> FindSymbol(
129c141
<     shl_t handle = (shl_t)loadHandle;
---
>     shl_t handle = (shl_t)(loadHandle->clientData);
146a159,163
>     if (proc == NULL && interp != NULL) {
> 	Tcl_ResetResult(interp);
> 	Tcl_AppendResult(interp, "cannot find symbol\"", symbol, 
> 			 "\": ", Tcl_PosixError(interp), NULL);
>     }
153c170
<  * TclpUnloadFile --
---
>  * UnloadFile --
168,169c185,186
< void
< TclpUnloadFile(
---
> static void
> UnloadFile(
176c193
<     handle = (shl_t) loadHandle;
---
>     handle = (shl_t) (loadHandle -> clientData);
177a195
>     ckfree((char*) loadHandle);
Index: unix/tclUnixPipe.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixPipe.c,v
retrieving revision 1.51
diff -r1.51 tclUnixPipe.c
271a272,305
>  *-----------------------------------------------------------------------------
>  *
>  * TclpTempFileNameForLibrary --
>  *
>  *	Constructs a file name in the native file system where a
>  *	dynamically loaded library may be placed.
>  *
>  * Results:
>  *	Returns the constructed file name. If an error occurs,
>  *	returns NULL and leaves an error message in the interpreter
>  *	result.
>  *
>  * On Unix, it works to load a shared object from a file of any
>  * name, so this function is merely a thin wrapper around
>  * TclpTempFileName().
>  *	
>  *-----------------------------------------------------------------------------
>  */
> 
> Tcl_Obj*
> TclpTempFileNameForLibrary(Tcl_Interp* interp, /* Tcl interpreter */
> 			   Tcl_Obj* path)      /* Path name of the library
> 						* in the VFS */
> {
>     Tcl_Obj* retval;
>     retval = TclpTempFileName();
>     if (retval == NULL) {
> 	Tcl_AppendResult(interp, "couldn't create temporary file: ",
> 		Tcl_PosixError(interp), NULL);
>     }
>     return retval;
> }
> 
> /*
Index: win/tclWinLoad.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinLoad.c,v
retrieving revision 1.26
diff -r1.26 tclWinLoad.c
17a18,23
> /* Static functions defined within this file */
> 
> void* FindSymbol(Tcl_Interp* interp, Tcl_LoadHandle loadHandle,
> 		 const char* symbol);
> void UnloadFile(Tcl_LoadHandle loadHandle);
> 
50c56
<     HINSTANCE handle;
---
>     HINSTANCE hInstance;
51a58
>     Tcl_LoadHandle handlePtr;
60,61c67,68
<     handle = tclWinProcs->loadLibraryProc(nativeName);
<     if (handle == NULL) {
---
>     hInstance = tclWinProcs->loadLibraryProc(nativeName);
>     if (hInstance == NULL) {
72c79
< 	handle = tclWinProcs->loadLibraryProc(nativeName);
---
> 	hInstance = tclWinProcs->loadLibraryProc(nativeName);
76,78c83
<     *loadHandle = (Tcl_LoadHandle) handle;
< 
<     if (handle == NULL) {
---
>     if (hInstance == NULL) {
133c138,144
< 	*unloadProcPtr = &TclpUnloadFile;
---
> 	handlePtr = 
> 	    (Tcl_LoadHandle) ckalloc(sizeof(struct Tcl_LoadHandle_));
> 	handlePtr->clientData = (ClientData) hInstance;
> 	handlePtr->findSymbolProcPtr = &FindSymbol;
> 	handlePtr->unloadFileProcPtr = &UnloadFile;
> 	*loadHandle = (Tcl_LoadHandle) handlePtr;
> 	*unloadProcPtr = &UnloadFile;
141c152
<  * TclpFindSymbol --
---
>  * FindSymbol --
154,155c165,166
< Tcl_PackageInitProc *
< TclpFindSymbol(
---
> void *
> FindSymbol(
161c172
<     HINSTANCE handle = (HINSTANCE)loadHandle;
---
>     HINSTANCE hInstance = (HINSTANCE)(loadHandle->clientData);
168c179
<     proc = (Tcl_PackageInitProc *) GetProcAddress(handle, symbol);
---
>     proc = (void*) GetProcAddress(hInstance, symbol);
171c182
< 
---
> 	const char* sym2;
174,175c185,186
< 	symbol = Tcl_DStringAppend(&ds, symbol, -1);
< 	proc = (Tcl_PackageInitProc *) GetProcAddress(handle, symbol);
---
> 	sym2 = Tcl_DStringAppend(&ds, symbol, -1);
> 	proc = (Tcl_PackageInitProc *) GetProcAddress(hInstance, sym2);
177a189,192
>     if (proc == NULL && interp != NULL) {
> 	Tcl_AppendResult(interp, "cannot find symbol \"", symbol, "\"", NULL);
> 	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
>     }
184c199
<  * TclpUnloadFile --
---
>  * UnloadFile --
200c215
< TclpUnloadFile(
---
> UnloadFile(
205,208c220,222
<     HINSTANCE handle;
< 
<     handle = (HINSTANCE) loadHandle;
<     FreeLibrary(handle);
---
>     HINSTANCE hInstance = (HINSTANCE) loadHandle->clientData;
>     FreeLibrary(hInstance);
>     ckfree((char*) loadHandle);
Index: win/tclWinPipe.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinPipe.c,v
retrieving revision 1.77
diff -r1.77 tclWinPipe.c
174a175,181
>  * Name of the directory in the native filesystem where DLLs used in this
>  * process are copied prior to loading.
>  */
> 
> static WCHAR* dllDirectoryName = NULL;
> 
> /*
772a780,874
>  *-----------------------------------------------------------------------------
>  *
>  * TclpTempFileNameForLibrary --
>  *
>  *	Constructs a temporary file name for loading a shared object (DLL).
>  *
>  * Results:
>  *	Returns the constructed file name.
>  *
>  * On Windows, a DLL is identified by the final component of its path name.
>  * Cross linking among DLL's (and hence, preloading) will not work unless
>  * this name is preserved when copying a DLL from a VFS to a temp file for
>  * preloading. For this reason, all DLLs in a given process are copied
>  * to a temp directory, and their names are preserved.
>  *
>  *-----------------------------------------------------------------------------
>  */
> 
> Tcl_Obj*
> TclpTempFileNameForLibrary(Tcl_Interp* interp, /* Tcl interpreter */
> 			   Tcl_Obj* path)      /* Path name of the DLL in
> 						* the VFS */
> {
>     size_t nameLen;		/* Length of the temp folder name */
>     WCHAR name[MAX_PATH];	/* Path name of the temp folder */
>     BOOL status;		/* Status from Win32 API calls */
>     Tcl_Obj* fileName;		/* Name of the temp file */
>     Tcl_Obj* tail;		/* Tail of the source path */
> 
>     /*
>      * Determine the name of the directory to use, and create it.
>      * (Keep trying with new names until an attempt to create the directory
>      * succeeds)
>      */
> 
>     nameLen = 0;
>     if (dllDirectoryName == NULL) {
> 	Tcl_MutexLock(&pipeMutex);
> 	if (dllDirectoryName == NULL) {
> 	    if ((nameLen = GetTempPathW(MAX_PATH, name)) >= 0) {
> 		if (nameLen >= MAX_PATH-12) {
> 		    Tcl_SetErrno(ENAMETOOLONG);
> 		    nameLen = 0;
> 		} else {
> 		    wcscpy(name+nameLen, L"TCLXXXXXXXX");
> 		    nameLen += 11;
> 		}
> 	    }
> 	    status = 1;
> 	    if (nameLen != 0) {
> 		DWORD id;
> 		int i = 0;
> 		id = GetCurrentProcessId();
> 		for (;;) {
> 		    DWORD lastError;
> 		    wsprintfW(name+nameLen-8, L"%08x", id);
> 		    status = CreateDirectoryW(name, NULL);
> 		    if (status) {
> 			break;
> 		    }
> 		    if ((lastError = GetLastError()) != ERROR_ALREADY_EXISTS) {
> 			TclWinConvertError(lastError);
> 			break;
> 		    } else if (++i > 256) {
> 			TclWinConvertError(lastError);
> 			break;
> 		    }
> 		    id *= 16777619;
> 		}
> 	    }
> 	    if (status != 0) {
> 		dllDirectoryName = (WCHAR*)
> 		    ckalloc((nameLen+1) * sizeof(WCHAR));
> 		wcscpy(dllDirectoryName, name);
> 	    }
> 	}
> 	Tcl_MutexUnlock(&pipeMutex);
>     }
>     if (dllDirectoryName == NULL) {
> 	Tcl_AppendResult(interp, "couldn't create temporary directory: ",
> 			 Tcl_PosixError(interp), NULL);
>     }
>     fileName = TclpNativeToNormalized((ClientData) dllDirectoryName);
>     tail = TclPathPart(interp, path, TCL_PATH_TAIL);
>     if (tail == NULL) {
> 	Tcl_DecrRefCount(fileName);
> 	return NULL;
>     } else {
> 	Tcl_AppendToObj(fileName, "/", 1);
> 	Tcl_AppendObjToObj(fileName, tail);
> 	return fileName;
>     }    
> }
> 
> /*
