? libpathutf.patch
Index: generic/tclEncoding.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclEncoding.c,v
retrieving revision 1.16.2.2
diff -u -r1.16.2.2 tclEncoding.c
--- generic/tclEncoding.c	6 Nov 2003 21:47:33 -0000	1.16.2.2
+++ generic/tclEncoding.c	29 Mar 2004 18:42:38 -0000
@@ -227,6 +227,7 @@
 			    Tcl_EncodingState *statePtr, char *dst, int dstLen,
 			    int *srcReadPtr, int *dstWrotePtr,
 			    int *dstCharsPtr));
+static int		TclFindEncodings _ANSI_ARGS_((CONST char *argv0));
 
 
 /*
@@ -1111,6 +1112,7 @@
     CONST char *argv0;		/* The value of the application's argv[0]
 				 * (native). */
 {
+    int mustCleanUtf;
     CONST char *name;
     Tcl_DString buffer, nameString;
 
@@ -1129,32 +1131,40 @@
 
     /*
      * The value returned from TclpNameOfExecutable is a UTF string that
-     * is possibly dirty depending on when it was initialized.  To assure
-     * that the UTF string is a properly encoded native string for this
-     * system, convert the UTF string to the default native encoding
-     * before the default encoding is initialized.  Then, convert it back
-     * to UTF after the system encoding is loaded.
+     * is possibly dirty depending on when it was initialized.
+     * TclFindEncodings will indicate whether we must "clean" the UTF (as
+     * reported by the underlying system).  To assure that the UTF string
+     * is a properly encoded native string for this system, convert the
+     * UTF string to the default native encoding before the default
+     * encoding is initialized.  Then, convert it back to UTF after the
+     * system encoding is loaded.
      */
     
     Tcl_UtfToExternalDString(NULL, name, -1, &buffer);
-    TclFindEncodings(argv0);
+    mustCleanUtf = TclFindEncodings(argv0);
 
     /*
      * Now it is OK to convert the native string back to UTF and set
      * the value of the tclExecutableName.
      */
     
-    Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buffer), -1, &nameString);
-    tclExecutableName = (char *)
-	ckalloc((unsigned) (Tcl_DStringLength(&nameString) + 1));
-    strcpy(tclExecutableName, Tcl_DStringValue(&nameString));
+    if (mustCleanUtf) {
+	Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buffer), -1,
+		&nameString);
+	tclExecutableName = (char *)
+	    ckalloc((unsigned) (Tcl_DStringLength(&nameString) + 1));
+	strcpy(tclExecutableName, Tcl_DStringValue(&nameString));
 
+	Tcl_DStringFree(&nameString);
+    } else {
+	tclExecutableName = (char *) ckalloc((unsigned) (strlen(name) + 1));
+	strcpy(tclExecutableName, name);
+    }
     Tcl_DStringFree(&buffer);
-    Tcl_DStringFree(&nameString);
     return;
 	
     done:
-    TclFindEncodings(argv0);
+    (void) TclFindEncodings(argv0);
 }
 
 /*
@@ -2813,7 +2823,8 @@
  *	assured.
  *
  * Results:
- *	None.
+ *	Return result of TclpInitLibraryPath, which reports whether the
+ *	path is clean (0) or dirty (1) UTF.
  *
  * Side effects:
  *	Varied, see the respective initialization routines.
@@ -2821,11 +2832,13 @@
  *-------------------------------------------------------------------------
  */
 
-void
+int
 TclFindEncodings(argv0)
     CONST char *argv0;		/* Name of executable from argv[0] to main()
 				 * in native multi-byte encoding. */
 {
+    int mustCleanUtf = 0;
+
     if (encodingsInitialized == 0) {
 	/* 
 	 * Double check inside the mutex.  There may be calls
@@ -2846,7 +2859,7 @@
 	    encodingsInitialized = 1;
 
 	    native = TclpFindExecutable(argv0);
-	    TclpInitLibraryPath(native);
+	    mustCleanUtf = TclpInitLibraryPath(native);
 
 	    /*
 	     * The library path was set in the TclpInitLibraryPath routine.
@@ -2856,7 +2869,7 @@
 	     */
 	    
 	    pathPtr = TclGetLibraryPath();
-	    if (pathPtr != NULL) {
+	    if ((pathPtr != NULL) && mustCleanUtf) {
 		Tcl_UtfToExternalDString(NULL, Tcl_GetString(pathPtr), -1,
 			&libPath);
 	    }
@@ -2867,7 +2880,7 @@
 	     * Now convert the native string back to UTF.
 	     */
 	     
-	    if (pathPtr != NULL) {
+	    if ((pathPtr != NULL) && mustCleanUtf) {
 		Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&libPath), -1,
 			&buffer);
 		pathPtr = Tcl_NewStringObj(Tcl_DStringValue(&buffer), -1);
@@ -2879,4 +2892,6 @@
 	}
 	TclpInitUnlock();
     }
+
+    return mustCleanUtf;
 }
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.118.2.3
diff -u -r1.118.2.3 tclInt.h
--- generic/tclInt.h	16 Apr 2003 23:31:44 -0000	1.118.2.3
+++ generic/tclInt.h	29 Mar 2004 18:42:38 -0000
@@ -1636,7 +1636,6 @@
 EXTERN void		TclFinalizeAsync _ANSI_ARGS_((void));
 EXTERN void		TclFinalizeSynchronization _ANSI_ARGS_((void));
 EXTERN void		TclFinalizeThreadData _ANSI_ARGS_((void));
-EXTERN void		TclFindEncodings _ANSI_ARGS_((CONST char *argv0));
 EXTERN int		TclGlob _ANSI_ARGS_((Tcl_Interp *interp,
 			    char *pattern, Tcl_Obj *unquotedPrefix, 
 			    int globFlags, Tcl_GlobTypeData* types));
@@ -1699,7 +1698,7 @@
 			    CONST char *argv0));
 EXTERN int		TclpFindVariable _ANSI_ARGS_((CONST char *name,
 			    int *lengthPtr));
-EXTERN void		TclpInitLibraryPath _ANSI_ARGS_((CONST char *argv0));
+EXTERN int		TclpInitLibraryPath _ANSI_ARGS_((CONST char *argv0));
 EXTERN void		TclpInitLock _ANSI_ARGS_((void));
 EXTERN void		TclpInitPlatform _ANSI_ARGS_((void));
 EXTERN void		TclpInitUnlock _ANSI_ARGS_((void));
Index: mac/tclMacInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/mac/Attic/tclMacInit.c,v
retrieving revision 1.9
diff -u -r1.9 tclMacInit.c
--- mac/tclMacInit.c	8 Feb 2002 02:52:54 -0000	1.9
+++ mac/tclMacInit.c	29 Mar 2004 18:42:38 -0000
@@ -339,7 +339,8 @@
  *	Called at process initialization time.
  *
  * Results:
- *	None.
+ *	Return 1, indicating that the UTF may be dirty and require "cleanup"
+ *	after encodings are initialized.
  *
  * Side effects:
  *	None.
@@ -347,7 +348,7 @@
  *---------------------------------------------------------------------------
  */
 
-void
+int
 TclpInitLibraryPath(argv0)
     CONST char *argv0;		/* Name of executable from argv[0] to main().
 				 * Not used because we can determine the name
@@ -411,6 +412,8 @@
 	    Tcl_DStringFree(&path);
     }    
     TclSetLibraryPath(pathPtr);
+
+    return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */
 }
 
 /*
Index: unix/tclUnixInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixInit.c,v
retrieving revision 1.34.2.3
diff -u -r1.34.2.3 tclUnixInit.c
--- unix/tclUnixInit.c	17 Feb 2004 23:46:54 -0000	1.34.2.3
+++ unix/tclUnixInit.c	29 Mar 2004 18:42:38 -0000
@@ -242,7 +242,8 @@
  *	Called at process initialization time.
  *
  * Results:
- *	None.
+ *	Return 1, indicating that the UTF may be dirty and require "cleanup"
+ *	after encodings are initialized.
  *
  * Side effects:
  *	None.
@@ -250,7 +251,7 @@
  *---------------------------------------------------------------------------
  */
 
-void
+int
 TclpInitLibraryPath(path)
 CONST char *path;		/* Path to the executable in native 
 				 * multi-byte encoding. */
@@ -453,6 +454,8 @@
 
     TclSetLibraryPath(pathPtr);    
     Tcl_DStringFree(&buffer);
+
+    return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */
 }
 
 /*
Index: win/tclWinFile.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinFile.c,v
retrieving revision 1.44.2.6
diff -u -r1.44.2.6 tclWinFile.c
--- win/tclWinFile.c	3 Oct 2003 17:45:37 -0000	1.44.2.6
+++ win/tclWinFile.c	29 Mar 2004 18:42:38 -0000
@@ -665,12 +665,11 @@
  *	application, given its argv[0] value.
  *
  * Results:
- *	A dirty UTF string that is the path to the executable.  At this
- *	point we may not know the system encoding.  Convert the native
- *	string value to UTF using the default encoding.  The assumption
- *	is that we will still be able to parse the path given the path
- *	name contains ASCII string and '/' chars do not conflict with
- *	other UTF chars.
+ *	A clean UTF string that is the path to the executable.  At this
+ *	point we may not know the system encoding, but we convert the
+ *	string value to UTF-8 using core Windows functions.  The path name
+ *	contains ASCII string and '/' chars do not conflict with other UTF
+ *	chars.
  *
  * Side effects:
  *	The variable tclNativeExecutableName gets filled in with the file
@@ -685,8 +684,8 @@
     CONST char *argv0;		/* The value of the application's argv[0]
 				 * (native). */
 {
-    Tcl_DString ds;
     WCHAR wName[MAX_PATH];
+    char name[MAX_PATH * TCL_UTF_MAX];
 
     if (argv0 == NULL) {
 	return NULL;
@@ -700,12 +699,15 @@
      * create this process.
      */
 
-    (*tclWinProcs->getModuleFileNameProc)(NULL, wName, MAX_PATH);
-    Tcl_WinTCharToUtf((CONST TCHAR *) wName, -1, &ds);
+    if (GetModuleFileNameW(NULL, wName, MAX_PATH) == 0) {
+	GetModuleFileNameA(NULL, name, sizeof(name));
+    } else {
+	WideCharToMultiByte(CP_UTF8, 0, wName, -1, 
+		name, sizeof(name), NULL, NULL);
+    }
 
-    tclNativeExecutableName = ckalloc((unsigned) (Tcl_DStringLength(&ds) + 1));
-    strcpy(tclNativeExecutableName, Tcl_DStringValue(&ds));
-    Tcl_DStringFree(&ds);
+    tclNativeExecutableName = ckalloc((unsigned) (strlen(name) + 1));
+    strcpy(tclNativeExecutableName, name);
 
     TclWinNoBackslash(tclNativeExecutableName);
     return tclNativeExecutableName;
Index: win/tclWinInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinInit.c,v
retrieving revision 1.40.2.4
diff -u -r1.40.2.4 tclWinInit.c
--- win/tclWinInit.c	21 Mar 2004 21:03:37 -0000	1.40.2.4
+++ win/tclWinInit.c	29 Mar 2004 18:42:38 -0000
@@ -165,7 +165,7 @@
  *	Called at process initialization time.
  *
  * Results:
- *	None.
+ *	Return 0, indicating that the UTF is clean.
  *
  * Side effects:
  *	None.
@@ -173,7 +173,7 @@
  *---------------------------------------------------------------------------
  */
 
-void
+int
 TclpInitLibraryPath(path)
     CONST char *path;		/* Potentially dirty UTF string that is */
 				/* the path to the executable name.     */
@@ -330,6 +330,8 @@
     }
 
     TclSetLibraryPath(pathPtr);
+
+    return 0; /* 0 indicates that pathPtr is clean (true) utf */
 }
 
 /*
