From 4842df1ea67d934dad86802e91e66aeb8ecad9ed Mon Sep 17 00:00:00 2001 From: hobbs Date: Mon, 29 Mar 2004 18:49:19 +0000 Subject: * generic/tclInt.h: * generic/tclEncoding.c (TclFindEncodings, Tcl_FindExecutable): * mac/tclMacInit.c (TclpInitLibraryPath): Correct handling of UTF * unix/tclUnixInit.c (TclpInitLibraryPath): data that is actually * win/tclWinFile.c (TclpFindExecutable): "clean", allowing the * win/tclWinInit.c (TclpInitLibraryPath): loading of Tcl from paths that contain multi-byte chars on Windows [Bug 920667] --- ChangeLog | 10 ++++++++++ generic/tclEncoding.c | 53 +++++++++++++++++++++++++++++++++------------------ generic/tclInt.h | 5 ++--- mac/tclMacInit.c | 9 ++++++--- unix/tclUnixInit.c | 9 ++++++--- win/tclWinFile.c | 28 ++++++++++++++------------- win/tclWinInit.c | 8 +++++--- 7 files changed, 78 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1661a03..718571c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2004-03-29 Jeff Hobbs + + * generic/tclInt.h: + * generic/tclEncoding.c (TclFindEncodings, Tcl_FindExecutable): + * mac/tclMacInit.c (TclpInitLibraryPath): Correct handling of UTF + * unix/tclUnixInit.c (TclpInitLibraryPath): data that is actually + * win/tclWinFile.c (TclpFindExecutable): "clean", allowing the + * win/tclWinInit.c (TclpInitLibraryPath): loading of Tcl from + paths that contain multi-byte chars on Windows [Bug 920667] + 2004-03-28 Miguel Sofer * generic/tclCompile.c (TclCompileScript): corrected possible diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 7f27ab8..870d587 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclEncoding.c,v 1.16.2.2 2003/11/06 21:47:33 hobbs Exp $ + * RCS: @(#) $Id: tclEncoding.c,v 1.16.2.3 2004/03/29 18:49:35 hobbs Exp $ */ #include "tclInt.h" @@ -227,6 +227,7 @@ static int UtfToUtfProc _ANSI_ARGS_((ClientData clientData, 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 @@ Tcl_FindExecutable(argv0) 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 @@ Tcl_FindExecutable(argv0) /* * 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 @@ unilen(src) * 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 @@ unilen(src) *------------------------------------------------------------------------- */ -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 @@ TclFindEncodings(argv0) encodingsInitialized = 1; native = TclpFindExecutable(argv0); - TclpInitLibraryPath(native); + mustCleanUtf = TclpInitLibraryPath(native); /* * The library path was set in the TclpInitLibraryPath routine. @@ -2856,7 +2869,7 @@ TclFindEncodings(argv0) */ pathPtr = TclGetLibraryPath(); - if (pathPtr != NULL) { + if ((pathPtr != NULL) && mustCleanUtf) { Tcl_UtfToExternalDString(NULL, Tcl_GetString(pathPtr), -1, &libPath); } @@ -2867,7 +2880,7 @@ TclFindEncodings(argv0) * 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 @@ TclFindEncodings(argv0) } TclpInitUnlock(); } + + return mustCleanUtf; } diff --git a/generic/tclInt.h b/generic/tclInt.h index 39343aa..18438e2 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclInt.h,v 1.118.2.3 2003/04/16 23:31:44 dgp Exp $ + * RCS: @(#) $Id: tclInt.h,v 1.118.2.4 2004/03/29 18:49:36 hobbs Exp $ */ #ifndef _TCLINT @@ -1636,7 +1636,6 @@ EXTERN void TclFinalizeNotifier _ANSI_ARGS_((void)); 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 @@ EXTERN char * TclpFindExecutable _ANSI_ARGS_(( 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)); diff --git a/mac/tclMacInit.c b/mac/tclMacInit.c index f132577..a319713 100644 --- a/mac/tclMacInit.c +++ b/mac/tclMacInit.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMacInit.c,v 1.9 2002/02/08 02:52:54 dgp Exp $ + * RCS: @(#) $Id: tclMacInit.c,v 1.9.2.1 2004/03/29 18:49:36 hobbs Exp $ */ #include @@ -339,7 +339,8 @@ TclpInitPlatform() * 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 @@ TclpInitPlatform() *--------------------------------------------------------------------------- */ -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 @@ TclpInitLibraryPath(argv0) Tcl_DStringFree(&path); } TclSetLibraryPath(pathPtr); + + return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */ } /* diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index d0dfd28..a51124e 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -7,7 +7,7 @@ * Copyright (c) 1999 by Scriptics Corporation. * All rights reserved. * - * RCS: @(#) $Id: tclUnixInit.c,v 1.34.2.3 2004/02/17 23:46:54 hobbs Exp $ + * RCS: @(#) $Id: tclUnixInit.c,v 1.34.2.4 2004/03/29 18:49:36 hobbs Exp $ */ #if defined(HAVE_CFBUNDLE) @@ -242,7 +242,8 @@ TclpInitPlatform() * 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 @@ TclpInitPlatform() *--------------------------------------------------------------------------- */ -void +int TclpInitLibraryPath(path) CONST char *path; /* Path to the executable in native * multi-byte encoding. */ @@ -453,6 +454,8 @@ CONST char *path; /* Path to the executable in native TclSetLibraryPath(pathPtr); Tcl_DStringFree(&buffer); + + return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */ } /* diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 13a2c48..6e1dde1 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinFile.c,v 1.44.2.6 2003/10/03 17:45:37 vincentdarley Exp $ + * RCS: @(#) $Id: tclWinFile.c,v 1.44.2.7 2004/03/29 18:49:36 hobbs Exp $ */ //#define _WIN32_WINNT 0x0500 @@ -665,12 +665,11 @@ NativeWriteReparse(LinkDirectory, buffer) * 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 @@ TclpFindExecutable(argv0) 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 @@ TclpFindExecutable(argv0) * 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; diff --git a/win/tclWinInit.c b/win/tclWinInit.c index a65c970..d7ddbb5 100644 --- a/win/tclWinInit.c +++ b/win/tclWinInit.c @@ -7,7 +7,7 @@ * Copyright (c) 1998-1999 by Scriptics Corporation. * All rights reserved. * - * RCS: @(#) $Id: tclWinInit.c,v 1.40.2.4 2004/03/21 21:03:37 hobbs Exp $ + * RCS: @(#) $Id: tclWinInit.c,v 1.40.2.5 2004/03/29 18:49:36 hobbs Exp $ */ #include "tclWinInt.h" @@ -165,7 +165,7 @@ TclpInitPlatform() * Called at process initialization time. * * Results: - * None. + * Return 0, indicating that the UTF is clean. * * Side effects: * None. @@ -173,7 +173,7 @@ TclpInitPlatform() *--------------------------------------------------------------------------- */ -void +int TclpInitLibraryPath(path) CONST char *path; /* Potentially dirty UTF string that is */ /* the path to the executable name. */ @@ -330,6 +330,8 @@ TclpInitLibraryPath(path) } TclSetLibraryPath(pathPtr); + + return 0; /* 0 indicates that pathPtr is clean (true) utf */ } /* -- cgit v0.12