summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixInit.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixInit.c')
-rw-r--r--unix/tclUnixInit.c1470
1 files changed, 682 insertions, 788 deletions
diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c
index f9015b7..5de9e48 100644
--- a/unix/tclUnixInit.c
+++ b/unix/tclUnixInit.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclUnixInit.c --
*
* Contains the Unix-specific interpreter initialization functions.
@@ -8,8 +8,11 @@
* All rights reserved.
*/
+#if defined(HAVE_COREFOUNDATION)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
#include "tclInt.h"
-#include <stddef.h>
+#include "tclPort.h"
#include <locale.h>
#ifdef HAVE_LANGINFO
# include <langinfo.h>
@@ -21,7 +24,6 @@
# endif
# endif
#endif
-#include <sys/resource.h>
#if defined(__FreeBSD__) && defined(__GNUC__)
# include <floatingpoint.h>
#endif
@@ -76,72 +78,22 @@ typedef struct _OSVERSIONINFOA {
} OSVERSIONINFOA;
#endif
-#ifdef HAVE_COREFOUNDATION
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
-/*
- * Define TCL_NO_STACK_CHECK in the compiler options if you want to revert to
- * the old behavior of never checking the stack.
- */
-
-/*
- * Define this if you want to see a lot of output regarding stack checking.
- */
-
-#undef TCL_DEBUG_STACK_CHECK
-
-/*
- * Values used to compute how much space is really available for Tcl's use for
- * the stack.
- *
- * The getrlimit() function is documented to return the maximum stack size in
- * bytes. However, with threads enabled, the pthread library on some platforms
- * does bad things to the stack size limits. First, the limits cannot be
- * changed. Second, they appear to be sometimes reported incorrectly.
- *
- * The defines below may need to be adjusted if more platforms have this
- * broken behavior with threads enabled.
- */
-
-#ifndef TCL_MAGIC_STACK_DIVISOR
-#define TCL_MAGIC_STACK_DIVISOR 1
-#endif
-#ifndef TCL_RESERVED_STACK_PAGES
-#define TCL_RESERVED_STACK_PAGES 8
-#endif
/*
- * Thread specific data for stack checking.
+ * The Init script (common to Windows and Unix platforms) is
+ * defined in tkInitScript.h
*/
+#include "tclInitScript.h"
-#ifndef TCL_NO_STACK_CHECK
-typedef struct ThreadSpecificData {
- int *outerVarPtr; /* The "outermost" stack frame pointer for
- * this thread. */
- int *stackBound; /* The current stack boundary */
-} ThreadSpecificData;
-static Tcl_ThreadDataKey dataKey;
-#ifdef TCL_CROSS_COMPILE
-static int stackGrowsDown = -1;
-static int StackGrowsDown(int *parent);
-#elif defined(TCL_STACK_GROWS_UP)
-#define stackGrowsDown 0
-#else
-#define stackGrowsDown 1
-#endif
-#endif /* TCL_NO_STACK_CHECK */
-
-#ifdef TCL_DEBUG_STACK_CHECK
-#define STACK_DEBUG(args) printf args
-#else
-#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, and this value
- * is it. Make sure it is a real Tcl encoding.
+ * Tcl tries to use standard and homebrew methods to guess the right
+ * encoding on the platform. However, there is always a final fallback,
+ * and this value is it. Make sure it is a real Tcl encoding.
*/
#ifndef TCL_DEFAULT_ENCODING
@@ -149,25 +101,26 @@ static int StackGrowsDown(int *parent);
#endif
/*
- * Default directory in which to look for Tcl library scripts. The symbol is
- * defined by Makefile.
+ * Default directory in which to look for Tcl library scripts. The
+ * symbol is defined by Makefile.
*/
static char defaultLibraryDir[sizeof(TCL_LIBRARY)+200] = TCL_LIBRARY;
/*
* Directory in which to look for packages (each package is typically
- * installed as a subdirectory of this directory). The symbol is defined by
- * Makefile.
+ * installed as a subdirectory of this directory). The symbol is
+ * defined by Makefile.
*/
static char pkgPath[sizeof(TCL_PACKAGE_PATH)+200] = TCL_PACKAGE_PATH;
/*
- * The following table is used to map from Unix locale strings to encoding
- * files. If HAVE_LANGINFO is defined, then this is a fallback table when the
- * result from nl_langinfo isn't a recognized encoding. Otherwise this is the
- * first list checked for a mapping from env encoding to Tcl encoding name.
+ * The following table is used to map from Unix locale strings to
+ * encoding files. If HAVE_LANGINFO is defined, then this is a fallback
+ * table when the result from nl_langinfo isn't a recognized encoding.
+ * Otherwise this is the first list checked for a mapping from env
+ * encoding to Tcl encoding name.
*/
typedef struct LocaleTable {
@@ -175,207 +128,78 @@ typedef struct LocaleTable {
CONST char *encoding;
} LocaleTable;
-/*
- * The table below is sorted for the sake of doing binary searches on it. The
- * indenting reflects different categories of data. The leftmost data
- * represent the encoding names directly implemented by data files in Tcl's
- * default encoding directory. Indented by one TAB are the encoding names that
- * are common alternative spellings. Indented by two TABs are the accumulated
- * "bug fixes" that have been added to deal with the wide variability seen
- * among existing platforms.
- */
-
static CONST LocaleTable localeTable[] = {
- {"", "iso8859-1"},
- {"ansi-1251", "cp1251"},
- {"ansi_x3.4-1968", "iso8859-1"},
- {"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"},
- {"eucjp", "euc-jp"},
- {"euckr", "euc-kr"},
- {"euctw", "euc-cn"},
- {"gb12345", "gb12345"},
- {"gb1988", "gb1988"},
- {"gb2312", "gb2312"},
- {"gb2312-1980", "gb2312"},
- {"gb2312-raw", "gb2312-raw"},
- {"greek8", "cp869"},
- {"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"},
- {"iso-2022", "iso2022"},
- {"iso-2022-jp", "iso2022-jp"},
- {"iso-2022-kr", "iso2022-kr"},
- {"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"},
- {"iso2022", "iso2022"},
- {"iso2022-jp", "iso2022-jp"},
- {"iso2022-kr", "iso2022-kr"},
- {"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"},
- {"iso88591", "iso8859-1"},
- {"iso885915", "iso8859-15"},
- {"iso88592", "iso8859-2"},
- {"iso88595", "iso8859-5"},
- {"iso88596", "iso8859-6"},
- {"iso88597", "iso8859-7"},
- {"iso88598", "iso8859-8"},
- {"iso88599", "iso8859-9"},
-#ifdef hpux
- {"ja", "shiftjis"},
-#else
- {"ja", "euc-jp"},
-#endif
- {"ja_jp", "euc-jp"},
- {"ja_jp.euc", "euc-jp"},
- {"ja_jp.eucjp", "euc-jp"},
- {"ja_jp.jis", "iso2022-jp"},
- {"ja_jp.mscode", "shiftjis"},
- {"ja_jp.sjis", "shiftjis"},
- {"ja_jp.ujis", "euc-jp"},
- {"japan", "euc-jp"},
+#ifdef HAVE_LANGINFO
+ {"gb2312-1980", "gb2312"},
+ {"ansi-1251", "cp1251"}, /* Solaris gets this wrong. */
+#ifdef __hpux
+ {"SJIS", "shiftjis"},
+ {"eucjp", "euc-jp"},
+ {"euckr", "euc-kr"},
+ {"euctw", "euc-cn"},
+ {"greek8", "cp869"},
+ {"iso88591", "iso8859-1"},
+ {"iso88592", "iso8859-2"},
+ {"iso88595", "iso8859-5"},
+ {"iso88596", "iso8859-6"},
+ {"iso88597", "iso8859-7"},
+ {"iso88598", "iso8859-8"},
+ {"iso88599", "iso8859-9"},
+ {"iso885915", "iso8859-15"},
+ {"roman8", "iso8859-1"},
+ {"tis620", "tis-620"},
+ {"turkish8", "cp857"},
+ {"utf8", "utf-8"},
+#endif /* __hpux */
+#endif /* HAVE_LANGINFO */
+
+ {"ja_JP.SJIS", "shiftjis"},
+ {"ja_JP.EUC", "euc-jp"},
+ {"ja_JP.eucJP", "euc-jp"},
+ {"ja_JP.JIS", "iso2022-jp"},
+ {"ja_JP.mscode", "shiftjis"},
+ {"ja_JP.ujis", "euc-jp"},
+ {"ja_JP", "euc-jp"},
+ {"Ja_JP", "shiftjis"},
+ {"Jp_JP", "shiftjis"},
+ {"japan", "euc-jp"},
#ifdef hpux
- {"japanese", "shiftjis"},
+ {"japanese", "shiftjis"},
+ {"ja", "shiftjis"},
#else
- {"japanese", "euc-jp"},
+ {"japanese", "euc-jp"},
+ {"ja", "euc-jp"},
#endif
- {"japanese-sjis", "shiftjis"},
- {"japanese-ujis", "euc-jp"},
- {"japanese.euc", "euc-jp"},
- {"japanese.sjis", "shiftjis"},
- {"jis0201", "jis0201"},
- {"jis0208", "jis0208"},
- {"jis0212", "jis0212"},
- {"jp_jp", "shiftjis"},
- {"ko", "euc-kr"},
- {"ko_kr", "euc-kr"},
- {"ko_kr.euc", "euc-kr"},
- {"ko_kw.euckw", "euc-kr"},
- {"koi8-r", "koi8-r"},
- {"koi8-u", "koi8-u"},
- {"korean", "euc-kr"},
- {"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"},
- {"roman8", "iso8859-1"},
- {"ru", "iso8859-5"},
- {"ru_ru", "iso8859-5"},
- {"ru_su", "iso8859-5"},
- {"shiftjis", "shiftjis"},
- {"sjis", "shiftjis"},
- {"symbol", "symbol"},
- {"tis-620", "tis-620"},
- {"tis620", "tis-620"},
- {"turkish8", "cp857"},
- {"utf8", "utf-8"},
- {"zh", "cp936"},
- {"zh_cn.gb2312", "euc-cn"},
- {"zh_cn.gbk", "euc-cn"},
- {"zh_cz.gb2312", "euc-cn"},
- {"zh_tw", "euc-tw"},
- {"zh_tw.big5", "big5"},
+ {"japanese.sjis", "shiftjis"},
+ {"japanese.euc", "euc-jp"},
+ {"japanese-sjis", "shiftjis"},
+ {"japanese-ujis", "euc-jp"},
+
+ {"ko", "euc-kr"},
+ {"ko_KR", "euc-kr"},
+ {"ko_KR.EUC", "euc-kr"},
+ {"ko_KR.euc", "euc-kr"},
+ {"ko_KR.eucKR", "euc-kr"},
+ {"korean", "euc-kr"},
+
+ {"ru", "iso8859-5"},
+ {"ru_RU", "iso8859-5"},
+ {"ru_SU", "iso8859-5"},
+
+ {"zh", "cp936"},
+ {"zh_CN.gb2312", "euc-cn"},
+ {"zh_CN.GB2312", "euc-cn"},
+ {"zh_CN.GBK", "euc-cn"},
+ {"zh_TW.Big5", "big5"},
+ {"zh_TW", "euc-tw"},
+
+ {NULL, NULL}
};
-#ifndef TCL_NO_STACK_CHECK
-static int GetStackSize(size_t *stackSizePtr);
-#endif /* TCL_NO_STACK_CHECK */
#ifdef HAVE_COREFOUNDATION
-static int MacOSXGetLibraryPath(Tcl_Interp *interp,
- int maxPathLen, char *tclLibPath);
+static int MacOSXGetLibraryPath _ANSI_ARGS_((
+ Tcl_Interp *interp, int maxPathLen,
+ char *tclLibPath));
#endif /* HAVE_COREFOUNDATION */
#if defined(__APPLE__) && (defined(TCL_LOAD_FROM_MEMORY) || ( \
defined(MAC_OS_X_VERSION_MIN_REQUIRED) && ( \
@@ -388,7 +212,6 @@ static int MacOSXGetLibraryPath(Tcl_Interp *interp,
* initialize release global at startup from uname().
*/
#define GET_DARWIN_RELEASE 1
-MODULE_SCOPE long tclMacOSXDarwinRelease;
long tclMacOSXDarwinRelease = 0;
#endif
@@ -413,18 +236,13 @@ long tclMacOSXDarwinRelease = 0;
*/
void
-TclpInitPlatform(void)
+TclpInitPlatform()
{
-#ifdef DJGPP
- tclPlatform = TCL_PLATFORM_WINDOWS;
-#else
tclPlatform = TCL_PLATFORM_UNIX;
-#endif
/*
* Make sure, that the standard FDs exist. [Bug 772288]
*/
-
if (TclOSseek(0, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
open("/dev/null", O_RDONLY);
}
@@ -436,12 +254,13 @@ TclpInitPlatform(void)
}
/*
- * The code below causes SIGPIPE (broken pipe) errors to be ignored. This
- * is needed so that Tcl processes don't die if they create child
- * processes (e.g. using "exec" or "open") that terminate prematurely.
- * The signal handler is only set up when the first interpreter is
- * created; after this the application can override the handler with a
- * different one of its own, if it wants.
+ * The code below causes SIGPIPE (broken pipe) errors to
+ * be ignored. This is needed so that Tcl processes don't
+ * die if they create child processes (e.g. using "exec" or
+ * "open") that terminate prematurely. The signal handler
+ * is only set up when the first interpreter is created;
+ * after this the application can override the handler with
+ * a different one of its own, if it wants.
*/
#ifdef SIGPIPE
@@ -457,41 +276,19 @@ TclpInitPlatform(void)
*/
fpsetround(FP_RN);
- (void) fpsetmask(0L);
+ fpsetmask(0L);
#endif
#if defined(__bsdi__) && (_BSDI_VERSION > 199501)
/*
* Find local symbols. Don't report an error if we fail.
*/
-
- (void) dlopen(NULL, RTLD_NOW); /* INTL: Native. */
+ (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");
-
#ifdef GET_DARWIN_RELEASE
{
struct utsname name;
-
if (!uname(&name)) {
tclMacOSXDarwinRelease = strtol(name.release, NULL, 10);
}
@@ -504,62 +301,95 @@ TclpInitPlatform(void)
*
* TclpInitLibraryPath --
*
- * This is the fallback routine that sets the library path if the
- * application has not set one by the first time it is needed.
+ * 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.
*
* Results:
- * None.
+ * Return 1, indicating that the UTF may be dirty and require "cleanup"
+ * after encodings are initialized.
*
* Side effects:
- * Sets the library path to an initial value.
+ * None.
*
- *-------------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
-void
-TclpInitLibraryPath(
- char **valuePtr,
- int *lengthPtr,
- Tcl_Encoding *encodingPtr)
+int
+TclpInitLibraryPath(path)
+CONST char *path; /* Path to the executable in native
+ * multi-byte encoding. */
{
#define LIBRARY_SIZE 32
Tcl_Obj *pathPtr, *objPtr;
CONST char *str;
- Tcl_DString buffer;
+ Tcl_DString buffer, ds;
+ int pathc;
+ CONST char **pathv;
+ char installLib[LIBRARY_SIZE], developLib[LIBRARY_SIZE];
+ Tcl_DStringInit(&ds);
pathPtr = Tcl_NewObj();
/*
- * 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 of installLib in
- * addition to the orginal TCL_LIBRARY path.
+ * Initialize the substrings used when locating an executable. The
+ * installLib variable computes the path as though the executable
+ * is installed. The developLib computes the path as though the
+ * executable is run from a develpment directory.
*/
+
+ sprintf(installLib, "lib/tcl%s", TCL_VERSION);
+ sprintf(developLib, "tcl%s/library", TCL_PATCH_LEVEL);
- str = getenv("TCL_LIBRARY"); /* INTL: Native. */
- Tcl_ExternalToUtfDString(NULL, str, -1, &buffer);
- str = Tcl_DStringValue(&buffer);
+ /*
+ * Look for the library relative to default encoding dir.
+ */
+ str = Tcl_GetDefaultEncodingDir();
if ((str != NULL) && (str[0] != '\0')) {
- Tcl_DString ds;
- int pathc;
- CONST char **pathv;
- char installLib[LIBRARY_SIZE];
-
- Tcl_DStringInit(&ds);
+ objPtr = Tcl_NewStringObj(str, -1);
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ }
- /*
- * Initialize the substrings used when locating an executable. The
- * installLib variable computes the path as though the executable is
- * installed.
- */
+ /*
+ * 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
+ * of installLib in addition to the orginal TCL_LIBRARY path.
+ */
- sprintf(installLib, "lib/tcl%s", TCL_VERSION);
+ str = getenv("TCL_LIBRARY"); /* INTL: Native. */
+ Tcl_ExternalToUtfDString(NULL, str, -1, &buffer);
+ str = Tcl_DStringValue(&buffer);
+ if ((str != NULL) && (str[0] != '\0')) {
/*
* If TCL_LIBRARY is set, search there.
*/
-
+
objPtr = Tcl_NewStringObj(str, -1);
Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
@@ -569,10 +399,10 @@ TclpInitLibraryPath(
* If TCL_LIBRARY is set but refers to a different tcl
* installation than the current version, try fiddling with the
* specified directory to make it refer to this installation by
- * removing the old "tclX.Y" and substituting the current version
- * string.
+ * removing the old "tclX.Y" and substituting the current
+ * version string.
*/
-
+
pathv[pathc - 1] = installLib + 4;
str = Tcl_JoinPath(pathc, pathv, &ds);
objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&ds));
@@ -583,38 +413,136 @@ TclpInitLibraryPath(
}
/*
- * Finally, look for the library relative to the compiled-in path. This is
- * needed when users install Tcl with an exec-prefix that is different
- * from the prefix.
+ * Look for the library relative to the executable. This algorithm
+ * should be the same as the one in the tcl_findLibrary procedure.
+ *
+ * This code looks in the following directories:
+ *
+ * <bindir>/../<installLib>
+ * (e.g. /usr/local/bin/../lib/tcl8.4)
+ * <bindir>/../../<installLib>
+ * (e.g. /usr/local/TclPro/solaris-sparc/bin/../../lib/tcl8.4)
+ * <bindir>/../library
+ * (e.g. /usr/src/tcl8.4.0/unix/../library)
+ * <bindir>/../../library
+ * (e.g. /usr/src/tcl8.4.0/unix/solaris-sparc/../../library)
+ * <bindir>/../../<developLib>
+ * (e.g. /usr/src/tcl8.4.0/unix/../../tcl8.4.0/library)
+ * <bindir>/../../../<developLib>
+ * (e.g. /usr/src/tcl8.4.0/unix/solaris-sparc/../../../tcl8.4.0/library)
+ */
+
+
+ /*
+ * The variable path holds an absolute path. Take care not to
+ * overwrite pathv[0] since that might produce a relative path.
+ */
+
+ if (path != NULL) {
+ int i, origc;
+ CONST char **origv;
+
+ Tcl_SplitPath(path, &origc, &origv);
+ pathc = 0;
+ pathv = (CONST char **) ckalloc((unsigned int)(origc * sizeof(char *)));
+ for (i=0; i< origc; i++) {
+ if (origv[i][0] == '.') {
+ if (strcmp(origv[i], ".") == 0) {
+ /* do nothing */
+ } else if (strcmp(origv[i], "..") == 0) {
+ pathc--;
+ } else {
+ pathv[pathc++] = origv[i];
+ }
+ } else {
+ pathv[pathc++] = origv[i];
+ }
+ }
+ if (pathc > 2) {
+ str = pathv[pathc - 2];
+ pathv[pathc - 2] = installLib;
+ path = Tcl_JoinPath(pathc - 1, pathv, &ds);
+ pathv[pathc - 2] = str;
+ objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ Tcl_DStringFree(&ds);
+ }
+ if (pathc > 3) {
+ str = pathv[pathc - 3];
+ pathv[pathc - 3] = installLib;
+ path = Tcl_JoinPath(pathc - 2, pathv, &ds);
+ pathv[pathc - 3] = str;
+ objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ Tcl_DStringFree(&ds);
+ }
+ if (pathc > 2) {
+ str = pathv[pathc - 2];
+ pathv[pathc - 2] = "library";
+ path = Tcl_JoinPath(pathc - 1, pathv, &ds);
+ pathv[pathc - 2] = str;
+ objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ Tcl_DStringFree(&ds);
+ }
+ if (pathc > 3) {
+ str = pathv[pathc - 3];
+ pathv[pathc - 3] = "library";
+ path = Tcl_JoinPath(pathc - 2, pathv, &ds);
+ pathv[pathc - 3] = str;
+ objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ Tcl_DStringFree(&ds);
+ }
+ if (pathc > 3) {
+ str = pathv[pathc - 3];
+ pathv[pathc - 3] = developLib;
+ path = Tcl_JoinPath(pathc - 2, pathv, &ds);
+ pathv[pathc - 3] = str;
+ objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ Tcl_DStringFree(&ds);
+ }
+ if (pathc > 4) {
+ str = pathv[pathc - 4];
+ pathv[pathc - 4] = developLib;
+ path = Tcl_JoinPath(pathc - 3, pathv, &ds);
+ pathv[pathc - 4] = str;
+ objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ Tcl_DStringFree(&ds);
+ }
+ ckfree((char *) origv);
+ ckfree((char *) pathv);
+ }
+
+ /*
+ * Finally, look for the library relative to the compiled-in path.
+ * This is needed when users install Tcl with an exec-prefix that
+ * is different from the prtefix.
*/
{
#ifdef HAVE_COREFOUNDATION
- char tclLibPath[MAXPATHLEN + 1];
+ char tclLibPath[MAXPATHLEN + 1];
- if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
- str = tclLibPath;
- } else
+ if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
+ str = tclLibPath;
+ } else
#endif /* HAVE_COREFOUNDATION */
- {
- /*
- * TODO: Pull this value from the TIP 59 table.
- */
-
- str = defaultLibraryDir;
- }
- if (str[0] != '\0') {
- objPtr = Tcl_NewStringObj(str, -1);
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- }
+ {
+ str = defaultLibraryDir;
+ }
+ if (str[0] != '\0') {
+ objPtr = Tcl_NewStringObj(str, -1);
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
}
+ }
+
+ TclSetLibraryPath(pathPtr);
Tcl_DStringFree(&buffer);
- *encodingPtr = Tcl_GetEncoding(NULL, NULL);
- str = Tcl_GetStringFromObj(pathPtr, lengthPtr);
- *valuePtr = ckalloc((unsigned int) (*lengthPtr)+1);
- memcpy(*valuePtr, str, (size_t)(*lengthPtr)+1);
- Tcl_DecrRefCount(pathPtr);
+ return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */
}
/*
@@ -622,168 +550,250 @@ TclpInitLibraryPath(
*
* TclpSetInitialEncodings --
*
- * Based on the locale, determine the encoding of the operating system
- * and the default encoding for newly opened files.
+ * Based on the locale, determine the encoding of the operating
+ * system and the default encoding for newly opened files.
*
- * Called at process initialization time, and part way through startup,
- * we verify that the initial encodings were correctly setup. Depending
- * on Tcl's environment, there may not have been enough information first
- * time through (above).
+ * Called at process initialization time, and part way through
+ * startup, we verify that the initial encodings were correctly
+ * setup. Depending on Tcl's environment, there may not have been
+ * enough information first time through (above).
*
* Results:
* None.
*
* Side effects:
- * The Tcl library path is converted from native encoding to UTF-8, on
- * the first call, and the encodings may be changed on first or second
- * call.
+ * The Tcl library path is converted from native encoding to UTF-8,
+ * on the first call, and the encodings may be changed on first or
+ * second call.
*
*---------------------------------------------------------------------------
*/
void
-TclpSetInitialEncodings(void)
-{
- Tcl_DString encodingName;
- Tcl_SetSystemEncoding(NULL,
- Tcl_GetEncodingNameFromEnvironment(&encodingName));
- Tcl_DStringFree(&encodingName);
-}
-
-void
-TclpSetInterfaces(void)
-{
- /* do nothing */
-}
-
-static CONST char *
-SearchKnownEncodings(
- CONST char *encoding)
-{
- int left = 0;
- int right = sizeof(localeTable)/sizeof(LocaleTable);
-
- while (left <= right) {
- int test = (left + right)/2;
- int code = strcmp(localeTable[test].lang, encoding);
-
- if (code == 0) {
- return localeTable[test].encoding;
- }
- if (code < 0) {
- left = test+1;
- } else {
- right = test-1;
- }
- }
- return NULL;
-}
-
-CONST char *
-Tcl_GetEncodingNameFromEnvironment(
- Tcl_DString *bufPtr)
+TclpSetInitialEncodings()
{
- CONST char *encoding;
- CONST char *knownEncoding;
-
- Tcl_DStringInit(bufPtr);
-
- /*
- * 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).
- */
+ 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 (
+ if (
#ifdef WEAK_IMPORT_NL_LANGINFO
- nl_langinfo != NULL &&
+ nl_langinfo != NULL &&
#endif
- setlocale(LC_CTYPE, "") != NULL) {
- Tcl_DString ds;
+ setlocale(LC_CTYPE, "") != NULL) {
+ Tcl_DString ds;
- /*
- * Use a DString so we can modify case.
- */
+ /*
+ * Use a DString so we can overwrite it in name compatability
+ * checks below.
+ */
- Tcl_DStringInit(&ds);
- encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
- Tcl_UtfToLower(Tcl_DStringValue(&ds));
- knownEncoding = SearchKnownEncodings(encoding);
- if (knownEncoding != NULL) {
- Tcl_DStringAppend(bufPtr, knownEncoding, -1);
- } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
- Tcl_DStringAppend(bufPtr, encoding, -1);
+ Tcl_DStringInit(&ds);
+ encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
+
+ 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.
+ */
+
+ for (i = 0; localeTable[i].lang != NULL; i++) {
+ if (strcmp(localeTable[i].lang, encoding) == 0) {
+ setSysEncCode = Tcl_SetSystemEncoding(NULL,
+ localeTable[i].encoding);
+ break;
+ }
+ }
+ }
+#ifdef HAVE_LANGINFO_DEBUG
+ fprintf(stderr, " => '%s'\n", encoding);
+#endif
+ Tcl_DStringFree(&ds);
}
- Tcl_DStringFree(&ds);
- if (Tcl_DStringLength(bufPtr)) {
- return Tcl_DStringValue(bufPtr);
+#ifdef HAVE_LANGINFO_DEBUG
+ else {
+ fprintf(stderr, "setlocale returned NULL\n");
}
- }
+#endif
#endif /* HAVE_LANGINFO */
- /*
- * Classic fallback check. This tries a homebrew algorithm to determine
- * what encoding should be used based on env vars.
- */
-
- encoding = getenv("LC_ALL");
+ 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;
- 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 || 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) {
- CONST char *p;
- Tcl_DString ds;
+ 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;
+ }
- Tcl_DStringInit(&ds);
- p = encoding;
- encoding = Tcl_DStringAppend(&ds, p, -1);
- Tcl_UtfToLower(Tcl_DStringValue(&ds));
+ Tcl_SetSystemEncoding(NULL, encoding);
+ }
- knownEncoding = SearchKnownEncodings(encoding);
- if (knownEncoding != NULL) {
- Tcl_DStringAppend(bufPtr, knownEncoding, -1);
- } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
- Tcl_DStringAppend(bufPtr, encoding, -1);
- }
- if (Tcl_DStringLength(bufPtr)) {
- Tcl_DStringFree(&ds);
- return Tcl_DStringValue(bufPtr);
+ /*
+ * 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
}
/*
- * We didn't recognize the full value as an encoding name. If there is
- * an encoding subfield, we can try to guess from that.
+ * 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.
*/
- for (p = encoding; *p != '\0'; p++) {
- if (*p == '.') {
- p++;
- break;
- }
- }
- if (*p != '\0') {
- knownEncoding = SearchKnownEncodings(p);
- if (knownEncoding != NULL) {
- Tcl_DStringAppend(bufPtr, knownEncoding, -1);
- } else if (NULL != Tcl_GetEncoding(NULL, p)) {
- Tcl_DStringAppend(bufPtr, p, -1);
+ setlocale(LC_NUMERIC, "C");
+
+ if ((libraryPathEncodingFixed == 0) && strcmp("identity",
+ Tcl_GetEncodingName(Tcl_GetEncoding(NULL, NULL))) ) {
+ /*
+ * 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.
+ */
+
+ 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);
}
}
- Tcl_DStringFree(&ds);
- if (Tcl_DStringLength(bufPtr)) {
- return Tcl_DStringValue(bufPtr);
- }
+
+ libraryPathEncodingFixed = 1;
+ }
+
+ /* 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);
}
/*
@@ -791,9 +801,9 @@ Tcl_GetEncodingNameFromEnvironment(
*
* TclpSetVariables --
*
- * Performs platform-specific interpreter initialization related to the
- * tcl_library and tcl_platform variables, and other platform-specific
- * things.
+ * Performs platform-specific interpreter initialization related to
+ * the tcl_library and tcl_platform variables, and other platform-
+ * specific things.
*
* Results:
* None.
@@ -806,8 +816,8 @@ Tcl_GetEncodingNameFromEnvironment(
*/
void
-TclpSetVariables(
- Tcl_Interp *interp)
+TclpSetVariables(interp)
+ Tcl_Interp *interp;
{
#ifdef __CYGWIN__
SYSTEM_INFO sysInfo;
@@ -817,6 +827,7 @@ TclpSetVariables(
struct utsname name;
#endif
int unameOK;
+ CONST char *user;
Tcl_DString ds;
#ifdef HAVE_COREFOUNDATION
@@ -826,7 +837,6 @@ TclpSetVariables(
/*
* Set msgcat fallback locale to current CFLocale identifier.
*/
-
CFLocaleRef localeRef;
if (CFLocaleCopyCurrent != NULL && CFLocaleGetIdentifier != NULL &&
@@ -845,74 +855,68 @@ TclpSetVariables(
}
CFRelease(localeRef);
}
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED > 1020 */
+#endif
if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) {
- CONST char *str;
- CFBundleRef bundleRef;
-
- Tcl_SetVar(interp, "tclDefaultLibrary", tclLibPath, TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath, TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, "tcl_pkgPath", " ",
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
-
- str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
- if ((str != NULL) && (str[0] != '\0')) {
- char *p = Tcl_DStringValue(&ds);
-
- /*
- * Convert DYLD_FRAMEWORK_PATH from colon to space separated.
- */
-
- do {
- if (*p == ':') {
- *p = ' ';
- }
- } while (*p++);
- Tcl_SetVar(interp, "tcl_pkgPath", Tcl_DStringValue(&ds),
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- Tcl_SetVar(interp, "tcl_pkgPath", " ",
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- Tcl_DStringFree(&ds);
- }
- bundleRef = CFBundleGetMainBundle();
- if (bundleRef) {
- CFURLRef frameworksURL;
- Tcl_StatBuf statBuf;
-
- frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef);
- if (frameworksURL) {
- if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
- (unsigned char*) tclLibPath, MAXPATHLEN) &&
- ! TclOSstat(tclLibPath, &statBuf) &&
- S_ISDIR(statBuf.st_mode)) {
- Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- Tcl_SetVar(interp, "tcl_pkgPath", " ",
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- }
- CFRelease(frameworksURL);
- }
- frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef);
- if (frameworksURL) {
- if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
- (unsigned char*) tclLibPath, MAXPATHLEN) &&
- ! TclOSstat(tclLibPath, &statBuf) &&
- S_ISDIR(statBuf.st_mode)) {
- Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- Tcl_SetVar(interp, "tcl_pkgPath", " ",
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- }
- CFRelease(frameworksURL);
- }
- }
- Tcl_SetVar(interp, "tcl_pkgPath", pkgPath,
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ CONST char *str;
+ Tcl_DString ds;
+ CFBundleRef bundleRef;
+
+ Tcl_SetVar(interp, "tclDefaultLibrary", tclLibPath,
+ TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
+ TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "tcl_pkgPath", " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
+ if ((str != NULL) && (str[0] != '\0')) {
+ char *p = Tcl_DStringValue(&ds);
+ /* convert DYLD_FRAMEWORK_PATH from colon to space separated */
+ do {
+ if(*p == ':') *p = ' ';
+ } while (*p++);
+ Tcl_SetVar(interp, "tcl_pkgPath", Tcl_DStringValue(&ds),
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_SetVar(interp, "tcl_pkgPath", " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_DStringFree(&ds);
+ }
+ if ((bundleRef = CFBundleGetMainBundle())) {
+ CFURLRef frameworksURL;
+ Tcl_StatBuf statBuf;
+ if((frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef))) {
+ if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
+ (unsigned char*) tclLibPath, MAXPATHLEN) &&
+ ! TclOSstat(tclLibPath, &statBuf) &&
+ S_ISDIR(statBuf.st_mode)) {
+ Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_SetVar(interp, "tcl_pkgPath", " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ }
+ CFRelease(frameworksURL);
+ }
+ if((frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef))) {
+ if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
+ (unsigned char*) tclLibPath, MAXPATHLEN) &&
+ ! TclOSstat(tclLibPath, &statBuf) &&
+ S_ISDIR(statBuf.st_mode)) {
+ Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_SetVar(interp, "tcl_pkgPath", " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ }
+ CFRelease(frameworksURL);
+ }
+ }
+ Tcl_SetVar(interp, "tcl_pkgPath", pkgPath,
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
} else
#endif /* HAVE_COREFOUNDATION */
{
- Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "tclDefaultLibrary", defaultLibraryDir,
+ TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
}
#ifdef DJGPP
@@ -920,7 +924,6 @@ TclpSetVariables(
#else
Tcl_SetVar2(interp, "tcl_platform", "platform", "unix", TCL_GLOBAL_ONLY);
#endif
-
unameOK = 0;
#ifdef __CYGWIN__
unameOK = 1;
@@ -943,19 +946,19 @@ TclpSetVariables(
#elif !defined NO_UNAME
if (uname(&name) >= 0) {
CONST char *native;
-
+
unameOK = 1;
native = Tcl_ExternalToUtfDString(NULL, name.sysname, -1, &ds);
Tcl_SetVar2(interp, "tcl_platform", "os", native, TCL_GLOBAL_ONLY);
Tcl_DStringFree(&ds);
-
+
/*
- * The following code is a special hack to handle differences in the
- * way version information is returned by uname. On most systems the
- * full version number is available in name.release. However, under
- * AIX the major version number is in name.version and the minor
- * version number is in name.release.
+ * The following code is a special hack to handle differences in
+ * the way version information is returned by uname. On most
+ * systems the full version number is available in name.release.
+ * However, under AIX the major version number is in
+ * name.version and the minor version number is in name.release.
*/
if ((strchr(name.release, '.') != NULL)
@@ -963,33 +966,17 @@ TclpSetVariables(
Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
TCL_GLOBAL_ONLY);
} else {
-#ifdef DJGPP
- /*
- * For some obscure reason DJGPP puts major version into
- * name.release and minor into name.version. As of DJGPP 2.04 this
- * is documented in djgpp libc.info file.
- */
-
- Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
- TCL_GLOBAL_ONLY);
- Tcl_SetVar2(interp, "tcl_platform", "osVersion", ".",
- TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
- Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.version,
- TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
-#else
Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.version,
TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "tcl_platform", "osVersion", ".",
TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
-
-#endif /* DJGPP */
}
Tcl_SetVar2(interp, "tcl_platform", "machine", name.machine,
TCL_GLOBAL_ONLY);
}
-#endif /* !NO_UNAME */
+#endif
if (!unameOK) {
Tcl_SetVar2(interp, "tcl_platform", "os", "", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "tcl_platform", "osVersion", "", TCL_GLOBAL_ONLY);
@@ -997,24 +984,20 @@ TclpSetVariables(
}
/*
- * Copy the username of the real user (according to getuid()) into
- * tcl_platform(user).
+ * Copy USER or LOGNAME environment variable into tcl_platform(user)
*/
- {
- struct passwd *pwEnt = TclpGetPwUid(getuid());
- const char *user;
-
- if (pwEnt == NULL) {
+ Tcl_DStringInit(&ds);
+ user = TclGetEnv("USER", &ds);
+ if (user == NULL) {
+ user = TclGetEnv("LOGNAME", &ds);
+ if (user == NULL) {
user = "";
- Tcl_DStringInit(&ds); /* ensure cleanliness */
- } else {
- user = Tcl_ExternalToUtfDString(NULL, pwEnt->pw_name, -1, &ds);
}
-
- Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
- Tcl_DStringFree(&ds);
}
+ Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
+ Tcl_DStringFree(&ds);
+
}
/*
@@ -1022,14 +1005,15 @@ TclpSetVariables(
*
* TclpFindVariable --
*
- * Locate the entry in environ for a given name. On Unix this routine is
- * case sensetive, on Windows this matches mixed case.
+ * Locate the entry in environ for a given name. On Unix this
+ * routine is case sensetive, on Windows this matches mixed case.
*
* Results:
- * The return value is the index in environ of an entry with the name
- * "name", or -1 if there is no such entry. The integer at *lengthPtr is
- * filled in with the length of name (if a matching entry is found) or
- * the length of the environ array (if no matching entry is found).
+ * The return value is the index in environ of an entry with the
+ * name "name", or -1 if there is no such entry. The integer at
+ * *lengthPtr is filled in with the length of name (if a matching
+ * entry is found) or the length of the environ array (if no matching
+ * entry is found).
*
* Side effects:
* None.
@@ -1038,10 +1022,10 @@ TclpSetVariables(
*/
int
-TclpFindVariable(
- CONST char *name, /* Name of desired environment variable
+TclpFindVariable(name, lengthPtr)
+ CONST char *name; /* Name of desired environment variable
* (native). */
- int *lengthPtr) /* Used to return length of name (for
+ int *lengthPtr; /* Used to return length of name (for
* successful searches) or number of non-NULL
* entries in environ (for unsuccessful
* searches). */
@@ -1063,231 +1047,155 @@ TclpFindVariable(
result = i;
goto done;
}
-
+
Tcl_DStringFree(&envString);
}
-
+
*lengthPtr = i;
- done:
+ done:
Tcl_DStringFree(&envString);
return result;
}
-#ifndef TCL_NO_STACK_CHECK
/*
*----------------------------------------------------------------------
*
- * TclpGetCStackParams --
+ * Tcl_Init --
*
- * Determine the stack params for the current thread: in which
- * direction does the stack grow, and what is the stack lower (resp.
- * upper) bound for safe invocation of a new command? This is used to
- * cache the values needed for an efficient computation of
- * TclpCheckStackSpace() when the interp is known.
+ * This procedure is typically invoked by Tcl_AppInit procedures
+ * to find and source the "init.tcl" script, which should exist
+ * somewhere on the Tcl library path.
*
* Results:
- * Returns 1 if the stack grows down, in which case a stack lower bound
- * is stored at stackBoundPtr. If the stack grows up, 0 is returned and
- * an upper bound is stored at stackBoundPtr. If a bound cannot be
- * determined NULL is stored at stackBoundPtr.
+ * Returns a standard Tcl completion code and sets the interp's
+ * result if there is an error.
+ *
+ * Side effects:
+ * Depends on what's in the init.tcl script.
*
*----------------------------------------------------------------------
*/
int
-TclpGetCStackParams(
- int **stackBoundPtr)
+Tcl_Init(interp)
+ Tcl_Interp *interp; /* Interpreter to initialize. */
{
- int result = TCL_OK;
- size_t stackSize = 0; /* The size of the current stack. */
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- /* Most variables are actually in a
- * thread-specific data block to minimise the
- * impact on the stack. */
-#ifdef TCL_CROSS_COMPILE
- if (stackGrowsDown == -1) {
- /*
- * Not initialised!
- */
+ Tcl_Obj *pathPtr;
- stackGrowsDown = StackGrowsDown(&result);
+ if (tclPreInitScript != NULL) {
+ if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
+ return (TCL_ERROR);
+ };
}
-#endif
- /*
- * The first time through in a thread: record the "outermost" stack
- * frame and inquire with the OS about the stack size.
- */
-
- if (tsdPtr->outerVarPtr == NULL) {
- tsdPtr->outerVarPtr = &result;
- result = GetStackSize(&stackSize);
- if (result != TCL_OK) {
- /* Can't check, assume it always succeeds */
-#ifdef TCL_CROSS_COMPILE
- stackGrowsDown = 1;
-#endif
- tsdPtr->stackBound = NULL;
- goto done;
- }
+ pathPtr = TclGetLibraryPath();
+ if (pathPtr == NULL) {
+ pathPtr = Tcl_NewObj();
}
+ Tcl_IncrRefCount(pathPtr);
+ Tcl_SetVar2Ex(interp, "tcl_libPath", NULL, pathPtr, TCL_GLOBAL_ONLY);
+ Tcl_DecrRefCount(pathPtr);
+ return Tcl_Eval(interp, initScript);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SourceRCFile --
+ *
+ * This procedure is typically invoked by Tcl_Main of Tk_Main
+ * procedure to source an application specific rc file into the
+ * interpreter at startup time.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on what's in the rc script.
+ *
+ *----------------------------------------------------------------------
+ */
- if (stackSize || (tsdPtr->stackBound &&
- ((stackGrowsDown && (&result < tsdPtr->stackBound)) ||
- (!stackGrowsDown && (&result > tsdPtr->stackBound))))) {
- /*
- * Either the thread's first pass or stack failure: set the params
- */
+void
+Tcl_SourceRCFile(interp)
+ Tcl_Interp *interp; /* Interpreter to source rc file into. */
+{
+ Tcl_DString temp;
+ CONST char *fileName;
+ Tcl_Channel errChannel;
+
+ fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
+
+ if (fileName != NULL) {
+ Tcl_Channel c;
+ CONST char *fullName;
- if (!stackSize) {
+ Tcl_DStringInit(&temp);
+ fullName = Tcl_TranslateFileName(interp, fileName, &temp);
+ if (fullName == NULL) {
/*
- * Stack failure: if we didn't already blow up, we are within the
- * safety area. Recheck with the OS in case the stack was grown.
+ * Couldn't translate the file name (e.g. it referred to a
+ * bogus user or there was no HOME environment variable).
+ * Just do nothing.
*/
- result = GetStackSize(&stackSize);
- if (result != TCL_OK) {
- /* Can't check, assume it always succeeds */
-#ifdef TCL_CROSS_COMPILE
- stackGrowsDown = 1;
-#endif
- tsdPtr->stackBound = NULL;
- goto done;
- }
- }
-
- if (stackGrowsDown) {
- tsdPtr->stackBound = (int *) ((char *)tsdPtr->outerVarPtr -
- stackSize);
- if (tsdPtr->stackBound > tsdPtr->outerVarPtr) {
- /* Overflow, that should never happen, just set it to NULL.
- * See [Bug #3166410] */
- tsdPtr->stackBound = NULL;
- }
} else {
- tsdPtr->stackBound = (int *) ((char *)tsdPtr->outerVarPtr +
- stackSize);
- if (tsdPtr->stackBound < tsdPtr->outerVarPtr) {
- /* Overflow, that should never happen, just set it to NULL.
- * See [Bug #3166410] */
- tsdPtr->stackBound = NULL;
+
+ /*
+ * Test for the existence of the rc file before trying to read it.
+ */
+
+ c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
+ if (c != (Tcl_Channel) NULL) {
+ Tcl_Close(NULL, c);
+ if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
+ errChannel = Tcl_GetStdChannel(TCL_STDERR);
+ if (errChannel) {
+ Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
+ Tcl_WriteChars(errChannel, "\n", 1);
+ }
+ }
}
}
+ Tcl_DStringFree(&temp);
}
-
- done:
- *stackBoundPtr = tsdPtr->stackBound;
- return stackGrowsDown;
-}
-
-#ifdef TCL_CROSS_COMPILE
-int
-StackGrowsDown(
- int *parent)
-{
- int here;
- return (&here < parent);
}
-#endif
/*
*----------------------------------------------------------------------
*
- * GetStackSize --
+ * TclpCheckStackSpace --
*
- * Discover what the stack size for the current thread/process actually
- * is. Expects to only ever be called once per thread and then only at a
- * point when there is a reasonable amount of space left on the current
- * stack; TclpCheckStackSpace is called sufficiently frequently that that
- * is true.
+ * Detect if we are about to blow the stack. Called before an
+ * evaluation can happen when nesting depth is checked.
*
* Results:
- * TCL_OK if the stack space was discovered, TCL_BREAK if the stack space
- * was undiscoverable in a way that stack checks should fail, and
- * TCL_CONTINUE if the stack space was undiscoverable in a way that stack
- * checks should succeed.
+ * 1 if there is enough stack space to continue; 0 if not.
*
* Side effects:
- * None
+ * None.
*
*----------------------------------------------------------------------
*/
-static int
-GetStackSize(
- size_t *stackSizePtr)
+int
+TclpCheckStackSpace()
{
- size_t rawStackSize;
- struct rlimit rLimit; /* The result from getrlimit(). */
-
-#ifdef TCL_THREADS
- rawStackSize = TclpThreadGetStackSize();
- if (rawStackSize == (size_t) -1) {
- /*
- * Some kind of confirmed error in TclpThreadGetStackSize?! Fall back
- * to whatever getrlimit can determine.
- */
- STACK_DEBUG(("stack checks: TclpThreadGetStackSize failed in \n"));
- }
- if (rawStackSize > 0) {
- goto finalSanityCheck;
- }
-
/*
- * If we have zero or an error, try the system limits instead. After all,
- * the pthread documentation states that threads should always be bound by
- * the system stack size limit in any case.
+ * This function is unimplemented on Unix platforms.
*/
-#endif /* TCL_THREADS */
- if (getrlimit(RLIMIT_STACK, &rLimit) != 0) {
- /*
- * getrlimit() failed, just fail the whole thing.
- */
- STACK_DEBUG(("skipping stack checks with failure: getrlimit failed\n"));
- return TCL_BREAK;
- }
- if (rLimit.rlim_cur == RLIM_INFINITY) {
- /*
- * Limit is "infinite"; there is no stack limit.
- */
- STACK_DEBUG(("skipping stack checks with success: infinite limit\n"));
- return TCL_CONTINUE;
- }
- rawStackSize = rLimit.rlim_cur;
-
- /*
- * Final sanity check on the determined stack size. If we fail this,
- * assume there are bogus values about and that we can't actually figure
- * out what the stack size really is.
- */
-
-#ifdef TCL_THREADS /* Stop warning... */
- finalSanityCheck:
-#endif
- if (rawStackSize <= 0) {
- STACK_DEBUG(("skipping stack checks with success\n"));
- return TCL_CONTINUE;
- }
-
- /*
- * Calculate a stack size with a safety margin.
- */
-
- *stackSizePtr = (rawStackSize / TCL_MAGIC_STACK_DIVISOR)
- - (getpagesize() * TCL_RESERVED_STACK_PAGES);
-
- return TCL_OK;
+ return 1;
}
-#endif /* TCL_NO_STACK_CHECK */
/*
*----------------------------------------------------------------------
*
* MacOSXGetLibraryPath --
*
- * If we have a bundle structure for the Tcl installation, then check
- * there first to see if we can find the libraries there.
+ * If we have a bundle structure for the Tcl installation,
+ * then check there first to see if we can find the libraries
+ * there.
*
* Results:
* TCL_OK if we have found the tcl library; TCL_ERROR otherwise.
@@ -1300,27 +1208,13 @@ GetStackSize(
#ifdef HAVE_COREFOUNDATION
static int
-MacOSXGetLibraryPath(
- Tcl_Interp *interp,
- int maxPathLen,
- char *tclLibPath)
+MacOSXGetLibraryPath(Tcl_Interp *interp, int maxPathLen, char *tclLibPath)
{
int foundInFramework = TCL_ERROR;
-
#ifdef TCL_FRAMEWORK
- foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
- "com.tcltk.tcllibrary", TCL_FRAMEWORK_VERSION, 0, maxPathLen,
- tclLibPath);
+ foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
+ "com.tcltk.tcllibrary", TCL_FRAMEWORK_VERSION, 0, maxPathLen, tclLibPath);
#endif
-
return foundInFramework;
}
#endif /* HAVE_COREFOUNDATION */
-
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * fill-column: 78
- * End:
- */