os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixInit.c
Update contrib.
4 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
6 * Contains the Unix-specific interpreter initialization functions.
8 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
9 * Copyright (c) 1999 by Scriptics Corporation.
10 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
11 * All rights reserved.
13 * RCS: @(#) $Id: tclUnixInit.c,v 1.34.2.15 2007/04/29 02:19:51 das Exp $
16 #if defined(HAVE_COREFOUNDATION)
17 #include <CoreFoundation/CoreFoundation.h>
23 # include <langinfo.h>
25 # if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030
26 /* Support for weakly importing nl_langinfo on Darwin. */
27 # define WEAK_IMPORT_NL_LANGINFO
28 extern char *nl_langinfo(nl_item) WEAK_IMPORT_ATTRIBUTE;
32 #if defined(__FreeBSD__) && defined(__GNUC__)
33 # include <floatingpoint.h>
36 # include <sys/param.h>
37 # if _BSDI_VERSION > 199501
42 #if defined(__SYMBIAN32__)
43 #include "tclSymbianGlobals.h"
44 #include "convertPathSlashes.h"
48 * The Init script (common to Windows and Unix platforms) is
49 * defined in tkInitScript.h
51 #include "tclInitScript.h"
53 /* Used to store the encoding used for binary files */
54 static Tcl_Encoding binaryEncoding = NULL;
55 /* Has the basic library path encoding issue been fixed */
56 static int libraryPathEncodingFixed = 0;
59 * Tcl tries to use standard and homebrew methods to guess the right
60 * encoding on the platform. However, there is always a final fallback,
61 * and this value is it. Make sure it is a real Tcl encoding.
64 #ifndef TCL_DEFAULT_ENCODING
65 #define TCL_DEFAULT_ENCODING "iso8859-1"
69 * Default directory in which to look for Tcl library scripts. The
70 * symbol is defined by Makefile.
73 // building one *.exe, giving substitute values to tclUnixInt.c (l#65) to bypass compiler errors for 'normal' install.
74 // IMPORTANT NOTE: tcl uses unix-style slashes _inside_ tcl.
76 #define TCL_LIBRARY "C:/private/00000000/library/"
80 static char defaultLibraryDir[sizeof(TCL_LIBRARY)+200] = TCL_LIBRARY;
83 * Directory in which to look for packages (each package is typically
84 * installed as a subdirectory of this directory). The symbol is
85 * defined by Makefile.
88 // building one *.exe, giving substitute values to tclUnixInt.c (l#65) to bypass compiler errors for 'normal' install.
89 // IMPORTANT NOTE: tcl uses unix-style slashes _insode_ tcl.
90 #ifndef TCL_PACKAGE_PATH
91 #define TCL_PACKAGE_PATH "C:/private/00000000/"
95 static char pkgPath[sizeof(TCL_PACKAGE_PATH)+200] = TCL_PACKAGE_PATH;
98 * The following table is used to map from Unix locale strings to
99 * encoding files. If HAVE_LANGINFO is defined, then this is a fallback
100 * table when the result from nl_langinfo isn't a recognized encoding.
101 * Otherwise this is the first list checked for a mapping from env
102 * encoding to Tcl encoding name.
105 typedef struct LocaleTable {
107 CONST char *encoding;
110 static CONST LocaleTable localeTable[] = {
112 {"gb2312-1980", "gb2312"},
113 {"ansi-1251", "cp1251"}, /* Solaris gets this wrong. */
115 {"SJIS", "shiftjis"},
120 {"iso88591", "iso8859-1"},
121 {"iso88592", "iso8859-2"},
122 {"iso88595", "iso8859-5"},
123 {"iso88596", "iso8859-6"},
124 {"iso88597", "iso8859-7"},
125 {"iso88598", "iso8859-8"},
126 {"iso88599", "iso8859-9"},
127 {"iso885915", "iso8859-15"},
128 {"roman8", "iso8859-1"},
129 {"tis620", "tis-620"},
130 {"turkish8", "cp857"},
133 #endif /* HAVE_LANGINFO */
135 {"ja_JP.SJIS", "shiftjis"},
136 {"ja_JP.EUC", "euc-jp"},
137 {"ja_JP.eucJP", "euc-jp"},
138 {"ja_JP.JIS", "iso2022-jp"},
139 {"ja_JP.mscode", "shiftjis"},
140 {"ja_JP.ujis", "euc-jp"},
142 {"Ja_JP", "shiftjis"},
143 {"Jp_JP", "shiftjis"},
146 {"japanese", "shiftjis"},
149 {"japanese", "euc-jp"},
152 {"japanese.sjis", "shiftjis"},
153 {"japanese.euc", "euc-jp"},
154 {"japanese-sjis", "shiftjis"},
155 {"japanese-ujis", "euc-jp"},
159 {"ko_KR.EUC", "euc-kr"},
160 {"ko_KR.euc", "euc-kr"},
161 {"ko_KR.eucKR", "euc-kr"},
162 {"korean", "euc-kr"},
165 {"ru_RU", "iso8859-5"},
166 {"ru_SU", "iso8859-5"},
169 {"zh_CN.gb2312", "euc-cn"},
170 {"zh_CN.GB2312", "euc-cn"},
171 {"zh_CN.GBK", "euc-cn"},
172 {"zh_TW.Big5", "big5"},
178 #ifdef HAVE_COREFOUNDATION
179 static int MacOSXGetLibraryPath _ANSI_ARGS_((
180 Tcl_Interp *interp, int maxPathLen,
182 #endif /* HAVE_COREFOUNDATION */
183 #if defined(__APPLE__) && (defined(TCL_LOAD_FROM_MEMORY) || ( \
184 defined(TCL_THREADS) && defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
185 MAC_OS_X_VERSION_MIN_REQUIRED < 1030) || ( \
186 defined(__LP64__) && defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
187 MAC_OS_X_VERSION_MIN_REQUIRED < 1050))
189 * Need to check Darwin release at runtime in tclUnixFCmd.c and tclLoadDyld.c:
190 * initialize release global at startup from uname().
192 #define GET_DARWIN_RELEASE 1
193 long tclMacOSXDarwinRelease = 0;
198 *---------------------------------------------------------------------------
200 * TclpInitPlatform --
202 * Initialize all the platform-dependant things like signals and
203 * floating-point error handling.
205 * Called at process initialization time.
213 *---------------------------------------------------------------------------
219 #if defined(__SYMBIAN32__)
220 // we need to use Windows file and path name convention with unix code.
221 tclPlatform = TCL_PLATFORM_WINDOWS;
223 tclPlatform = TCL_PLATFORM_UNIX;
227 * Make sure, that the standard FDs exist. [Bug 772288]
229 if (TclOSseek(0, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
230 open("/dev/null", O_RDONLY);
232 if (TclOSseek(1, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
233 open("/dev/null", O_WRONLY);
235 if (TclOSseek(2, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
236 open("/dev/null", O_WRONLY);
240 * The code below causes SIGPIPE (broken pipe) errors to
241 * be ignored. This is needed so that Tcl processes don't
242 * die if they create child processes (e.g. using "exec" or
243 * "open") that terminate prematurely. The signal handler
244 * is only set up when the first interpreter is created;
245 * after this the application can override the handler with
246 * a different one of its own, if it wants.
250 (void) signal(SIGPIPE, SIG_IGN);
253 #if defined(__FreeBSD__) && defined(__GNUC__)
255 * Adjust the rounding mode to be more conventional. Note that FreeBSD
256 * only provides the __fpsetreg() used by the following two for the GNU
257 * Compiler. When using, say, Intel's icc they break. (Partially based on
258 * patch in BSD ports system from root@celsius.bychok.com)
265 #if defined(__bsdi__) && (_BSDI_VERSION > 199501)
267 * Find local symbols. Don't report an error if we fail.
269 (void) dlopen (NULL, RTLD_NOW); /* INTL: Native. */
272 #ifdef GET_DARWIN_RELEASE
276 tclMacOSXDarwinRelease = strtol(name.release, NULL, 10);
283 *---------------------------------------------------------------------------
285 * TclpInitLibraryPath --
287 * Initialize the library path at startup. We have a minor
288 * metacircular problem that we don't know the encoding of the
289 * operating system but we may need to talk to operating system
290 * to find the library directories so that we know how to talk to
291 * the operating system.
293 * We do not know the encoding of the operating system.
294 * We do know that the encoding is some multibyte encoding.
295 * In that multibyte encoding, the characters 0..127 are equivalent
298 * So although we don't know the encoding, it's safe:
299 * to look for the last slash character in a path in the encoding.
300 * to append an ascii string to a path.
301 * to pass those strings back to the operating system.
303 * But any strings that we remembered before we knew the encoding of
304 * the operating system must be translated to UTF-8 once we know the
305 * encoding so that the rest of Tcl can use those strings.
307 * This call sets the library path to strings in the unknown native
308 * encoding. TclpSetInitialEncodings() will translate the library
309 * path from the native encoding to UTF-8 as soon as it determines
310 * what the native encoding actually is.
312 * Called at process initialization time.
315 * Return 1, indicating that the UTF may be dirty and require "cleanup"
316 * after encodings are initialized.
321 *---------------------------------------------------------------------------
325 TclpInitLibraryPath(path)
326 CONST char *path; /* Path to the executable in native
327 * multi-byte encoding. */
329 #define LIBRARY_SIZE 32
330 Tcl_Obj *pathPtr, *objPtr;
332 Tcl_DString buffer, ds;
335 char installLib[LIBRARY_SIZE], developLib[LIBRARY_SIZE];
338 char homeEnvVariableBuf[LIBRARY_SIZE];
339 char *homeEnvVariableStr;
342 Tcl_DStringInit(&ds);
343 pathPtr = Tcl_NewObj();
346 * Initialize the substrings used when locating an executable. The
347 * installLib variable computes the path as though the executable
348 * is installed. The developLib computes the path as though the
349 * executable is run from a develpment directory.
352 sprintf(installLib, "lib/tcl%s", TCL_VERSION);
353 sprintf(developLib, "tcl%s/library", TCL_PATCH_LEVEL);
356 * Look for the library relative to default encoding dir.
359 str = Tcl_GetDefaultEncodingDir();
360 if ((str != NULL) && (str[0] != '\0')) {
361 objPtr = Tcl_NewStringObj(str, -1);
362 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
366 * Look for the library relative to the TCL_LIBRARY env variable.
367 * If the last dirname in the TCL_LIBRARY path does not match the
368 * last dirname in the installLib variable, use the last dir name
369 * of installLib in addition to the orginal TCL_LIBRARY path.
373 // add setenv so that tcl has access to the TCL_LIBRARY "system" environment var. (It can also be accessed from *.tcl scripts.)
374 if (!getenv("HOME")) {
375 homeEnvVariableStr = getcwd(homeEnvVariableBuf, LIBRARY_SIZE);
376 if (!homeEnvVariableStr) {
377 fprintf(stderr, "Error getting cwd, defaulting to SYMB_TCL_DEFAULT_HOME_DIR.\r\n");
379 /* TODO - the line bellow is a temporary patch. The defect number is: DEF116621. */
380 homeEnvVariableBuf[0] = 'c';
381 tclCopySymbianPathSlashConversion(TO_TCL, homeEnvVariableStr, homeEnvVariableStr);
382 retEnv = setenv("HOME", homeEnvVariableStr, 1);
385 fprintf(stderr, "Error setting env(HOME)\r\n");
388 // add setenv so that tcl has access to the TCL_LIBRARY "system" environment var. (It can also be accessed from *.tcl scripts.)
389 retEnv = setenv("TCL_LIBRARY", TCL_LIBRARY, 1);
392 fprintf(stderr, "Error setting env(TCL_LIBRARY)\r\n");
394 // add setenv so that tcl has access to the TCL_LIBRARY "system" environment var 'tcllibpath' in init.tcl. (It can also be accessed from *.tcl scripts.)
395 retEnv = setenv("TCLLIBPATH", TCL_LIBRARY, 1);
398 fprintf(stderr, "Error setting env(TCLLIBPATH)\r\n");
401 str = getenv("TCL_LIBRARY"); /* INTL: Native. */
402 Tcl_ExternalToUtfDString(NULL, str, -1, &buffer);
403 str = Tcl_DStringValue(&buffer);
405 if ((str != NULL) && (str[0] != '\0')) {
407 * If TCL_LIBRARY is set, search there.
410 objPtr = Tcl_NewStringObj(str, -1);
411 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
413 Tcl_SplitPath(str, &pathc, &pathv);
414 if ((pathc > 0) && (strcasecmp(installLib + 4, pathv[pathc-1]) != 0)) {
416 * If TCL_LIBRARY is set but refers to a different tcl
417 * installation than the current version, try fiddling with the
418 * specified directory to make it refer to this installation by
419 * removing the old "tclX.Y" and substituting the current
423 pathv[pathc - 1] = installLib + 4;
424 str = Tcl_JoinPath(pathc, pathv, &ds);
425 objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&ds));
426 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
427 Tcl_DStringFree(&ds);
429 ckfree((char *) pathv);
433 * Look for the library relative to the executable. This algorithm
434 * should be the same as the one in the tcl_findLibrary procedure.
436 * This code looks in the following directories:
438 * <bindir>/../<installLib>
439 * (e.g. /usr/local/bin/../lib/tcl8.4)
440 * <bindir>/../../<installLib>
441 * (e.g. /usr/local/TclPro/solaris-sparc/bin/../../lib/tcl8.4)
442 * <bindir>/../library
443 * (e.g. /usr/src/tcl8.4.0/unix/../library)
444 * <bindir>/../../library
445 * (e.g. /usr/src/tcl8.4.0/unix/solaris-sparc/../../library)
446 * <bindir>/../../<developLib>
447 * (e.g. /usr/src/tcl8.4.0/unix/../../tcl8.4.0/library)
448 * <bindir>/../../../<developLib>
449 * (e.g. /usr/src/tcl8.4.0/unix/solaris-sparc/../../../tcl8.4.0/library)
454 * The variable path holds an absolute path. Take care not to
455 * overwrite pathv[0] since that might produce a relative path.
457 #ifndef __SYMBIAN32__
462 Tcl_SplitPath(path, &origc, &origv);
464 pathv = (CONST char **) ckalloc((unsigned int)(origc * sizeof(char *)));
465 for (i=0; i< origc; i++) {
466 if (origv[i][0] == '.') {
467 if (strcmp(origv[i], ".") == 0) {
469 } else if (strcmp(origv[i], "..") == 0) {
472 pathv[pathc++] = origv[i];
475 pathv[pathc++] = origv[i];
479 str = pathv[pathc - 2];
480 pathv[pathc - 2] = installLib;
481 path = Tcl_JoinPath(pathc - 1, pathv, &ds);
482 pathv[pathc - 2] = str;
483 objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
484 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
485 Tcl_DStringFree(&ds);
488 str = pathv[pathc - 3];
489 pathv[pathc - 3] = installLib;
490 path = Tcl_JoinPath(pathc - 2, pathv, &ds);
491 pathv[pathc - 3] = str;
492 objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
493 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
494 Tcl_DStringFree(&ds);
497 str = pathv[pathc - 2];
498 pathv[pathc - 2] = "library";
499 path = Tcl_JoinPath(pathc - 1, pathv, &ds);
500 pathv[pathc - 2] = str;
501 objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
502 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
503 Tcl_DStringFree(&ds);
506 str = pathv[pathc - 3];
507 pathv[pathc - 3] = "library";
508 path = Tcl_JoinPath(pathc - 2, pathv, &ds);
509 pathv[pathc - 3] = str;
510 objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
511 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
512 Tcl_DStringFree(&ds);
515 str = pathv[pathc - 3];
516 pathv[pathc - 3] = developLib;
517 path = Tcl_JoinPath(pathc - 2, pathv, &ds);
518 pathv[pathc - 3] = str;
519 objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
520 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
521 Tcl_DStringFree(&ds);
524 str = pathv[pathc - 4];
525 pathv[pathc - 4] = developLib;
526 path = Tcl_JoinPath(pathc - 3, pathv, &ds);
527 pathv[pathc - 4] = str;
528 objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
529 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
530 Tcl_DStringFree(&ds);
532 ckfree((char *) origv);
533 ckfree((char *) pathv);
538 * Finally, look for the library relative to the compiled-in path.
539 * This is needed when users install Tcl with an exec-prefix that
540 * is different from the prtefix.
544 #ifdef HAVE_COREFOUNDATION
545 char tclLibPath[MAXPATHLEN + 1];
547 if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
550 #endif /* HAVE_COREFOUNDATION */
552 str = defaultLibraryDir;
554 if (str[0] != '\0') {
555 objPtr = Tcl_NewStringObj(str, -1);
556 Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
560 TclSetLibraryPath(pathPtr);
561 Tcl_DStringFree(&buffer);
563 return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */
567 *---------------------------------------------------------------------------
569 * TclpSetInitialEncodings --
571 * Based on the locale, determine the encoding of the operating
572 * system and the default encoding for newly opened files.
574 * Called at process initialization time, and part way through
575 * startup, we verify that the initial encodings were correctly
576 * setup. Depending on Tcl's environment, there may not have been
577 * enough information first time through (above).
583 * The Tcl library path is converted from native encoding to UTF-8,
584 * on the first call, and the encodings may be changed on first or
587 *---------------------------------------------------------------------------
591 TclpSetInitialEncodings()
593 CONST char *encoding = NULL;
594 int i, setSysEncCode = TCL_ERROR;
598 * Determine the current encoding from the LC_* or LANG environment
599 * variables. We previously used setlocale() to determine the locale,
600 * but this does not work on some systems (e.g. Linux/i386 RH 5.0).
604 #ifdef WEAK_IMPORT_NL_LANGINFO
605 nl_langinfo != NULL &&
607 setlocale(LC_CTYPE, "") != NULL) {
611 * Use a DString so we can overwrite it in name compatability
615 Tcl_DStringInit(&ds);
616 encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
618 Tcl_UtfToLower(Tcl_DStringValue(&ds));
619 #ifdef HAVE_LANGINFO_DEBUG
620 fprintf(stderr, "encoding '%s'\r\n", encoding);
622 if (encoding[0] == 'i' && encoding[1] == 's' && encoding[2] == 'o'
623 && encoding[3] == '-') {
625 /* need to strip '-' from iso-* encoding */
626 for(p = Tcl_DStringValue(&ds)+3, q = Tcl_DStringValue(&ds)+4;
628 } else if (encoding[0] == 'i' && encoding[1] == 'b'
629 && encoding[2] == 'm' && encoding[3] >= '0'
630 && encoding[3] <= '9') {
632 /* if langinfo reports "ibm*" we should use "cp*" */
633 p = Tcl_DStringValue(&ds);
634 *p++ = 'c'; *p++ = 'p';
635 for(q = p+1; *p ; *p++ = *q++);
636 } else if ((*encoding == '\0')
637 || !strcmp(encoding, "ansi_x3.4-1968")) {
638 /* Use iso8859-1 for empty or 'ansi_x3.4-1968' encoding */
639 encoding = "iso8859-1";
641 #ifdef HAVE_LANGINFO_DEBUG
642 fprintf(stderr, " ?%s?\r\n", encoding);
644 setSysEncCode = Tcl_SetSystemEncoding(NULL, encoding);
645 if (setSysEncCode != TCL_OK) {
647 * If this doesn't return TCL_OK, the encoding returned by
648 * nl_langinfo or as we translated it wasn't accepted. Do
649 * this fallback check. If this fails, we will enter the
650 * old fallback below.
653 for (i = 0; localeTable[i].lang != NULL; i++) {
654 if (strcmp(localeTable[i].lang, encoding) == 0) {
655 setSysEncCode = Tcl_SetSystemEncoding(NULL,
656 localeTable[i].encoding);
661 #ifdef HAVE_LANGINFO_DEBUG
662 fprintf(stderr, " => '%s'\n", encoding);
664 Tcl_DStringFree(&ds);
666 #ifdef HAVE_LANGINFO_DEBUG
668 fprintf(stderr, "setlocale returned NULL\n");
671 #endif /* HAVE_LANGINFO */
673 if (setSysEncCode != TCL_OK) {
675 * Classic fallback check. This tries a homebrew algorithm to
676 * determine what encoding should be used based on env vars.
678 char *langEnv = getenv("LC_ALL");
681 if (langEnv == NULL || langEnv[0] == '\0') {
682 langEnv = getenv("LC_CTYPE");
684 if (langEnv == NULL || langEnv[0] == '\0') {
685 langEnv = getenv("LANG");
687 if (langEnv == NULL || langEnv[0] == '\0') {
691 if (langEnv != NULL) {
692 for (i = 0; localeTable[i].lang != NULL; i++) {
693 if (strcmp(localeTable[i].lang, langEnv) == 0) {
694 encoding = localeTable[i].encoding;
699 * There was no mapping in the locale table. If there is an
700 * encoding subfield, we can try to guess from that.
703 if (encoding == NULL) {
705 for (p = langEnv; *p != '\0'; p++) {
713 Tcl_DStringInit(&ds);
714 encoding = Tcl_DStringAppend(&ds, p, -1);
716 Tcl_UtfToLower(Tcl_DStringValue(&ds));
717 setSysEncCode = Tcl_SetSystemEncoding(NULL, encoding);
718 if (setSysEncCode != TCL_OK) {
721 Tcl_DStringFree(&ds);
724 #ifdef HAVE_LANGINFO_DEBUG
725 fprintf(stderr, "encoding fallback check '%s' => '%s'\n",
729 if (setSysEncCode != TCL_OK) {
730 if (encoding == NULL) {
731 encoding = TCL_DEFAULT_ENCODING;
734 Tcl_SetSystemEncoding(NULL, encoding);
738 * Initialize the C library's locale subsystem. This is required
739 * for input methods to work properly on X11. We only do this for
740 * LC_CTYPE because that's the necessary one, and we don't want to
741 * affect LC_TIME here. The side effect of setting the default
742 * locale should be to load any locale specific modules that are
743 * needed by X. [BUG: 5422 3345 4236 2522 2521].
744 * In HAVE_LANGINFO, this call is already done above.
746 #ifndef HAVE_LANGINFO
747 setlocale(LC_CTYPE, "");
752 * In case the initial locale is not "C", ensure that the numeric
753 * processing is done in "C" locale regardless. This is needed because
754 * Tcl relies on routines like strtod, but should not have locale
755 * dependent behavior.
758 setlocale(LC_NUMERIC, "C");
760 if ((libraryPathEncodingFixed == 0) && strcmp("identity",
761 Tcl_GetEncodingName(Tcl_GetEncoding(NULL, NULL))) ) {
763 * Until the system encoding was actually set, the library path was
764 * actually in the native multi-byte encoding, and not really UTF-8
765 * as advertised. We cheated as follows:
767 * 1. It was safe to allow the Tcl_SetSystemEncoding() call to
768 * append the ASCII chars that make up the encoding's filename to
769 * the names (in the native encoding) of directories in the library
770 * path, since all Unix multi-byte encodings have ASCII in the
773 * 2. To open the encoding file, the native bytes in the file name
774 * were passed to the OS, without translating from UTF-8 to native,
775 * because the name was already in the native encoding.
777 * Now that the system encoding was actually successfully set,
778 * translate all the names in the library path to UTF-8. That way,
779 * next time we search the library path, we'll translate the names
780 * from UTF-8 to the system encoding which will be the native
784 pathPtr = TclGetLibraryPath();
785 if (pathPtr != NULL) {
790 Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv);
791 for (i = 0; i < objc; i++) {
796 string = Tcl_GetStringFromObj(objv[i], &length);
797 Tcl_ExternalToUtfDString(NULL, string, length, &ds);
798 Tcl_SetStringObj(objv[i], Tcl_DStringValue(&ds),
799 Tcl_DStringLength(&ds));
800 Tcl_DStringFree(&ds);
804 libraryPathEncodingFixed = 1;
807 /* This is only ever called from the startup thread */
808 if (binaryEncoding == NULL) {
810 * Keep the iso8859-1 encoding preloaded. The IO package uses
811 * it for gets on a binary channel.
813 binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");
818 *---------------------------------------------------------------------------
820 * TclpSetVariables --
822 * Performs platform-specific interpreter initialization related to
823 * the tcl_library and tcl_platform variables, and other platform-
830 * Sets "tclDefaultLibrary", "tcl_pkgPath", and "tcl_platform" Tcl
833 *----------------------------------------------------------------------
837 TclpSetVariables(interp)
847 #ifdef HAVE_COREFOUNDATION
848 char tclLibPath[MAXPATHLEN + 1];
850 #if MAC_OS_X_VERSION_MAX_ALLOWED > 1020
852 * Set msgcat fallback locale to current CFLocale identifier.
854 CFLocaleRef localeRef;
856 if (CFLocaleCopyCurrent != NULL && CFLocaleGetIdentifier != NULL &&
857 (localeRef = CFLocaleCopyCurrent())) {
858 CFStringRef locale = CFLocaleGetIdentifier(localeRef);
863 if (CFStringGetCString(locale, loc, 256, kCFStringEncodingUTF8)) {
864 if (!Tcl_CreateNamespace(interp, "::tcl::mac", NULL, NULL)) {
865 Tcl_ResetResult(interp);
867 Tcl_SetVar(interp, "::tcl::mac::locale", loc, TCL_GLOBAL_ONLY);
870 CFRelease(localeRef);
874 if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) {
877 CFBundleRef bundleRef;
879 Tcl_SetVar(interp, "tclDefaultLibrary", tclLibPath,
881 Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
883 Tcl_SetVar(interp, "tcl_pkgPath", " ",
884 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
885 str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
886 if ((str != NULL) && (str[0] != '\0')) {
887 char *p = Tcl_DStringValue(&ds);
888 /* convert DYLD_FRAMEWORK_PATH from colon to space separated */
890 if(*p == ':') *p = ' ';
892 Tcl_SetVar(interp, "tcl_pkgPath", Tcl_DStringValue(&ds),
893 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
894 Tcl_SetVar(interp, "tcl_pkgPath", " ",
895 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
896 Tcl_DStringFree(&ds);
898 if ((bundleRef = CFBundleGetMainBundle())) {
899 CFURLRef frameworksURL;
901 if((frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef))) {
902 if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
903 (unsigned char*) tclLibPath, MAXPATHLEN) &&
904 ! TclOSstat(tclLibPath, &statBuf) &&
905 S_ISDIR(statBuf.st_mode)) {
906 Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
907 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
908 Tcl_SetVar(interp, "tcl_pkgPath", " ",
909 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
911 CFRelease(frameworksURL);
913 if((frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef))) {
914 if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
915 (unsigned char*) tclLibPath, MAXPATHLEN) &&
916 ! TclOSstat(tclLibPath, &statBuf) &&
917 S_ISDIR(statBuf.st_mode)) {
918 Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
919 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
920 Tcl_SetVar(interp, "tcl_pkgPath", " ",
921 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
923 CFRelease(frameworksURL);
926 Tcl_SetVar(interp, "tcl_pkgPath", pkgPath,
927 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
929 #endif /* HAVE_COREFOUNDATION */
931 Tcl_SetVar(interp, "tclDefaultLibrary", defaultLibraryDir,
933 Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
937 Tcl_SetVar2(interp, "tcl_platform", "platform", "dos", TCL_GLOBAL_ONLY);
939 Tcl_SetVar2(interp, "tcl_platform", "platform", "symbian", TCL_GLOBAL_ONLY);
943 if (uname(&name) >= 0) {
948 native = Tcl_ExternalToUtfDString(NULL, name.sysname, -1, &ds);
949 Tcl_SetVar2(interp, "tcl_platform", "os", native, TCL_GLOBAL_ONLY);
950 Tcl_DStringFree(&ds);
953 * The following code is a special hack to handle differences in
954 * the way version information is returned by uname. On most
955 * systems the full version number is available in name.release.
956 * However, under AIX the major version number is in
957 * name.version and the minor version number is in name.release.
960 if ((strchr(name.release, '.') != NULL)
961 || !isdigit(UCHAR(name.version[0]))) { /* INTL: digit */
962 Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
965 Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.version,
967 Tcl_SetVar2(interp, "tcl_platform", "osVersion", ".",
968 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
969 Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
970 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
972 Tcl_SetVar2(interp, "tcl_platform", "machine", name.machine,
976 // Symbian P.I.P.S. is a "flavour of" unix in that it's an emulation layer.
977 Tcl_SetVar2(interp, "tcl_platform", "osSystemName", name.sysname, TCL_GLOBAL_ONLY);
981 Tcl_SetVar2(interp, "tcl_platform", "os", "", TCL_GLOBAL_ONLY);
982 Tcl_SetVar2(interp, "tcl_platform", "osVersion", "", TCL_GLOBAL_ONLY);
983 Tcl_SetVar2(interp, "tcl_platform", "machine", "", TCL_GLOBAL_ONLY);
987 * Copy USER or LOGNAME environment variable into tcl_platform(user)
990 Tcl_DStringInit(&ds);
991 user = TclGetEnv("USER", &ds);
993 user = TclGetEnv("LOGNAME", &ds);
998 Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
999 Tcl_DStringFree(&ds);
1004 *----------------------------------------------------------------------
1006 * TclpFindVariable --
1008 * Locate the entry in environ for a given name. On Unix this
1009 * routine is case sensetive, on Windows this matches mixed case.
1012 * The return value is the index in environ of an entry with the
1013 * name "name", or -1 if there is no such entry. The integer at
1014 * *lengthPtr is filled in with the length of name (if a matching
1015 * entry is found) or the length of the environ array (if no matching
1021 *----------------------------------------------------------------------
1025 TclpFindVariable(name, lengthPtr)
1026 CONST char *name; /* Name of desired environment variable
1028 int *lengthPtr; /* Used to return length of name (for
1029 * successful searches) or number of non-NULL
1030 * entries in environ (for unsuccessful
1034 register CONST char *env, *p1, *p2;
1035 Tcl_DString envString;
1037 Tcl_DStringInit(&envString);
1038 for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) {
1039 p1 = Tcl_ExternalToUtfDString(NULL, env, -1, &envString);
1042 for (; *p2 == *p1; p1++, p2++) {
1043 /* NULL loop body. */
1045 if ((*p1 == '=') && (*p2 == '\0')) {
1046 *lengthPtr = p2 - name;
1051 Tcl_DStringFree(&envString);
1057 Tcl_DStringFree(&envString);
1062 *----------------------------------------------------------------------
1066 * This procedure is typically invoked by Tcl_AppInit procedures
1067 * to find and source the "init.tcl" script, which should exist
1068 * somewhere on the Tcl library path.
1071 * Returns a standard Tcl completion code and sets the interp's
1072 * result if there is an error.
1075 * Depends on what's in the init.tcl script.
1077 *----------------------------------------------------------------------
1082 Tcl_Interp *interp; /* Interpreter to initialize. */
1086 if (tclPreInitScript != NULL) {
1087 if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
1092 pathPtr = TclGetLibraryPath();
1093 if (pathPtr == NULL) {
1094 pathPtr = Tcl_NewObj();
1096 Tcl_IncrRefCount(pathPtr);
1097 Tcl_SetVar2Ex(interp, "tcl_libPath", NULL, pathPtr, TCL_GLOBAL_ONLY);
1098 Tcl_DecrRefCount(pathPtr);
1099 return Tcl_Eval(interp, initScript);
1103 *----------------------------------------------------------------------
1105 * Tcl_SourceRCFile --
1107 * This procedure is typically invoked by Tcl_Main of Tk_Main
1108 * procedure to source an application specific rc file into the
1109 * interpreter at startup time.
1115 * Depends on what's in the rc script.
1117 *----------------------------------------------------------------------
1121 Tcl_SourceRCFile(interp)
1122 Tcl_Interp *interp; /* Interpreter to source rc file into. */
1125 CONST char *fileName;
1126 Tcl_Channel errChannel;
1128 fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
1130 if (fileName != NULL) {
1132 CONST char *fullName;
1134 Tcl_DStringInit(&temp);
1135 fullName = Tcl_TranslateFileName(interp, fileName, &temp);
1136 if (fullName == NULL) {
1138 * Couldn't translate the file name (e.g. it referred to a
1139 * bogus user or there was no HOME environment variable).
1145 * Test for the existence of the rc file before trying to read it.
1148 c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
1149 if (c != (Tcl_Channel) NULL) {
1151 if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
1152 errChannel = Tcl_GetStdChannel(TCL_STDERR);
1154 Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
1155 Tcl_WriteChars(errChannel, "\n", 1);
1160 Tcl_DStringFree(&temp);
1165 *----------------------------------------------------------------------
1167 * TclpCheckStackSpace --
1169 * Detect if we are about to blow the stack. Called before an
1170 * evaluation can happen when nesting depth is checked.
1173 * 1 if there is enough stack space to continue; 0 if not.
1178 *----------------------------------------------------------------------
1182 TclpCheckStackSpace()
1185 * This function is unimplemented on Unix platforms.
1192 *----------------------------------------------------------------------
1194 * MacOSXGetLibraryPath --
1196 * If we have a bundle structure for the Tcl installation,
1197 * then check there first to see if we can find the libraries
1201 * TCL_OK if we have found the tcl library; TCL_ERROR otherwise.
1204 * Same as for Tcl_MacOSXOpenVersionedBundleResources.
1206 *----------------------------------------------------------------------
1209 #ifdef HAVE_COREFOUNDATION
1211 MacOSXGetLibraryPath(Tcl_Interp *interp, int maxPathLen, char *tclLibPath)
1213 int foundInFramework = TCL_ERROR;
1214 #ifdef TCL_FRAMEWORK
1215 foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
1216 "com.tcltk.tcllibrary", TCL_FRAMEWORK_VERSION, 0, maxPathLen, tclLibPath);
1218 return foundInFramework;
1220 #endif /* HAVE_COREFOUNDATION */