tclUnixInit.c

Go to the documentation of this file.
00001 /*
00002  * tclUnixInit.c --
00003  *
00004  *      Contains the Unix-specific interpreter initialization functions.
00005  *
00006  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
00007  * Copyright (c) 1999 by Scriptics Corporation.
00008  * All rights reserved.
00009  *
00010  * RCS: @(#) $Id: tclUnixInit.c,v 1.82 2007/12/13 15:28:42 dgp Exp $
00011  */
00012 
00013 #include "tclInt.h"
00014 #include <stddef.h>
00015 #include <locale.h>
00016 #ifdef HAVE_LANGINFO
00017 #   include <langinfo.h>
00018 #   ifdef __APPLE__
00019 #       if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030
00020             /* Support for weakly importing nl_langinfo on Darwin. */
00021 #           define WEAK_IMPORT_NL_LANGINFO
00022             extern char *nl_langinfo(nl_item) WEAK_IMPORT_ATTRIBUTE;
00023 #       endif
00024 #    endif
00025 #endif
00026 #include <sys/resource.h>
00027 #if defined(__FreeBSD__) && defined(__GNUC__)
00028 #   include <floatingpoint.h>
00029 #endif
00030 #if defined(__bsdi__)
00031 #   include <sys/param.h>
00032 #   if _BSDI_VERSION > 199501
00033 #       include <dlfcn.h>
00034 #   endif
00035 #endif
00036 #ifdef HAVE_COREFOUNDATION
00037 #include <CoreFoundation/CoreFoundation.h>
00038 #endif
00039 
00040 /*
00041  * Define TCL_NO_STACK_CHECK in the compiler options if you want to revert to
00042  * the old behavior of never checking the stack.
00043  */
00044 
00045 /*
00046  * Define this if you want to see a lot of output regarding stack checking.
00047  */
00048 
00049 #undef TCL_DEBUG_STACK_CHECK
00050 
00051 /*
00052  * Values used to compute how much space is really available for Tcl's use for
00053  * the stack.
00054  *
00055  * The getrlimit() function is documented to return the maximum stack size in
00056  * bytes. However, with threads enabled, the pthread library on some platforms
00057  * does bad things to the stack size limits. First, the limits cannot be
00058  * changed. Second, they appear to be sometimes reported incorrectly.
00059  *
00060  * The defines below may need to be adjusted if more platforms have this
00061  * broken behavior with threads enabled.
00062  */
00063 
00064 #ifndef TCL_MAGIC_STACK_DIVISOR
00065 #define TCL_MAGIC_STACK_DIVISOR         1
00066 #endif
00067 #ifndef TCL_RESERVED_STACK_PAGES
00068 #define TCL_RESERVED_STACK_PAGES        8
00069 #endif
00070 
00071 /*
00072  * Thread specific data for stack checking.
00073  */
00074 
00075 #ifndef TCL_NO_STACK_CHECK
00076 typedef struct ThreadSpecificData {
00077     int *outerVarPtr;           /* The "outermost" stack frame pointer for
00078                                  * this thread. */
00079     int *stackBound;            /* The current stack boundary */
00080 } ThreadSpecificData;
00081 static Tcl_ThreadDataKey dataKey;
00082 #ifdef TCL_CROSS_COMPILE
00083 static int stackGrowsDown = -1;
00084 static int StackGrowsDown(int *parent);
00085 #elif defined(TCL_STACK_GROWS_UP)
00086 #define stackGrowsDown 0
00087 #else
00088 #define stackGrowsDown 1
00089 #endif
00090 #endif /* TCL_NO_STACK_CHECK */
00091 
00092 #ifdef TCL_DEBUG_STACK_CHECK
00093 #define STACK_DEBUG(args) printf args
00094 #else
00095 #define STACK_DEBUG(args) (void)0
00096 #endif /* TCL_DEBUG_STACK_CHECK */
00097 
00098 /*
00099  * Tcl tries to use standard and homebrew methods to guess the right encoding
00100  * on the platform. However, there is always a final fallback, and this value
00101  * is it. Make sure it is a real Tcl encoding.
00102  */
00103 
00104 #ifndef TCL_DEFAULT_ENCODING
00105 #define TCL_DEFAULT_ENCODING "iso8859-1"
00106 #endif
00107 
00108 /*
00109  * Default directory in which to look for Tcl library scripts. The symbol is
00110  * defined by Makefile.
00111  */
00112 
00113 static char defaultLibraryDir[sizeof(TCL_LIBRARY)+200] = TCL_LIBRARY;
00114 
00115 /*
00116  * Directory in which to look for packages (each package is typically
00117  * installed as a subdirectory of this directory). The symbol is defined by
00118  * Makefile.
00119  */
00120 
00121 static char pkgPath[sizeof(TCL_PACKAGE_PATH)+200] = TCL_PACKAGE_PATH;
00122 
00123 /*
00124  * The following table is used to map from Unix locale strings to encoding
00125  * files. If HAVE_LANGINFO is defined, then this is a fallback table when the
00126  * result from nl_langinfo isn't a recognized encoding. Otherwise this is the
00127  * first list checked for a mapping from env encoding to Tcl encoding name.
00128  */
00129 
00130 typedef struct LocaleTable {
00131     CONST char *lang;
00132     CONST char *encoding;
00133 } LocaleTable;
00134 
00135 /*
00136  * The table below is sorted for the sake of doing binary searches on it. The
00137  * indenting reflects different categories of data. The leftmost data
00138  * represent the encoding names directly implemented by data files in Tcl's
00139  * default encoding directory. Indented by one TAB are the encoding names that
00140  * are common alternative spellings. Indented by two TABs are the accumulated
00141  * "bug fixes" that have been added to deal with the wide variability seen
00142  * among existing platforms.
00143  */
00144 
00145 static CONST LocaleTable localeTable[] = {
00146             {"",                "iso8859-1"},
00147                     {"ansi-1251",       "cp1251"},
00148             {"ansi_x3.4-1968",  "iso8859-1"},
00149     {"ascii",           "ascii"},
00150     {"big5",            "big5"},
00151     {"cp1250",          "cp1250"},
00152     {"cp1251",          "cp1251"},
00153     {"cp1252",          "cp1252"},
00154     {"cp1253",          "cp1253"},
00155     {"cp1254",          "cp1254"},
00156     {"cp1255",          "cp1255"},
00157     {"cp1256",          "cp1256"},
00158     {"cp1257",          "cp1257"},
00159     {"cp1258",          "cp1258"},
00160     {"cp437",           "cp437"},
00161     {"cp737",           "cp737"},
00162     {"cp775",           "cp775"},
00163     {"cp850",           "cp850"},
00164     {"cp852",           "cp852"},
00165     {"cp855",           "cp855"},
00166     {"cp857",           "cp857"},
00167     {"cp860",           "cp860"},
00168     {"cp861",           "cp861"},
00169     {"cp862",           "cp862"},
00170     {"cp863",           "cp863"},
00171     {"cp864",           "cp864"},
00172     {"cp865",           "cp865"},
00173     {"cp866",           "cp866"},
00174     {"cp869",           "cp869"},
00175     {"cp874",           "cp874"},
00176     {"cp932",           "cp932"},
00177     {"cp936",           "cp936"},
00178     {"cp949",           "cp949"},
00179     {"cp950",           "cp950"},
00180     {"dingbats",        "dingbats"},
00181     {"ebcdic",          "ebcdic"},
00182     {"euc-cn",          "euc-cn"},
00183     {"euc-jp",          "euc-jp"},
00184     {"euc-kr",          "euc-kr"},
00185                     {"eucjp",           "euc-jp"},
00186                     {"euckr",           "euc-kr"},
00187                     {"euctw",           "euc-cn"},
00188     {"gb12345",         "gb12345"},
00189     {"gb1988",          "gb1988"},
00190     {"gb2312",          "gb2312"},
00191                     {"gb2312-1980",     "gb2312"},
00192     {"gb2312-raw",      "gb2312-raw"},
00193                     {"greek8",          "cp869"},
00194             {"ibm1250",         "cp1250"},
00195             {"ibm1251",         "cp1251"},
00196             {"ibm1252",         "cp1252"},
00197             {"ibm1253",         "cp1253"},
00198             {"ibm1254",         "cp1254"},
00199             {"ibm1255",         "cp1255"},
00200             {"ibm1256",         "cp1256"},
00201             {"ibm1257",         "cp1257"},
00202             {"ibm1258",         "cp1258"},
00203             {"ibm437",          "cp437"},
00204             {"ibm737",          "cp737"},
00205             {"ibm775",          "cp775"},
00206             {"ibm850",          "cp850"},
00207             {"ibm852",          "cp852"},
00208             {"ibm855",          "cp855"},
00209             {"ibm857",          "cp857"},
00210             {"ibm860",          "cp860"},
00211             {"ibm861",          "cp861"},
00212             {"ibm862",          "cp862"},
00213             {"ibm863",          "cp863"},
00214             {"ibm864",          "cp864"},
00215             {"ibm865",          "cp865"},
00216             {"ibm866",          "cp866"},
00217             {"ibm869",          "cp869"},
00218             {"ibm874",          "cp874"},
00219             {"ibm932",          "cp932"},
00220             {"ibm936",          "cp936"},
00221             {"ibm949",          "cp949"},
00222             {"ibm950",          "cp950"},
00223             {"iso-2022",        "iso2022"},
00224             {"iso-2022-jp",     "iso2022-jp"},
00225             {"iso-2022-kr",     "iso2022-kr"},
00226             {"iso-8859-1",      "iso8859-1"},
00227             {"iso-8859-10",     "iso8859-10"},
00228             {"iso-8859-13",     "iso8859-13"},
00229             {"iso-8859-14",     "iso8859-14"},
00230             {"iso-8859-15",     "iso8859-15"},
00231             {"iso-8859-16",     "iso8859-16"},
00232             {"iso-8859-2",      "iso8859-2"},
00233             {"iso-8859-3",      "iso8859-3"},
00234             {"iso-8859-4",      "iso8859-4"},
00235             {"iso-8859-5",      "iso8859-5"},
00236             {"iso-8859-6",      "iso8859-6"},
00237             {"iso-8859-7",      "iso8859-7"},
00238             {"iso-8859-8",      "iso8859-8"},
00239             {"iso-8859-9",      "iso8859-9"},
00240     {"iso2022",         "iso2022"},
00241     {"iso2022-jp",      "iso2022-jp"},
00242     {"iso2022-kr",      "iso2022-kr"},
00243     {"iso8859-1",       "iso8859-1"},
00244     {"iso8859-10",      "iso8859-10"},
00245     {"iso8859-13",      "iso8859-13"},
00246     {"iso8859-14",      "iso8859-14"},
00247     {"iso8859-15",      "iso8859-15"},
00248     {"iso8859-16",      "iso8859-16"},
00249     {"iso8859-2",       "iso8859-2"},
00250     {"iso8859-3",       "iso8859-3"},
00251     {"iso8859-4",       "iso8859-4"},
00252     {"iso8859-5",       "iso8859-5"},
00253     {"iso8859-6",       "iso8859-6"},
00254     {"iso8859-7",       "iso8859-7"},
00255     {"iso8859-8",       "iso8859-8"},
00256     {"iso8859-9",       "iso8859-9"},
00257                     {"iso88591",        "iso8859-1"},
00258                     {"iso885915",       "iso8859-15"},
00259                     {"iso88592",        "iso8859-2"},
00260                     {"iso88595",        "iso8859-5"},
00261                     {"iso88596",        "iso8859-6"},
00262                     {"iso88597",        "iso8859-7"},
00263                     {"iso88598",        "iso8859-8"},
00264                     {"iso88599",        "iso8859-9"},
00265 #ifdef hpux
00266                     {"ja",              "shiftjis"},
00267 #else
00268                     {"ja",              "euc-jp"},
00269 #endif
00270                     {"ja_jp",           "euc-jp"},
00271                     {"ja_jp.euc",       "euc-jp"},
00272                     {"ja_jp.eucjp",     "euc-jp"},
00273                     {"ja_jp.jis",       "iso2022-jp"},
00274                     {"ja_jp.mscode",    "shiftjis"},
00275                     {"ja_jp.sjis",      "shiftjis"},
00276                     {"ja_jp.ujis",      "euc-jp"},
00277                     {"japan",           "euc-jp"},
00278 #ifdef hpux
00279                     {"japanese",        "shiftjis"},
00280 #else
00281                     {"japanese",        "euc-jp"},
00282 #endif
00283                     {"japanese-sjis",   "shiftjis"},
00284                     {"japanese-ujis",   "euc-jp"},
00285                     {"japanese.euc",    "euc-jp"},
00286                     {"japanese.sjis",   "shiftjis"},
00287     {"jis0201",         "jis0201"},
00288     {"jis0208",         "jis0208"},
00289     {"jis0212",         "jis0212"},
00290                     {"jp_jp",           "shiftjis"},
00291                     {"ko",              "euc-kr"},
00292                     {"ko_kr",           "euc-kr"},
00293                     {"ko_kr.euc",       "euc-kr"},
00294                     {"ko_kw.euckw",     "euc-kr"},
00295     {"koi8-r",          "koi8-r"},
00296     {"koi8-u",          "koi8-u"},
00297                     {"korean",          "euc-kr"},
00298     {"ksc5601",         "ksc5601"},
00299     {"maccenteuro",     "macCentEuro"},
00300     {"maccroatian",     "macCroatian"},
00301     {"maccyrillic",     "macCyrillic"},
00302     {"macdingbats",     "macDingbats"},
00303     {"macgreek",        "macGreek"},
00304     {"maciceland",      "macIceland"},
00305     {"macjapan",        "macJapan"},
00306     {"macroman",        "macRoman"},
00307     {"macromania",      "macRomania"},
00308     {"macthai",         "macThai"},
00309     {"macturkish",      "macTurkish"},
00310     {"macukraine",      "macUkraine"},
00311                     {"roman8",          "iso8859-1"},
00312                     {"ru",              "iso8859-5"},
00313                     {"ru_ru",           "iso8859-5"},
00314                     {"ru_su",           "iso8859-5"},
00315     {"shiftjis",        "shiftjis"},
00316                     {"sjis",            "shiftjis"},
00317     {"symbol",          "symbol"},
00318     {"tis-620",         "tis-620"},
00319                     {"tis620",          "tis-620"},
00320                     {"turkish8",        "cp857"},
00321                     {"utf8",            "utf-8"},
00322                     {"zh",              "cp936"},
00323                     {"zh_cn.gb2312",    "euc-cn"},
00324                     {"zh_cn.gbk",       "euc-cn"},
00325                     {"zh_cz.gb2312",    "euc-cn"},
00326                     {"zh_tw",           "euc-tw"},
00327                     {"zh_tw.big5",      "big5"},
00328 };
00329 
00330 #ifndef TCL_NO_STACK_CHECK
00331 static int              GetStackSize(size_t *stackSizePtr);
00332 #endif /* TCL_NO_STACK_CHECK */
00333 #ifdef HAVE_COREFOUNDATION
00334 static int              MacOSXGetLibraryPath(Tcl_Interp *interp,
00335                             int maxPathLen, char *tclLibPath);
00336 #endif /* HAVE_COREFOUNDATION */
00337 #if defined(__APPLE__) && (defined(TCL_LOAD_FROM_MEMORY) || ( \
00338         defined(TCL_THREADS) && defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
00339         MAC_OS_X_VERSION_MIN_REQUIRED < 1030) || ( \
00340         defined(__LP64__) && defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
00341         MAC_OS_X_VERSION_MIN_REQUIRED < 1050))
00342 /*
00343  * Need to check Darwin release at runtime in tclUnixFCmd.c and tclLoadDyld.c:
00344  * initialize release global at startup from uname().
00345  */
00346 #define GET_DARWIN_RELEASE 1
00347 MODULE_SCOPE long tclMacOSXDarwinRelease;
00348 long tclMacOSXDarwinRelease = 0;
00349 #endif
00350 
00351 
00352 /*
00353  *---------------------------------------------------------------------------
00354  *
00355  * TclpInitPlatform --
00356  *
00357  *      Initialize all the platform-dependant things like signals and
00358  *      floating-point error handling.
00359  *
00360  *      Called at process initialization time.
00361  *
00362  * Results:
00363  *      None.
00364  *
00365  * Side effects:
00366  *      None.
00367  *
00368  *---------------------------------------------------------------------------
00369  */
00370 
00371 void
00372 TclpInitPlatform(void)
00373 {
00374 #ifdef DJGPP
00375     tclPlatform = TCL_PLATFORM_WINDOWS;
00376 #else
00377     tclPlatform = TCL_PLATFORM_UNIX;
00378 #endif
00379 
00380     /*
00381      * Make sure, that the standard FDs exist. [Bug 772288]
00382      */
00383 
00384     if (TclOSseek(0, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
00385         open("/dev/null", O_RDONLY);
00386     }
00387     if (TclOSseek(1, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
00388         open("/dev/null", O_WRONLY);
00389     }
00390     if (TclOSseek(2, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
00391         open("/dev/null", O_WRONLY);
00392     }
00393 
00394     /*
00395      * The code below causes SIGPIPE (broken pipe) errors to be ignored. This
00396      * is needed so that Tcl processes don't die if they create child
00397      * processes (e.g. using "exec" or "open") that terminate prematurely.
00398      * The signal handler is only set up when the first interpreter is
00399      * created; after this the application can override the handler with a
00400      * different one of its own, if it wants.
00401      */
00402 
00403 #ifdef SIGPIPE
00404     (void) signal(SIGPIPE, SIG_IGN);
00405 #endif /* SIGPIPE */
00406 
00407 #if defined(__FreeBSD__) && defined(__GNUC__)
00408     /*
00409      * Adjust the rounding mode to be more conventional. Note that FreeBSD
00410      * only provides the __fpsetreg() used by the following two for the GNU
00411      * Compiler. When using, say, Intel's icc they break. (Partially based on
00412      * patch in BSD ports system from root@celsius.bychok.com)
00413      */
00414 
00415     fpsetround(FP_RN);
00416     (void) fpsetmask(0L);
00417 #endif
00418 
00419 #if defined(__bsdi__) && (_BSDI_VERSION > 199501)
00420     /*
00421      * Find local symbols. Don't report an error if we fail.
00422      */
00423 
00424     (void) dlopen(NULL, RTLD_NOW);                      /* INTL: Native. */
00425 #endif
00426 
00427     /*
00428      * Initialize the C library's locale subsystem. This is required for input
00429      * methods to work properly on X11. We only do this for LC_CTYPE because
00430      * that's the necessary one, and we don't want to affect LC_TIME here.
00431      * The side effect of setting the default locale should be to load any
00432      * locale specific modules that are needed by X. [BUG: 5422 3345 4236 2522
00433      * 2521].
00434      */
00435 
00436     setlocale(LC_CTYPE, "");
00437 
00438     /*
00439      * In case the initial locale is not "C", ensure that the numeric
00440      * processing is done in "C" locale regardless. This is needed because Tcl
00441      * relies on routines like strtod, but should not have locale dependent
00442      * behavior.
00443      */
00444 
00445     setlocale(LC_NUMERIC, "C");
00446 
00447 #ifdef GET_DARWIN_RELEASE
00448     {
00449         struct utsname name;
00450 
00451         if (!uname(&name)) {
00452             tclMacOSXDarwinRelease = strtol(name.release, NULL, 10);
00453         }
00454     }
00455 #endif
00456 }
00457 
00458 /*
00459  *---------------------------------------------------------------------------
00460  *
00461  * TclpInitLibraryPath --
00462  *
00463  *      This is the fallback routine that sets the library path if the
00464  *      application has not set one by the first time it is needed.
00465  *
00466  * Results:
00467  *      None.
00468  *
00469  * Side effects:
00470  *      Sets the library path to an initial value.
00471  *
00472  *-------------------------------------------------------------------------
00473  */
00474 
00475 void
00476 TclpInitLibraryPath(
00477     char **valuePtr,
00478     int *lengthPtr,
00479     Tcl_Encoding *encodingPtr)
00480 {
00481 #define LIBRARY_SIZE        32
00482     Tcl_Obj *pathPtr, *objPtr;
00483     CONST char *str;
00484     Tcl_DString buffer;
00485 
00486     pathPtr = Tcl_NewObj();
00487 
00488     /*
00489      * Look for the library relative to the TCL_LIBRARY env variable. If the
00490      * last dirname in the TCL_LIBRARY path does not match the last dirname in
00491      * the installLib variable, use the last dir name of installLib in
00492      * addition to the orginal TCL_LIBRARY path.
00493      */
00494 
00495     str = getenv("TCL_LIBRARY");                        /* INTL: Native. */
00496     Tcl_ExternalToUtfDString(NULL, str, -1, &buffer);
00497     str = Tcl_DStringValue(&buffer);
00498 
00499     if ((str != NULL) && (str[0] != '\0')) {
00500         Tcl_DString ds;
00501         int pathc;
00502         CONST char **pathv;
00503         char installLib[LIBRARY_SIZE];
00504 
00505         Tcl_DStringInit(&ds);
00506 
00507         /*
00508          * Initialize the substrings used when locating an executable. The
00509          * installLib variable computes the path as though the executable is
00510          * installed.
00511          */
00512 
00513         sprintf(installLib, "lib/tcl%s", TCL_VERSION);
00514 
00515         /*
00516          * If TCL_LIBRARY is set, search there.
00517          */
00518 
00519         objPtr = Tcl_NewStringObj(str, -1);
00520         Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
00521 
00522         Tcl_SplitPath(str, &pathc, &pathv);
00523         if ((pathc > 0) && (strcasecmp(installLib + 4, pathv[pathc-1]) != 0)) {
00524             /*
00525              * If TCL_LIBRARY is set but refers to a different tcl
00526              * installation than the current version, try fiddling with the
00527              * specified directory to make it refer to this installation by
00528              * removing the old "tclX.Y" and substituting the current version
00529              * string.
00530              */
00531 
00532             pathv[pathc - 1] = installLib + 4;
00533             str = Tcl_JoinPath(pathc, pathv, &ds);
00534             objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&ds));
00535             Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
00536             Tcl_DStringFree(&ds);
00537         }
00538         ckfree((char *) pathv);
00539     }
00540 
00541     /*
00542      * Finally, look for the library relative to the compiled-in path. This is
00543      * needed when users install Tcl with an exec-prefix that is different
00544      * from the prefix.
00545      */
00546 
00547     {
00548 #ifdef HAVE_COREFOUNDATION
00549         char tclLibPath[MAXPATHLEN + 1];
00550 
00551         if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
00552             str = tclLibPath;
00553         } else
00554 #endif /* HAVE_COREFOUNDATION */
00555         {
00556             /*
00557              * TODO: Pull this value from the TIP 59 table.
00558              */
00559 
00560             str = defaultLibraryDir;
00561         }
00562         if (str[0] != '\0') {
00563             objPtr = Tcl_NewStringObj(str, -1);
00564             Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
00565         }
00566     }
00567     Tcl_DStringFree(&buffer);
00568 
00569     *encodingPtr = Tcl_GetEncoding(NULL, NULL);
00570     str = Tcl_GetStringFromObj(pathPtr, lengthPtr);
00571     *valuePtr = ckalloc((unsigned int) (*lengthPtr)+1);
00572     memcpy(*valuePtr, str, (size_t)(*lengthPtr)+1);
00573     Tcl_DecrRefCount(pathPtr);
00574 }
00575 
00576 /*
00577  *---------------------------------------------------------------------------
00578  *
00579  * TclpSetInitialEncodings --
00580  *
00581  *      Based on the locale, determine the encoding of the operating system
00582  *      and the default encoding for newly opened files.
00583  *
00584  *      Called at process initialization time, and part way through startup,
00585  *      we verify that the initial encodings were correctly setup. Depending
00586  *      on Tcl's environment, there may not have been enough information first
00587  *      time through (above).
00588  *
00589  * Results:
00590  *      None.
00591  *
00592  * Side effects:
00593  *      The Tcl library path is converted from native encoding to UTF-8, on
00594  *      the first call, and the encodings may be changed on first or second
00595  *      call.
00596  *
00597  *---------------------------------------------------------------------------
00598  */
00599 
00600 void
00601 TclpSetInitialEncodings(void)
00602 {
00603     Tcl_DString encodingName;
00604     Tcl_SetSystemEncoding(NULL,
00605             Tcl_GetEncodingNameFromEnvironment(&encodingName));
00606     Tcl_DStringFree(&encodingName);
00607 }
00608 
00609 void
00610 TclpSetInterfaces(void)
00611 {
00612     /* do nothing */
00613 }
00614 
00615 static CONST char *
00616 SearchKnownEncodings(
00617     CONST char *encoding)
00618 {
00619     int left = 0;
00620     int right = sizeof(localeTable)/sizeof(LocaleTable);
00621 
00622     while (left <= right) {
00623         int test = (left + right)/2;
00624         int code = strcmp(localeTable[test].lang, encoding);
00625 
00626         if (code == 0) {
00627             return localeTable[test].encoding;
00628         }
00629         if (code < 0) {
00630             left = test+1;
00631         } else {
00632             right = test-1;
00633         }
00634     }
00635     return NULL;
00636 }
00637 
00638 CONST char *
00639 Tcl_GetEncodingNameFromEnvironment(
00640     Tcl_DString *bufPtr)
00641 {
00642     CONST char *encoding;
00643     CONST char *knownEncoding;
00644 
00645     Tcl_DStringInit(bufPtr);
00646 
00647     /*
00648      * Determine the current encoding from the LC_* or LANG environment
00649      * variables. We previously used setlocale() to determine the locale, but
00650      * this does not work on some systems (e.g. Linux/i386 RH 5.0).
00651      */
00652 
00653 #ifdef HAVE_LANGINFO
00654     if (
00655 #ifdef WEAK_IMPORT_NL_LANGINFO
00656             nl_langinfo != NULL &&
00657 #endif
00658             setlocale(LC_CTYPE, "") != NULL) {
00659         Tcl_DString ds;
00660 
00661         /*
00662          * Use a DString so we can modify case.
00663          */
00664 
00665         Tcl_DStringInit(&ds);
00666         encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
00667         Tcl_UtfToLower(Tcl_DStringValue(&ds));
00668         knownEncoding = SearchKnownEncodings(encoding);
00669         if (knownEncoding != NULL) {
00670             Tcl_DStringAppend(bufPtr, knownEncoding, -1);
00671         } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
00672             Tcl_DStringAppend(bufPtr, encoding, -1);
00673         }
00674         Tcl_DStringFree(&ds);
00675         if (Tcl_DStringLength(bufPtr)) {
00676             return Tcl_DStringValue(bufPtr);
00677         }
00678     }
00679 #endif /* HAVE_LANGINFO */
00680 
00681     /*
00682      * Classic fallback check. This tries a homebrew algorithm to determine
00683      * what encoding should be used based on env vars.
00684      */
00685 
00686     encoding = getenv("LC_ALL");
00687 
00688     if (encoding == NULL || encoding[0] == '\0') {
00689         encoding = getenv("LC_CTYPE");
00690     }
00691     if (encoding == NULL || encoding[0] == '\0') {
00692         encoding = getenv("LANG");
00693     }
00694     if (encoding == NULL || encoding[0] == '\0') {
00695         encoding = NULL;
00696     }
00697 
00698     if (encoding != NULL) {
00699         CONST char *p;
00700         Tcl_DString ds;
00701 
00702         Tcl_DStringInit(&ds);
00703         p = encoding;
00704         encoding = Tcl_DStringAppend(&ds, p, -1);
00705         Tcl_UtfToLower(Tcl_DStringValue(&ds));
00706 
00707         knownEncoding = SearchKnownEncodings(encoding);
00708         if (knownEncoding != NULL) {
00709             Tcl_DStringAppend(bufPtr, knownEncoding, -1);
00710         } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
00711             Tcl_DStringAppend(bufPtr, encoding, -1);
00712         }
00713         if (Tcl_DStringLength(bufPtr)) {
00714             Tcl_DStringFree(&ds);
00715             return Tcl_DStringValue(bufPtr);
00716         }
00717 
00718         /*
00719          * We didn't recognize the full value as an encoding name. If there is
00720          * an encoding subfield, we can try to guess from that.
00721          */
00722 
00723         for (p = encoding; *p != '\0'; p++) {
00724             if (*p == '.') {
00725                 p++;
00726                 break;
00727             }
00728         }
00729         if (*p != '\0') {
00730             knownEncoding = SearchKnownEncodings(p);
00731             if (knownEncoding != NULL) {
00732                 Tcl_DStringAppend(bufPtr, knownEncoding, -1);
00733             } else if (NULL != Tcl_GetEncoding(NULL, p)) {
00734                 Tcl_DStringAppend(bufPtr, p, -1);
00735             }
00736         }
00737         Tcl_DStringFree(&ds);
00738         if (Tcl_DStringLength(bufPtr)) {
00739             return Tcl_DStringValue(bufPtr);
00740         }
00741     }
00742     return Tcl_DStringAppend(bufPtr, TCL_DEFAULT_ENCODING, -1);
00743 }
00744 
00745 /*
00746  *---------------------------------------------------------------------------
00747  *
00748  * TclpSetVariables --
00749  *
00750  *      Performs platform-specific interpreter initialization related to the
00751  *      tcl_library and tcl_platform variables, and other platform-specific
00752  *      things.
00753  *
00754  * Results:
00755  *      None.
00756  *
00757  * Side effects:
00758  *      Sets "tclDefaultLibrary", "tcl_pkgPath", and "tcl_platform" Tcl
00759  *      variables.
00760  *
00761  *----------------------------------------------------------------------
00762  */
00763 
00764 void
00765 TclpSetVariables(
00766     Tcl_Interp *interp)
00767 {
00768 #ifndef NO_UNAME
00769     struct utsname name;
00770 #endif
00771     int unameOK;
00772     Tcl_DString ds;
00773 
00774 #ifdef HAVE_COREFOUNDATION
00775     char tclLibPath[MAXPATHLEN + 1];
00776 
00777 #if MAC_OS_X_VERSION_MAX_ALLOWED > 1020
00778     /*
00779      * Set msgcat fallback locale to current CFLocale identifier.
00780      */
00781 
00782     CFLocaleRef localeRef;
00783     
00784     if (CFLocaleCopyCurrent != NULL && CFLocaleGetIdentifier != NULL &&
00785             (localeRef = CFLocaleCopyCurrent())) {
00786         CFStringRef locale = CFLocaleGetIdentifier(localeRef);
00787 
00788         if (locale) {
00789             char loc[256];
00790 
00791             if (CFStringGetCString(locale, loc, 256, kCFStringEncodingUTF8)) {
00792                 if (!Tcl_CreateNamespace(interp, "::tcl::mac", NULL, NULL)) {
00793                     Tcl_ResetResult(interp);
00794                 }
00795                 Tcl_SetVar(interp, "::tcl::mac::locale", loc, TCL_GLOBAL_ONLY);
00796             }
00797         }
00798         CFRelease(localeRef);
00799     }
00800 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED > 1020 */
00801 
00802     if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) {
00803         CONST char *str;
00804         CFBundleRef bundleRef;
00805 
00806         Tcl_SetVar(interp, "tclDefaultLibrary", tclLibPath, TCL_GLOBAL_ONLY);
00807         Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath, TCL_GLOBAL_ONLY);
00808         Tcl_SetVar(interp, "tcl_pkgPath", " ",
00809                 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
00810 
00811         str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
00812         if ((str != NULL) && (str[0] != '\0')) {
00813             char *p = Tcl_DStringValue(&ds);
00814 
00815             /*
00816              * Convert DYLD_FRAMEWORK_PATH from colon to space separated.
00817              */
00818 
00819             do {
00820                 if (*p == ':') {
00821                     *p = ' ';
00822                 }
00823             } while (*p++);
00824             Tcl_SetVar(interp, "tcl_pkgPath", Tcl_DStringValue(&ds),
00825                     TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
00826             Tcl_SetVar(interp, "tcl_pkgPath", " ",
00827                     TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
00828             Tcl_DStringFree(&ds);
00829         }
00830         bundleRef = CFBundleGetMainBundle();
00831         if (bundleRef) {
00832             CFURLRef frameworksURL;
00833             Tcl_StatBuf statBuf;
00834 
00835             frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef);
00836             if (frameworksURL) {
00837                 if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
00838                         (unsigned char*) tclLibPath, MAXPATHLEN) &&
00839                         ! TclOSstat(tclLibPath, &statBuf) &&
00840                         S_ISDIR(statBuf.st_mode)) {
00841                     Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
00842                             TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
00843                     Tcl_SetVar(interp, "tcl_pkgPath", " ",
00844                             TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
00845                 }
00846                 CFRelease(frameworksURL);
00847             }
00848             frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef);
00849             if (frameworksURL) {
00850                 if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
00851                         (unsigned char*) tclLibPath, MAXPATHLEN) &&
00852                         ! TclOSstat(tclLibPath, &statBuf) &&
00853                         S_ISDIR(statBuf.st_mode)) {
00854                     Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
00855                             TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
00856                     Tcl_SetVar(interp, "tcl_pkgPath", " ",
00857                             TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
00858                 }
00859                 CFRelease(frameworksURL);
00860             }
00861         }
00862         Tcl_SetVar(interp, "tcl_pkgPath", pkgPath,
00863                 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
00864     } else
00865 #endif /* HAVE_COREFOUNDATION */
00866     {
00867         Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
00868     }
00869 
00870 #ifdef DJGPP
00871     Tcl_SetVar2(interp, "tcl_platform", "platform", "dos", TCL_GLOBAL_ONLY);
00872 #else
00873     Tcl_SetVar2(interp, "tcl_platform", "platform", "unix", TCL_GLOBAL_ONLY);
00874 #endif
00875 
00876     unameOK = 0;
00877 #ifndef NO_UNAME
00878     if (uname(&name) >= 0) {
00879         CONST char *native;
00880 
00881         unameOK = 1;
00882 
00883         native = Tcl_ExternalToUtfDString(NULL, name.sysname, -1, &ds);
00884         Tcl_SetVar2(interp, "tcl_platform", "os", native, TCL_GLOBAL_ONLY);
00885         Tcl_DStringFree(&ds);
00886 
00887         /*
00888          * The following code is a special hack to handle differences in the
00889          * way version information is returned by uname. On most systems the
00890          * full version number is available in name.release. However, under
00891          * AIX the major version number is in name.version and the minor
00892          * version number is in name.release.
00893          */
00894 
00895         if ((strchr(name.release, '.') != NULL)
00896                 || !isdigit(UCHAR(name.version[0]))) {  /* INTL: digit */
00897             Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
00898                     TCL_GLOBAL_ONLY);
00899         } else {
00900 #ifdef DJGPP
00901             /*
00902              * For some obscure reason DJGPP puts major version into
00903              * name.release and minor into name.version. As of DJGPP 2.04 this
00904              * is documented in djgpp libc.info file.
00905              */
00906 
00907             Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
00908                     TCL_GLOBAL_ONLY);
00909             Tcl_SetVar2(interp, "tcl_platform", "osVersion", ".",
00910                     TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
00911             Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.version,
00912                     TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
00913 #else
00914             Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.version,
00915                     TCL_GLOBAL_ONLY);
00916             Tcl_SetVar2(interp, "tcl_platform", "osVersion", ".",
00917                     TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
00918             Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
00919                     TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
00920 
00921 #endif /* DJGPP */
00922         }
00923         Tcl_SetVar2(interp, "tcl_platform", "machine", name.machine,
00924                 TCL_GLOBAL_ONLY);
00925     }
00926 #endif /* !NO_UNAME */
00927     if (!unameOK) {
00928         Tcl_SetVar2(interp, "tcl_platform", "os", "", TCL_GLOBAL_ONLY);
00929         Tcl_SetVar2(interp, "tcl_platform", "osVersion", "", TCL_GLOBAL_ONLY);
00930         Tcl_SetVar2(interp, "tcl_platform", "machine", "", TCL_GLOBAL_ONLY);
00931     }
00932 
00933     /*
00934      * Copy the username of the real user (according to getuid()) into
00935      * tcl_platform(user).
00936      */
00937 
00938     {
00939         struct passwd *pwEnt = TclpGetPwUid(getuid());
00940         const char *user;
00941 
00942         if (pwEnt == NULL) {
00943             user = "";
00944             Tcl_DStringInit(&ds);       /* ensure cleanliness */
00945         } else {
00946             user = Tcl_ExternalToUtfDString(NULL, pwEnt->pw_name, -1, &ds);
00947         }
00948 
00949         Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
00950         Tcl_DStringFree(&ds);
00951     }
00952 }
00953 
00954 /*
00955  *----------------------------------------------------------------------
00956  *
00957  * TclpFindVariable --
00958  *
00959  *      Locate the entry in environ for a given name. On Unix this routine is
00960  *      case sensetive, on Windows this matches mixed case.
00961  *
00962  * Results:
00963  *      The return value is the index in environ of an entry with the name
00964  *      "name", or -1 if there is no such entry. The integer at *lengthPtr is
00965  *      filled in with the length of name (if a matching entry is found) or
00966  *      the length of the environ array (if no matching entry is found).
00967  *
00968  * Side effects:
00969  *      None.
00970  *
00971  *----------------------------------------------------------------------
00972  */
00973 
00974 int
00975 TclpFindVariable(
00976     CONST char *name,           /* Name of desired environment variable
00977                                  * (native). */
00978     int *lengthPtr)             /* Used to return length of name (for
00979                                  * successful searches) or number of non-NULL
00980                                  * entries in environ (for unsuccessful
00981                                  * searches). */
00982 {
00983     int i, result = -1;
00984     register CONST char *env, *p1, *p2;
00985     Tcl_DString envString;
00986 
00987     Tcl_DStringInit(&envString);
00988     for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) {
00989         p1 = Tcl_ExternalToUtfDString(NULL, env, -1, &envString);
00990         p2 = name;
00991 
00992         for (; *p2 == *p1; p1++, p2++) {
00993             /* NULL loop body. */
00994         }
00995         if ((*p1 == '=') && (*p2 == '\0')) {
00996             *lengthPtr = p2 - name;
00997             result = i;
00998             goto done;
00999         }
01000 
01001         Tcl_DStringFree(&envString);
01002     }
01003 
01004     *lengthPtr = i;
01005 
01006   done:
01007     Tcl_DStringFree(&envString);
01008     return result;
01009 }
01010 
01011 #ifndef TCL_NO_STACK_CHECK
01012 /*
01013  *----------------------------------------------------------------------
01014  *
01015  * TclpGetCStackParams --
01016  *
01017  *      Determine the stack params for the current thread: in which
01018  *      direction does the stack grow, and what is the stack lower (resp.
01019  *      upper) bound for safe invocation of a new command? This is used to
01020  *      cache the values needed for an efficient computation of
01021  *      TclpCheckStackSpace() when the interp is known.
01022  *
01023  * Results:
01024  *      Returns 1 if the stack grows down, in which case a stack lower bound
01025  *      is stored at stackBoundPtr. If the stack grows up, 0 is returned and
01026  *      an upper bound is stored at stackBoundPtr. If a bound cannot be
01027  *      determined NULL is stored at stackBoundPtr.
01028  *
01029  *----------------------------------------------------------------------
01030  */
01031 
01032 int
01033 TclpGetCStackParams(
01034     int **stackBoundPtr)
01035 {
01036     int result = TCL_OK;
01037     size_t stackSize = 0;       /* The size of the current stack. */
01038     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
01039                                 /* Most variables are actually in a
01040                                  * thread-specific data block to minimise the
01041                                  * impact on the stack. */
01042 #ifdef TCL_CROSS_COMPILE
01043     if (stackGrowsDown == -1) {
01044         /*
01045          * Not initialised!
01046          */
01047 
01048         stackGrowsDown = StackGrowsDown(&result);
01049     }
01050 #endif
01051     
01052     /*
01053      * The first time through in a thread: record the "outermost" stack
01054      * frame and inquire with the OS about the stack size.
01055      */
01056 
01057     if (tsdPtr->outerVarPtr == NULL) {
01058         tsdPtr->outerVarPtr = &result;
01059         result = GetStackSize(&stackSize);
01060         if (result != TCL_OK) {
01061             /* Can't check, assume it always succeeds */
01062 #ifdef TCL_CROSS_COMPILE
01063             stackGrowsDown = 1;
01064 #endif
01065             tsdPtr->stackBound = NULL;
01066             goto done;
01067         }
01068     }
01069 
01070     if (stackSize || (tsdPtr->stackBound &&
01071             ((stackGrowsDown && (&result < tsdPtr->stackBound)) ||
01072             (!stackGrowsDown && (&result > tsdPtr->stackBound))))) {
01073         /*
01074          * Either the thread's first pass or stack failure: set the params
01075          */
01076 
01077         if (!stackSize) {
01078             /*
01079              * Stack failure: if we didn't already blow up, we are within the
01080              * safety area. Recheck with the OS in case the stack was grown. 
01081              */
01082             result = GetStackSize(&stackSize);
01083             if (result != TCL_OK) {
01084                 /* Can't check, assume it always succeeds */
01085 #ifdef TCL_CROSS_COMPILE
01086                 stackGrowsDown = 1;
01087 #endif
01088                 tsdPtr->stackBound = NULL;
01089                 goto done;
01090             }
01091         }
01092 
01093         if (stackGrowsDown) {
01094             tsdPtr->stackBound = (int *) ((char *)tsdPtr->outerVarPtr -
01095                     stackSize);
01096         } else {
01097             tsdPtr->stackBound = (int *) ((char *)tsdPtr->outerVarPtr +
01098                     stackSize);
01099         }
01100     }
01101 
01102     done:
01103     *stackBoundPtr = tsdPtr->stackBound;
01104     return stackGrowsDown;
01105 }
01106 
01107 #ifdef TCL_CROSS_COMPILE
01108 int
01109 StackGrowsDown(
01110     int *parent)
01111 {
01112     int here;
01113     return (&here < parent);
01114 }
01115 #endif
01116 
01117 /*
01118  *----------------------------------------------------------------------
01119  *
01120  * GetStackSize --
01121  *
01122  *      Discover what the stack size for the current thread/process actually
01123  *      is. Expects to only ever be called once per thread and then only at a
01124  *      point when there is a reasonable amount of space left on the current
01125  *      stack; TclpCheckStackSpace is called sufficiently frequently that that
01126  *      is true.
01127  *
01128  * Results:
01129  *      TCL_OK if the stack space was discovered, TCL_BREAK if the stack space
01130  *      was undiscoverable in a way that stack checks should fail, and
01131  *      TCL_CONTINUE if the stack space was undiscoverable in a way that stack
01132  *      checks should succeed.
01133  *
01134  * Side effects:
01135  *      None
01136  *
01137  *----------------------------------------------------------------------
01138  */
01139 
01140 static int
01141 GetStackSize(
01142     size_t *stackSizePtr)
01143 {
01144     size_t rawStackSize;
01145     struct rlimit rLimit;       /* The result from getrlimit(). */
01146 
01147 #ifdef TCL_THREADS
01148     rawStackSize = TclpThreadGetStackSize();
01149     if (rawStackSize == (size_t) -1) {
01150         /*
01151          * Some kind of confirmed error in TclpThreadGetStackSize?! Fall back
01152          * to whatever getrlimit can determine.
01153          */
01154         STACK_DEBUG(("stack checks: TclpThreadGetStackSize failed in \n"));
01155     }
01156     if (rawStackSize > 0) {
01157         goto finalSanityCheck;
01158     }
01159 
01160     /*
01161      * If we have zero or an error, try the system limits instead. After all,
01162      * the pthread documentation states that threads should always be bound by
01163      * the system stack size limit in any case.
01164      */
01165 #endif /* TCL_THREADS */
01166 
01167     if (getrlimit(RLIMIT_STACK, &rLimit) != 0) {
01168         /*
01169          * getrlimit() failed, just fail the whole thing.
01170          */
01171         STACK_DEBUG(("skipping stack checks with failure: getrlimit failed\n"));
01172         return TCL_BREAK;
01173     }
01174     if (rLimit.rlim_cur == RLIM_INFINITY) {
01175         /*
01176          * Limit is "infinite"; there is no stack limit.
01177          */
01178         STACK_DEBUG(("skipping stack checks with success: infinite limit\n"));
01179         return TCL_CONTINUE;
01180     }
01181     rawStackSize = rLimit.rlim_cur;
01182 
01183     /*
01184      * Final sanity check on the determined stack size. If we fail this,
01185      * assume there are bogus values about and that we can't actually figure
01186      * out what the stack size really is.
01187      */
01188 
01189 #ifdef TCL_THREADS /* Stop warning... */
01190   finalSanityCheck:
01191 #endif
01192     if (rawStackSize <= 0) {
01193         STACK_DEBUG(("skipping stack checks with success\n"));
01194         return TCL_CONTINUE;
01195     }
01196 
01197     /*
01198      * Calculate a stack size with a safety margin.
01199      */
01200 
01201     *stackSizePtr = (rawStackSize / TCL_MAGIC_STACK_DIVISOR)
01202             - (getpagesize() * TCL_RESERVED_STACK_PAGES);
01203 
01204     return TCL_OK;
01205 }
01206 #endif /* TCL_NO_STACK_CHECK */
01207 
01208 /*
01209  *----------------------------------------------------------------------
01210  *
01211  * MacOSXGetLibraryPath --
01212  *
01213  *      If we have a bundle structure for the Tcl installation, then check
01214  *      there first to see if we can find the libraries there.
01215  *
01216  * Results:
01217  *      TCL_OK if we have found the tcl library; TCL_ERROR otherwise.
01218  *
01219  * Side effects:
01220  *      Same as for Tcl_MacOSXOpenVersionedBundleResources.
01221  *
01222  *----------------------------------------------------------------------
01223  */
01224 
01225 #ifdef HAVE_COREFOUNDATION
01226 static int
01227 MacOSXGetLibraryPath(
01228     Tcl_Interp *interp,
01229     int maxPathLen,
01230     char *tclLibPath)
01231 {
01232     int foundInFramework = TCL_ERROR;
01233 
01234 #ifdef TCL_FRAMEWORK
01235     foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
01236             "com.tcltk.tcllibrary", TCL_FRAMEWORK_VERSION, 0, maxPathLen,
01237             tclLibPath);
01238 #endif
01239 
01240     return foundInFramework;
01241 }
01242 #endif /* HAVE_COREFOUNDATION */
01243 
01244 /*
01245  * Local Variables:
01246  * mode: c
01247  * c-basic-offset: 4
01248  * fill-column: 78
01249  * End:
01250  */



Generated on Wed Mar 12 12:18:26 2008 by  doxygen 1.5.1