From 9c4ceb163fd879f11fc0c03f0b20f8b86539f76c Mon Sep 17 00:00:00 2001 From: hobbs Date: Wed, 7 Apr 2004 22:04:19 +0000 Subject: * win/tclWinInit.c (TclpSetInitialEncodings): note that WIN32_CE is also a unicode platform. * generic/tclEncoding.c (TclFindEncodings, Tcl_FindExecutable): * generic/tclInt.h: 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 | 9 ++++++++ generic/tclEncoding.c | 59 ++++++++++++++++++++++++++++++++------------------- generic/tclInt.h | 5 ++--- unix/tclUnixInit.c | 9 +++++--- win/tclWinFile.c | 28 ++++++++++++------------ win/tclWinInit.c | 17 +++++++++------ 6 files changed, 80 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 60e7625..82990c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2004-04-07 Jeff Hobbs + * win/tclWinInit.c (TclpSetInitialEncodings): note that WIN32_CE + is also a unicode platform. + * generic/tclEncoding.c (TclFindEncodings, Tcl_FindExecutable): + * generic/tclInt.h: 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] + * win/configure: define TCL_LIB_FLAG, TCL_BUILD_LIB_SPEC, * win/configure.in: TCL_LIB_SPEC, TCL_PACKAGE_PATH in tclConfig.sh. diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 8b6a6b0..094da20 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.18 2004/04/06 22:25:50 dgp Exp $ + * RCS: @(#) $Id: tclEncoding.c,v 1.19 2004/04/07 22:04:28 hobbs Exp $ */ #include "tclInt.h" @@ -226,6 +226,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)); /* @@ -1110,6 +1111,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; @@ -1128,32 +1130,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,14 +2832,12 @@ unilen(src) *------------------------------------------------------------------------- */ -void +int TclFindEncodings(argv0) CONST char *argv0; /* Name of executable from argv[0] to main() * in native multi-byte encoding. */ { - char *native; - Tcl_Obj *pathPtr; - Tcl_DString libPath, buffer; + int mustCleanUtf = 0; if (encodingsInitialized == 0) { /* @@ -2838,6 +2847,10 @@ TclFindEncodings(argv0) TclpInitLock(); if (encodingsInitialized == 0) { + char *native; + Tcl_Obj *pathPtr; + Tcl_DString libPath, buffer; + /* * Have to set this bit here to avoid deadlock with the * routines below us that call into TclInitSubsystems. @@ -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,5 +2892,7 @@ TclFindEncodings(argv0) } TclpInitUnlock(); } + + return mustCleanUtf; } diff --git a/generic/tclInt.h b/generic/tclInt.h index f06642c..f4d1359 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.151 2004/04/06 22:25:53 dgp Exp $ + * RCS: @(#) $Id: tclInt.h,v 1.152 2004/04/07 22:04:29 hobbs Exp $ */ #ifndef _TCLINT @@ -1659,7 +1659,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)); @@ -1740,7 +1739,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/unix/tclUnixInit.c b/unix/tclUnixInit.c index 43f9348..f7e5722 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.40 2004/04/06 22:25:57 dgp Exp $ + * RCS: @(#) $Id: tclUnixInit.c,v 1.41 2004/04/07 22:04:30 hobbs Exp $ */ #if defined(HAVE_CFBUNDLE) @@ -246,7 +246,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. @@ -254,7 +255,7 @@ TclpInitPlatform() *--------------------------------------------------------------------------- */ -void +int TclpInitLibraryPath(path) CONST char *path; /* Path to the executable in native * multi-byte encoding. */ @@ -457,6 +458,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 30d08fa..b7af7d0 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.61 2004/01/29 10:28:23 vincentdarley Exp $ + * RCS: @(#) $Id: tclWinFile.c,v 1.62 2004/04/07 22:04:30 hobbs Exp $ */ //#define _WIN32_WINNT 0x0500 @@ -666,12 +666,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 @@ -686,8 +685,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; @@ -701,12 +700,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 98a6936..fb3c026 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.45 2004/02/12 23:19:17 mdejong Exp $ + * RCS: @(#) $Id: tclWinInit.c,v 1.46 2004/04/07 22:04:31 hobbs Exp $ */ #include "tclWinInt.h" @@ -172,7 +172,7 @@ TclpInitPlatform() * Called at process initialization time. * * Results: - * None. + * Return 0, indicating that the UTF is clean. * * Side effects: * None. @@ -180,7 +180,7 @@ TclpInitPlatform() *--------------------------------------------------------------------------- */ -void +int TclpInitLibraryPath(path) CONST char *path; /* Potentially dirty UTF string that is */ /* the path to the executable name. */ @@ -337,6 +337,8 @@ TclpInitLibraryPath(path) } TclSetLibraryPath(pathPtr); + + return 0; /* 0 indicates that pathPtr is clean (true) utf */ } /* @@ -576,14 +578,17 @@ TclpSetInitialEncodings() char buf[4 + TCL_INTEGER_SPACE]; if (libraryPathEncodingFixed == 0) { - int platformId; + int platformId, useWide; + platformId = TclWinGetPlatformId(); - TclWinSetInterfaces(platformId == VER_PLATFORM_WIN32_NT); + useWide = ((platformId == VER_PLATFORM_WIN32_NT) + || (platformId == VER_PLATFORM_WIN32_CE)); + TclWinSetInterfaces(useWide); wsprintfA(buf, "cp%d", GetACP()); Tcl_SetSystemEncoding(NULL, buf); - if (platformId != VER_PLATFORM_WIN32_NT) { + if (!useWide) { Tcl_Obj *pathPtr = TclGetLibraryPath(); if (pathPtr != NULL) { int i, objc; -- cgit v0.12