diff options
author | dgp <dgp@users.sourceforge.net> | 2004-11-30 19:34:44 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2004-11-30 19:34:44 (GMT) |
commit | 999c1d1867082cb366aeb7bb7d6f46f27ed40596 (patch) | |
tree | 3f6ea55c8096d98ba728284819430a49be305cf6 /unix | |
parent | f1608d9d16479048838c99d496b9f2812de574f2 (diff) | |
download | tcl-999c1d1867082cb366aeb7bb7d6f46f27ed40596.zip tcl-999c1d1867082cb366aeb7bb7d6f46f27ed40596.tar.gz tcl-999c1d1867082cb366aeb7bb7d6f46f27ed40596.tar.bz2 |
Patch 976520 reworks several of the details involved with
startup/initialization of the Tcl library, focused on the
activities of Tcl_FindExecutable().
* generic/tclIO.c: Removed bogus claim in comment that
encoding "iso8859-1" is "built-in" to Tcl.
* generic/tclInt.h: Created a new struct ProcessGlobalValue,
* generic/tclUtil.c: routines Tcl(Get|Set)ProcessGlobalValue,
and function type TclInitProcessGlobalValueProc. Together, these
take care of the housekeeping for "values" (things that can be
held in a Tcl_Obj) that are global across a whole process. That is,
they are shared among multiple threads, and epoch and mutex
protection must govern the validity of cached copies maintained
in each thread.
* generic/tclNotify.c: Modified TclInitNotifier() to tolerate
being called multiple times in the same thread.
* generic/tclEvent.c: Dropped the unused argv0 argument to
TclInitSubsystems(). Removed machinery to unsure only one
TclInitNotifier() call per thread, now that that is safe.
Converted Tcl(Get|Set)LibraryPath to use a ProcessGlobalValue,
and moved them to tclEncoding.c.
* generic/tclBasic.c: Updated caller.
* generic/tclInt.h: TclpFindExecutable now returns void.
* unix/tclUnixFile.c:
* win/tclWinFile.c:
* win/tclWinPipe.c:
* generic/tclEncoding.c: Built new encoding search initialization
on a foundation of ProcessGlobalValues, exposing new routines
Tcl(Get|Set)EncodingSearchPath. A cache of a map from encoding name
to directory pathname keeps track of where encodings are available
for loading. Tcl_FindExecutable greatly simplified into just
three function calls. The "library path" is now misnamed, as its
only remaining purpose is as a foundation for the default encoding
search path.
* generic/tclInterp.c: Inlined the initScript that is evaluated
by Tcl_Init(). Added verification after initScript evaluation
that Tcl can find its installed *.enc files, and that it has
initialized [encoding system] in agreement with what the environment
expects. [tclInit] no longer driven by the value of $::tcl_libPath;
it largely constructs its own search path now, rather than attempt
to share one with the encoding system.
* unix/tclUnixInit.c: TclpSetInitialEncodings factored so that a new
* win/tclWinInit.c: routine TclpGetEncodingNameFromEnvironment
can reveal that Tcl thinks the [encoding system] should be, even
when an incomplete encoding search path, or a missing *.enc file
won't allow that initialization to succeed. TclpInitLibraryPath
reworked as an initializer of a ProcessGlobalValue.
* unix/tclUnixTest.c: Update implementations of [testfindexecutable],
[testgetdefenc], and [testsetdefenc].
* tests/unixInit.test: Corrected tests to operate properly even
when a value of TCL_LIBRARY is required to find encodings.
* generic/tclInt.decls: New internal stubs: TclGetEncodingSearchPath,
TclSetEncodingSearchPath, TclpGetEncodingNameFromEnvironment. These
are candidates for public exposure by future TIPs.
* generic/tclIntDecls.h: make genstubs
* generic/tclStubInit.c:
* generic/tclTest.c: Updated [testencoding] to use
* tests/encoding.test: Tcl(Get|Set)EncodingSearchPath. Updated tests.
Diffstat (limited to 'unix')
-rw-r--r-- | unix/tclUnixFile.c | 41 | ||||
-rw-r--r-- | unix/tclUnixInit.c | 523 | ||||
-rw-r--r-- | unix/tclUnixTest.c | 30 |
3 files changed, 305 insertions, 289 deletions
diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c index 842d1b6..421ea16 100644 --- a/unix/tclUnixFile.c +++ b/unix/tclUnixFile.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUnixFile.c,v 1.42 2004/10/07 14:50:23 vincentdarley Exp $ + * RCS: @(#) $Id: tclUnixFile.c,v 1.43 2004/11/30 19:34:51 dgp Exp $ */ #include "tclInt.h" @@ -42,7 +42,7 @@ static int NativeMatchType(CONST char* nativeName, Tcl_GlobTypeData *types); *--------------------------------------------------------------------------- */ -char * +void TclpFindExecutable(argv0) CONST char *argv0; /* The value of the application's argv[0] * (native). */ @@ -50,13 +50,13 @@ TclpFindExecutable(argv0) CONST char *name, *p; Tcl_StatBuf statBuf; int length; - Tcl_DString buffer, nameString; + Tcl_DString buffer, nameString, cwd; if (argv0 == NULL) { - return NULL; + return; } if (tclFindExecutableSearchDone) { - return tclNativeExecutableName; + return; } tclFindExecutableSearchDone = 1; @@ -135,7 +135,7 @@ TclpFindExecutable(argv0) goto done; /* - * If the name starts with "/" then just copy it to tclExecutableName. + * If the name starts with "/" then just copy it to tclNativeExecutableName. */ gotName: @@ -144,11 +144,9 @@ gotName: #else if (name[0] == '/') { #endif - Tcl_ExternalToUtfDString(NULL, name, -1, &nameString); tclNativeExecutableName = (char *) - ckalloc((unsigned) (Tcl_DStringLength(&nameString) + 1)); - strcpy(tclNativeExecutableName, Tcl_DStringValue(&nameString)); - Tcl_DStringFree(&nameString); + ckalloc((unsigned int) strlen(name) + 1); + strcpy(tclNativeExecutableName, name); goto done; } @@ -162,22 +160,29 @@ gotName: name += 2; } - Tcl_ExternalToUtfDString(NULL, name, -1, &nameString); + Tcl_DStringInit(&nameString); + Tcl_DStringAppend(&nameString, name, -1); + + TclpGetCwd(NULL, &cwd); Tcl_DStringFree(&buffer); - TclpGetCwd(NULL, &buffer); + Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd), + Tcl_DStringLength(&cwd), &buffer); + if (Tcl_DStringValue(&cwd)[Tcl_DStringLength(&cwd) -1] != '/') { + Tcl_DStringAppend(&buffer, "/", 1); + } + Tcl_DStringFree(&cwd); + Tcl_DStringAppend(&buffer, Tcl_DStringValue(&nameString), + Tcl_DStringLength(&nameString)); + Tcl_DStringFree(&nameString); - length = Tcl_DStringLength(&buffer) + Tcl_DStringLength(&nameString) + 2; + length = Tcl_DStringLength(&buffer) + 1; tclNativeExecutableName = (char *) ckalloc((unsigned) length); strcpy(tclNativeExecutableName, Tcl_DStringValue(&buffer)); - tclNativeExecutableName[Tcl_DStringLength(&buffer)] = '/'; - strcpy(tclNativeExecutableName + Tcl_DStringLength(&buffer) + 1, - Tcl_DStringValue(&nameString)); - Tcl_DStringFree(&nameString); done: Tcl_DStringFree(&buffer); - return tclNativeExecutableName; + Tcl_GetNameOfExecutable(); } /* diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index 3592c17..4dd3208 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.52 2004/11/22 22:13:40 dgp Exp $ + * RCS: @(#) $Id: tclUnixInit.c,v 1.53 2004/11/30 19:34:51 dgp Exp $ */ #include "tclInt.h" @@ -93,11 +93,6 @@ static Tcl_ThreadDataKey dataKey; #define STACK_DEBUG(args) (void)0 #endif /* TCL_DEBUG_STACK_CHECK */ -/* Used to store the encoding used for binary files */ -static Tcl_Encoding binaryEncoding = NULL; -/* Has the basic library path encoding issue been fixed */ -static int libraryPathEncodingFixed = 0; - /* * Tcl tries to use standard and homebrew methods to guess the right * encoding on the platform. However, there is always a final fallback, @@ -137,6 +132,147 @@ typedef struct LocaleTable { } LocaleTable; static CONST LocaleTable localeTable[] = { + /* First list all the encoding files installed with Tcl */ + {"ascii", "ascii"}, + {"big5", "big5"}, + {"cp1250", "cp1250"}, + {"cp1251", "cp1251"}, + {"cp1252", "cp1252"}, + {"cp1253", "cp1253"}, + {"cp1254", "cp1254"}, + {"cp1255", "cp1255"}, + {"cp1256", "cp1256"}, + {"cp1257", "cp1257"}, + {"cp1258", "cp1258"}, + {"cp437", "cp437"}, + {"cp737", "cp737"}, + {"cp775", "cp775"}, + {"cp850", "cp850"}, + {"cp852", "cp852"}, + {"cp855", "cp855"}, + {"cp857", "cp857"}, + {"cp860", "cp860"}, + {"cp861", "cp861"}, + {"cp862", "cp862"}, + {"cp863", "cp863"}, + {"cp864", "cp864"}, + {"cp865", "cp865"}, + {"cp866", "cp866"}, + {"cp869", "cp869"}, + {"cp874", "cp874"}, + {"cp932", "cp932"}, + {"cp936", "cp936"}, + {"cp949", "cp949"}, + {"cp950", "cp950"}, + {"dingbats", "dingbats"}, + {"ebcdic", "ebcdic"}, + {"euc-cn", "euc-cn"}, + {"euc-jp", "euc-jp"}, + {"euc-kr", "euc-kr"}, + {"gb12345", "gb12345"}, + {"gb1988", "gb1988"}, + {"gb2312-raw", "gb2312-raw"}, + {"gb2312", "gb2312"}, + {"iso2022-jp", "iso2022-jp"}, + {"iso2022-kr", "iso2022-kr"}, + {"iso2022", "iso2022"}, + {"iso8859-1", "iso8859-1"}, + {"iso8859-10", "iso8859-10"}, + {"iso8859-13", "iso8859-13"}, + {"iso8859-14", "iso8859-14"}, + {"iso8859-15", "iso8859-15"}, + {"iso8859-16", "iso8859-16"}, + {"iso8859-2", "iso8859-2"}, + {"iso8859-3", "iso8859-3"}, + {"iso8859-4", "iso8859-4"}, + {"iso8859-5", "iso8859-5"}, + {"iso8859-6", "iso8859-6"}, + {"iso8859-7", "iso8859-7"}, + {"iso8859-8", "iso8859-8"}, + {"iso8859-9", "iso8859-9"}, + {"jis0201", "jis0201"}, + {"jis0208", "jis0208"}, + {"jis0212", "jis0212"}, + {"koi8-r", "koi8-r"}, + {"koi8-u", "koi8-u"}, + {"ksc5601", "ksc5601"}, + {"macCentEuro", "macCentEuro"}, + {"macCroatian", "macCroatian"}, + {"macCyrillic", "macCyrillic"}, + {"macDingbats", "macDingbats"}, + {"macGreek", "macGreek"}, + {"macIceland", "macIceland"}, + {"macJapan", "macJapan"}, + {"macRoman", "macRoman"}, + {"macRomania", "macRomania"}, + {"macThai", "macThai"}, + {"macTurkish", "macTurkish"}, + {"macUkraine", "macUkraine"}, + {"shiftjis", "shiftjis"}, + {"symbol", "symbol"}, + {"tis-620", "tis-620"}, + /* Next list a few common variants */ + {"maccenteuro", "macCentEuro"}, + {"maccroatian", "macCroatian"}, + {"maccyrillic", "macCyrillic"}, + {"macdingbats", "macDingbats"}, + {"macgreek", "macGreek"}, + {"maciceland", "macIceland"}, + {"macjapan", "macJapan"}, + {"macroman", "macRoman"}, + {"macromania", "macRomania"}, + {"macthai", "macThai"}, + {"macturkish", "macTurkish"}, + {"macukraine", "macUkraine"}, + {"iso-2022-jp", "iso2022-jp"}, + {"iso-2022-kr", "iso2022-kr"}, + {"iso-2022", "iso2022"}, + {"iso-8859-1", "iso8859-1"}, + {"iso-8859-10", "iso8859-10"}, + {"iso-8859-13", "iso8859-13"}, + {"iso-8859-14", "iso8859-14"}, + {"iso-8859-15", "iso8859-15"}, + {"iso-8859-16", "iso8859-16"}, + {"iso-8859-2", "iso8859-2"}, + {"iso-8859-3", "iso8859-3"}, + {"iso-8859-4", "iso8859-4"}, + {"iso-8859-5", "iso8859-5"}, + {"iso-8859-6", "iso8859-6"}, + {"iso-8859-7", "iso8859-7"}, + {"iso-8859-8", "iso8859-8"}, + {"iso-8859-9", "iso8859-9"}, + {"ibm1250", "cp1250"}, + {"ibm1251", "cp1251"}, + {"ibm1252", "cp1252"}, + {"ibm1253", "cp1253"}, + {"ibm1254", "cp1254"}, + {"ibm1255", "cp1255"}, + {"ibm1256", "cp1256"}, + {"ibm1257", "cp1257"}, + {"ibm1258", "cp1258"}, + {"ibm437", "cp437"}, + {"ibm737", "cp737"}, + {"ibm775", "cp775"}, + {"ibm850", "cp850"}, + {"ibm852", "cp852"}, + {"ibm855", "cp855"}, + {"ibm857", "cp857"}, + {"ibm860", "cp860"}, + {"ibm861", "cp861"}, + {"ibm862", "cp862"}, + {"ibm863", "cp863"}, + {"ibm864", "cp864"}, + {"ibm865", "cp865"}, + {"ibm866", "cp866"}, + {"ibm869", "cp869"}, + {"ibm874", "cp874"}, + {"ibm932", "cp932"}, + {"ibm936", "cp936"}, + {"ibm949", "cp949"}, + {"ibm950", "cp950"}, + {"", "iso8859-1"}, + {"ansi_x3.4-1968", "iso8859-1"}, + /* Finally, the accumulated bug fixes... */ #ifdef HAVE_LANGINFO {"gb2312-1980", "gb2312"}, #ifdef __hpux @@ -280,6 +416,25 @@ TclpInitPlatform() */ (void) dlopen (NULL, RTLD_NOW); /* INTL: Native. */ #endif + /* + * Initialize the C library's locale subsystem. This is required + * for input methods to work properly on X11. We only do this for + * LC_CTYPE because that's the necessary one, and we don't want to + * affect LC_TIME here. The side effect of setting the default + * locale should be to load any locale specific modules that are + * needed by X. [BUG: 5422 3345 4236 2522 2521]. + */ + + setlocale(LC_CTYPE, ""); + + /* + * In case the initial locale is not "C", ensure that the numeric + * processing is done in "C" locale regardless. This is needed because + * Tcl relies on routines like strtod, but should not have locale + * dependent behavior. + */ + + setlocale(LC_NUMERIC, "C"); } /* @@ -287,47 +442,24 @@ TclpInitPlatform() * * TclpInitLibraryPath -- * - * Initialize the library path at startup. We have a minor - * metacircular problem that we don't know the encoding of the - * operating system but we may need to talk to operating system - * to find the library directories so that we know how to talk to - * the operating system. - * - * We do not know the encoding of the operating system. - * We do know that the encoding is some multibyte encoding. - * In that multibyte encoding, the characters 0..127 are equivalent - * to ascii. - * - * So although we don't know the encoding, it's safe: - * to look for the last slash character in a path in the encoding. - * to append an ascii string to a path. - * to pass those strings back to the operating system. - * - * But any strings that we remembered before we knew the encoding of - * the operating system must be translated to UTF-8 once we know the - * encoding so that the rest of Tcl can use those strings. - * - * This call sets the library path to strings in the unknown native - * encoding. TclpSetInitialEncodings() will translate the library - * path from the native encoding to UTF-8 as soon as it determines - * what the native encoding actually is. - * - * Called at process initialization time. + * This is the fallback routine that sets the library path + * if the application has not set one by the first time + * it is needed. * * Results: - * Return 1, indicating that the UTF may be dirty and require "cleanup" - * after encodings are initialized. + * None. * * Side effects: - * None. + * Sets the library path to an initial value. * - *--------------------------------------------------------------------------- - */ + *------------------------------------------------------------------------- + */ -int -TclpInitLibraryPath(path) -CONST char *path; /* Path to the executable in native - * multi-byte encoding. */ +void +TclpInitLibraryPath(valuePtr, lengthPtr, encodingPtr) + char **valuePtr; + int *lengthPtr; + Tcl_Encoding *encodingPtr; { #define LIBRARY_SIZE 32 Tcl_Obj *pathPtr, *objPtr; @@ -349,16 +481,6 @@ CONST char *path; /* Path to the executable in native sprintf(installLib, "lib/tcl%s", TCL_VERSION); /* - * Look for the library relative to default encoding dir. - */ - - str = Tcl_GetDefaultEncodingDir(); - if ((str != NULL) && (str[0] != '\0')) { - objPtr = Tcl_NewStringObj(str, -1); - Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); - } - - /* * Look for the library relative to the TCL_LIBRARY env variable. * If the last dirname in the TCL_LIBRARY path does not match the * last dirname in the installLib variable, use the last dir name @@ -411,6 +533,7 @@ CONST char *path; /* Path to the executable in native } else #endif /* HAVE_CFBUNDLE */ { + /* TODO: Pull this value from the TIP 59 table */ str = defaultLibraryDir; } if (str[0] != '\0') { @@ -418,11 +541,13 @@ CONST char *path; /* Path to the executable in native Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); } } - - TclSetLibraryPath(pathPtr); Tcl_DStringFree(&buffer); - return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */ + *encodingPtr = Tcl_GetEncoding(NULL, NULL); + str = Tcl_GetStringFromObj(pathPtr, lengthPtr); + *valuePtr = ckalloc((unsigned int) (*lengthPtr)+1); + memcpy((VOID *) *valuePtr, (VOID *) str, (size_t)(*lengthPtr)+1); + Tcl_DecrRefCount(pathPtr); } /* @@ -452,223 +577,125 @@ CONST char *path; /* Path to the executable in native void TclpSetInitialEncodings() { - if (libraryPathEncodingFixed == 0) { - CONST char *encoding = NULL; - int i, setSysEncCode = TCL_ERROR; - Tcl_Obj *pathPtr; - - /* - * Determine the current encoding from the LC_* or LANG environment - * variables. We previously used setlocale() to determine the locale, - * but this does not work on some systems (e.g. Linux/i386 RH 5.0). - */ -#ifdef HAVE_LANGINFO - if (setlocale(LC_CTYPE, "") != NULL) { - Tcl_DString ds; - - /* - * Use a DString so we can overwrite it in name compatability - * checks below. - */ + Tcl_DString encodingName; + Tcl_SetSystemEncoding(NULL, + TclpGetEncodingNameFromEnvironment(&encodingName)); + Tcl_DStringFree(&encodingName); +} - Tcl_DStringInit(&ds); - encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1); +CONST char * +TclpGetEncodingNameFromEnvironment(bufPtr) + Tcl_DString *bufPtr; +{ + CONST char *encoding; + int i; - Tcl_UtfToLower(Tcl_DStringValue(&ds)); -#ifdef HAVE_LANGINFO_DEBUG - fprintf(stderr, "encoding '%s'", encoding); -#endif - if (encoding[0] == 'i' && encoding[1] == 's' && encoding[2] == 'o' - && encoding[3] == '-') { - char *p, *q; - /* need to strip '-' from iso-* encoding */ - for(p = Tcl_DStringValue(&ds)+3, q = Tcl_DStringValue(&ds)+4; - *p; *p++ = *q++); - } else if (encoding[0] == 'i' && encoding[1] == 'b' - && encoding[2] == 'm' && encoding[3] >= '0' - && encoding[3] <= '9') { - char *p, *q; - /* if langinfo reports "ibm*" we should use "cp*" */ - p = Tcl_DStringValue(&ds); - *p++ = 'c'; *p++ = 'p'; - for(q = p+1; *p ; *p++ = *q++); - } else if ((*encoding == '\0') - || !strcmp(encoding, "ansi_x3.4-1968")) { - /* Use iso8859-1 for empty or 'ansi_x3.4-1968' encoding */ - encoding = "iso8859-1"; - } -#ifdef HAVE_LANGINFO_DEBUG - fprintf(stderr, " ?%s?", encoding); -#endif - setSysEncCode = Tcl_SetSystemEncoding(NULL, encoding); - if (setSysEncCode != TCL_OK) { - /* - * If this doesn't return TCL_OK, the encoding returned by - * nl_langinfo or as we translated it wasn't accepted. Do - * this fallback check. If this fails, we will enter the - * old fallback below. - */ + Tcl_DStringInit(bufPtr); - for (i = 0; localeTable[i].lang != NULL; i++) { - if (strcmp(localeTable[i].lang, encoding) == 0) { - setSysEncCode = Tcl_SetSystemEncoding(NULL, - localeTable[i].encoding); - break; - } + /* + * Determine the current encoding from the LC_* or LANG environment + * variables. We previously used setlocale() to determine the locale, + * but this does not work on some systems (e.g. Linux/i386 RH 5.0). + */ +#ifdef HAVE_LANGINFO + if (setlocale(LC_CTYPE, "") != NULL) { + Tcl_DString ds; + + /* Use a DString so we can modify case. */ + Tcl_DStringInit(&ds); + encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1); + Tcl_UtfToLower(Tcl_DStringValue(&ds)); + /* Check whether it's a known encoding... */ + if (NULL == Tcl_GetEncoding(NULL, encoding)) { + /* ... or in the table if encodings we *should* know */ + for (i = 0; localeTable[i].lang != NULL; i++) { + if (strcmp(localeTable[i].lang, encoding) == 0) { + Tcl_DStringAppend(bufPtr, localeTable[i].encoding, -1); + break; } } -#ifdef HAVE_LANGINFO_DEBUG - fprintf(stderr, " => '%s'\n", encoding); -#endif - Tcl_DStringFree(&ds); + } else { + Tcl_DStringAppend(bufPtr, encoding, -1); } -#ifdef HAVE_LANGINFO_DEBUG - else { - fprintf(stderr, "setlocale returned NULL\n"); + Tcl_DStringFree(&ds); + if (Tcl_DStringLength(bufPtr)) { + return Tcl_DStringValue(bufPtr); } -#endif + } #endif /* HAVE_LANGINFO */ - if (setSysEncCode != TCL_OK) { - /* - * Classic fallback check. This tries a homebrew algorithm to - * determine what encoding should be used based on env vars. - */ - char *langEnv = getenv("LC_ALL"); - encoding = NULL; + /* + * Classic fallback check. This tries a homebrew algorithm to + * determine what encoding should be used based on env vars. + */ + encoding = getenv("LC_ALL"); - if (langEnv == NULL || langEnv[0] == '\0') { - langEnv = getenv("LC_CTYPE"); - } - if (langEnv == NULL || langEnv[0] == '\0') { - langEnv = getenv("LANG"); - } - if (langEnv == NULL || langEnv[0] == '\0') { - langEnv = NULL; - } + if (encoding == NULL || encoding[0] == '\0') { + encoding = getenv("LC_CTYPE"); + } + if (encoding == NULL || encoding[0] == '\0') { + encoding = getenv("LANG"); + } + if (encoding == NULL || encoding[0] == '\0') { + encoding = NULL; + } - if (langEnv != NULL) { - for (i = 0; localeTable[i].lang != NULL; i++) { - if (strcmp(localeTable[i].lang, langEnv) == 0) { - encoding = localeTable[i].encoding; - break; - } - } - /* - * There was no mapping in the locale table. If there is an - * encoding subfield, we can try to guess from that. - */ - - if (encoding == NULL) { - char *p; - for (p = langEnv; *p != '\0'; p++) { - if (*p == '.') { - p++; - break; - } - } - if (*p != '\0') { - Tcl_DString ds; - Tcl_DStringInit(&ds); - encoding = Tcl_DStringAppend(&ds, p, -1); - - Tcl_UtfToLower(Tcl_DStringValue(&ds)); - setSysEncCode = Tcl_SetSystemEncoding(NULL, encoding); - if (setSysEncCode != TCL_OK) { - encoding = NULL; - } - Tcl_DStringFree(&ds); - } - } -#ifdef HAVE_LANGINFO_DEBUG - fprintf(stderr, "encoding fallback check '%s' => '%s'\n", - langEnv, encoding); -#endif - } - if (setSysEncCode != TCL_OK) { - if (encoding == NULL) { - encoding = TCL_DEFAULT_ENCODING; - } + if (encoding != NULL) { + CONST char *p; - Tcl_SetSystemEncoding(NULL, encoding); + /* Check whether it's a known encoding... */ + if (NULL == Tcl_GetEncoding(NULL, encoding)) { + /* ... or in the table if encodings we *should* know */ + for (i = 0; localeTable[i].lang != NULL; i++) { + if (strcmp(localeTable[i].lang, encoding) == 0) { + Tcl_DStringAppend(bufPtr, localeTable[i].encoding, -1); + break; + } } - - /* - * Initialize the C library's locale subsystem. This is required - * for input methods to work properly on X11. We only do this for - * LC_CTYPE because that's the necessary one, and we don't want to - * affect LC_TIME here. The side effect of setting the default - * locale should be to load any locale specific modules that are - * needed by X. [BUG: 5422 3345 4236 2522 2521]. - * In HAVE_LANGINFO, this call is already done above. - */ -#ifndef HAVE_LANGINFO - setlocale(LC_CTYPE, ""); -#endif + } else { + Tcl_DStringAppend(bufPtr, encoding, -1); + } + if (Tcl_DStringLength(bufPtr)) { + return Tcl_DStringValue(bufPtr); } /* - * In case the initial locale is not "C", ensure that the numeric - * processing is done in "C" locale regardless. This is needed because - * Tcl relies on routines like strtod, but should not have locale - * dependent behavior. - */ - - setlocale(LC_NUMERIC, "C"); - - /* - * Until the system encoding was actually set, the library path was - * actually in the native multi-byte encoding, and not really UTF-8 - * as advertised. We cheated as follows: - * - * 1. It was safe to allow the Tcl_SetSystemEncoding() call to - * append the ASCII chars that make up the encoding's filename to - * the names (in the native encoding) of directories in the library - * path, since all Unix multi-byte encodings have ASCII in the - * beginning. - * - * 2. To open the encoding file, the native bytes in the file name - * were passed to the OS, without translating from UTF-8 to native, - * because the name was already in the native encoding. - * - * Now that the system encoding was actually successfully set, - * translate all the names in the library path to UTF-8. That way, - * next time we search the library path, we'll translate the names - * from UTF-8 to the system encoding which will be the native - * encoding. + * We didn't recognize the full value as an encoding name. + * If there is an encoding subfield, we can try to guess from that. */ - pathPtr = TclGetLibraryPath(); - if (pathPtr != NULL) { - int objc; - Tcl_Obj **objv; - - objc = 0; - Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv); - for (i = 0; i < objc; i++) { - int length; - char *string; - Tcl_DString ds; - - string = Tcl_GetStringFromObj(objv[i], &length); - Tcl_ExternalToUtfDString(NULL, string, length, &ds); - Tcl_SetStringObj(objv[i], Tcl_DStringValue(&ds), - Tcl_DStringLength(&ds)); - Tcl_DStringFree(&ds); + for (p = encoding; *p != '\0'; p++) { + if (*p == '.') { + p++; + break; } } + if (*p != '\0') { + Tcl_DString ds; + Tcl_DStringInit(&ds); + encoding = Tcl_DStringAppend(&ds, p, -1); + Tcl_UtfToLower(Tcl_DStringValue(&ds)); - libraryPathEncodingFixed = 1; - } + /* Check whether it's a known encoding... */ + if (NULL == Tcl_GetEncoding(NULL, encoding)) { + /* ... or in the table if encodings we *should* know */ + for (i = 0; localeTable[i].lang != NULL; i++) { + if (strcmp(localeTable[i].lang, encoding) == 0) { + Tcl_DStringAppend(bufPtr, localeTable[i].encoding, -1); + break; + } + } + } else { + Tcl_DStringAppend(bufPtr, encoding, -1); + } + Tcl_DStringFree(&ds); + if (Tcl_DStringLength(bufPtr)) { + return Tcl_DStringValue(bufPtr); + } - /* This is only ever called from the startup thread */ - if (binaryEncoding == NULL) { - /* - * Keep the iso8859-1 encoding preloaded. The IO package uses - * it for gets on a binary channel. - */ - binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1"); + } } + return Tcl_DStringAppend(bufPtr, TCL_DEFAULT_ENCODING, -1); } /* diff --git a/unix/tclUnixTest.c b/unix/tclUnixTest.c index 955f719..9b5c717 100644 --- a/unix/tclUnixTest.c +++ b/unix/tclUnixTest.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUnixTest.c,v 1.18 2004/06/18 20:38:02 dgp Exp $ + * RCS: @(#) $Id: tclUnixTest.c,v 1.19 2004/11/30 19:34:51 dgp Exp $ */ #include "tclInt.h" @@ -444,7 +444,6 @@ TestfindexecutableCmd(clientData, interp, argc, argv) int argc; /* Number of arguments. */ CONST char **argv; /* Argument strings. */ { - char *oldName; char *oldNativeName; int oldDone; @@ -454,24 +453,19 @@ TestfindexecutableCmd(clientData, interp, argc, argv) return TCL_ERROR; } - oldName = tclExecutableName; oldNativeName = tclNativeExecutableName; oldDone = tclFindExecutableSearchDone; - tclExecutableName = NULL; tclNativeExecutableName = NULL; tclFindExecutableSearchDone = 0; + Tcl_GetNameOfExecutable(); Tcl_FindExecutable(argv[1]); - if (tclExecutableName != NULL) { - Tcl_SetResult(interp, tclExecutableName, TCL_VOLATILE); - ckfree(tclExecutableName); - } + Tcl_SetResult(interp, (char *) Tcl_GetNameOfExecutable(), TCL_VOLATILE); if (tclNativeExecutableName != NULL) { ckfree(tclNativeExecutableName); } - tclExecutableName = oldName; tclNativeExecutableName = oldNativeName; tclFindExecutableSearchDone = oldDone; @@ -529,7 +523,7 @@ TestgetopenfileCmd(clientData, interp, argc, argv) * TestsetdefencdirCmd -- * * This procedure implements the "testsetdefenc" command. It is - * used to set the value of tclDefaultEncodingDir. + * used to test Tcl_SetDefaultEncodingDir(). * * Results: * A standard Tcl result. @@ -555,15 +549,7 @@ TestsetdefencdirCmd(clientData, interp, argc, argv) return TCL_ERROR; } - if (tclDefaultEncodingDir != NULL) { - ckfree(tclDefaultEncodingDir); - tclDefaultEncodingDir = NULL; - } - if (*argv[1] != '\0') { - tclDefaultEncodingDir = (char *) - ckalloc((unsigned) strlen(argv[1]) + 1); - strcpy(tclDefaultEncodingDir, argv[1]); - } + Tcl_SetDefaultEncodingDir(argv[1]); return TCL_OK; } @@ -573,7 +559,7 @@ TestsetdefencdirCmd(clientData, interp, argc, argv) * TestgetdefencdirCmd -- * * This procedure implements the "testgetdefenc" command. It is - * used to get the value of tclDefaultEncodingDir. + * used to test Tcl_GetDefaultEncodingDir(). * * Results: * A standard Tcl result. @@ -598,9 +584,7 @@ TestgetdefencdirCmd(clientData, interp, argc, argv) return TCL_ERROR; } - if (tclDefaultEncodingDir != NULL) { - Tcl_AppendResult(interp, tclDefaultEncodingDir, (char *) NULL); - } + Tcl_AppendResult(interp, Tcl_GetDefaultEncodingDir(), (char *) NULL); return TCL_OK; } |