summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixInit.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixInit.c')
-rw-r--r--unix/tclUnixInit.c1557
1 files changed, 704 insertions, 853 deletions
diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c
index 21ec34b..1617cba 100644
--- a/unix/tclUnixInit.c
+++ b/unix/tclUnixInit.c
@@ -6,18 +6,23 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 1999 by Scriptics Corporation.
* All rights reserved.
- *
- * RCS: @(#) $Id: tclUnixInit.c,v 1.50 2004/11/12 19:08:10 das Exp $
*/
#include "tclInt.h"
#include <stddef.h>
#include <locale.h>
#ifdef HAVE_LANGINFO
-#include <langinfo.h>
+# include <langinfo.h>
+# ifdef __APPLE__
+# if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030
+ /* Support for weakly importing nl_langinfo on Darwin. */
+# define WEAK_IMPORT_NL_LANGINFO
+ extern char *nl_langinfo(nl_item) WEAK_IMPORT_ATTRIBUTE;
+# endif
+# endif
#endif
#include <sys/resource.h>
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) && defined(__GNUC__)
# include <floatingpoint.h>
#endif
#if defined(__bsdi__)
@@ -26,82 +31,62 @@
# include <dlfcn.h>
# endif
#endif
-#ifdef HAVE_CFBUNDLE
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-/*
- * Define this if you want to revert to the old behavior of
- * never checking the stack.
- */
-#undef TCL_NO_STACK_CHECK
+#ifdef __CYGWIN__
+DLLIMPORT extern __stdcall unsigned char GetVersionExW(void *);
+DLLIMPORT extern __stdcall void *LoadLibraryW(const void *);
+DLLIMPORT extern __stdcall void FreeLibrary(void *);
+DLLIMPORT extern __stdcall void *GetProcAddress(void *, const char *);
+DLLIMPORT extern __stdcall void GetSystemInfo(void *);
-/*
- * Define this if you want to see a lot of output regarding
- * stack checking.
- */
-#undef TCL_DEBUG_STACK_CHECK
+#define NUMPLATFORMS 4
+static const char *const platforms[NUMPLATFORMS] = {
+ "Win32s", "Windows 95", "Windows NT", "Windows CE"
+};
-/*
- * Values used to compute how much space is really available for Tcl's
- * use for the stack.
- *
- * NOTE: Now I have some idea why the maximum stack size must be
- * divided by 64 on FreeBSD with threads enabled to get a reasonably
- * correct value.
- *
- * The getrlimit() function is documented to return the maximum stack
- * size in bytes. However, with threads enabled, the pthread library
- * does bad things to the stack size limits. First, the limits cannot
- * be changed. Second, they appear to be reported incorrectly by a
- * factor of about 64.
- *
- * The defines below may need to be adjusted if more platforms have
- * this broken behavior with threads enabled.
- */
+#define NUMPROCESSORS 11
+static const char *const processors[NUMPROCESSORS] = {
+ "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
+ "amd64", "ia32_on_win64"
+};
-#if defined(__FreeBSD__)
-# define TCL_MAGIC_STACK_DIVISOR 64
-# define TCL_RESERVED_STACK_PAGES 3
+typedef struct _SYSTEM_INFO {
+ union {
+ DWORD dwOemId;
+ struct {
+ int wProcessorArchitecture;
+ int wReserved;
+ };
+ };
+ DWORD dwPageSize;
+ void *lpMinimumApplicationAddress;
+ void *lpMaximumApplicationAddress;
+ void *dwActiveProcessorMask;
+ DWORD dwNumberOfProcessors;
+ DWORD dwProcessorType;
+ DWORD dwAllocationGranularity;
+ int wProcessorLevel;
+ int wProcessorRevision;
+} SYSTEM_INFO;
+
+typedef struct _OSVERSIONINFOW {
+ DWORD dwOSVersionInfoSize;
+ DWORD dwMajorVersion;
+ DWORD dwMinorVersion;
+ DWORD dwBuildNumber;
+ DWORD dwPlatformId;
+ wchar_t szCSDVersion[128];
+} OSVERSIONINFOW;
#endif
-#ifndef TCL_MAGIC_STACK_DIVISOR
-#define TCL_MAGIC_STACK_DIVISOR 1
-#endif
-#ifndef TCL_RESERVED_STACK_PAGES
-#define TCL_RESERVED_STACK_PAGES 8
+#ifdef HAVE_COREFOUNDATION
+#include <CoreFoundation/CoreFoundation.h>
#endif
/*
- * Thread specific data for stack checking.
- */
-
-#ifndef TCL_NO_STACK_CHECK
-typedef struct ThreadSpecificData {
- int *outerVarPtr; /* The "outermost" stack frame pointer for
- * this thread. */
- int initialised; /* Have we found what the stack size was? */
- int stackDetermineResult; /* What happened when we did that? */
- size_t stackSize; /* The size of the current stack. */
-} ThreadSpecificData;
-static Tcl_ThreadDataKey dataKey;
-#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
@@ -109,108 +94,245 @@ static int libraryPathEncodingFixed = 0;
#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 {
- CONST char *lang;
- CONST char *encoding;
+ const char *lang;
+ const char *encoding;
} LocaleTable;
-static CONST LocaleTable localeTable[] = {
-#ifdef HAVE_LANGINFO
- {"gb2312-1980", "gb2312"},
-#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 */
+/*
+ * 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.
+ */
- {"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"},
+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 hpux
- {"japanese", "shiftjis"},
- {"ja", "shiftjis"},
+ {"japanese", "shiftjis"},
#else
- {"japanese", "euc-jp"},
- {"ja", "euc-jp"},
+ {"japanese", "euc-jp"},
#endif
- {"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}
+ {"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"},
};
-#ifndef TCL_NO_STACK_CHECK
-static int GetStackSize _ANSI_ARGS_((size_t *stackSizePtr));
-#endif /* TCL_NO_STACK_CHECK */
-#ifdef HAVE_CFBUNDLE
-static int MacOSXGetLibraryPath _ANSI_ARGS_((
- Tcl_Interp *interp, int maxPathLen,
- char *tclLibPath));
-#endif /* HAVE_CFBUNDLE */
+#ifdef HAVE_COREFOUNDATION
+static int MacOSXGetLibraryPath(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) && ( \
+ (defined(TCL_THREADS) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030) || \
+ (defined(__LP64__) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050) || \
+ (defined(HAVE_COREFOUNDATION) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050)\
+ )))
+/*
+ * Need to check Darwin release at runtime in tclUnixFCmd.c and tclLoadDyld.c:
+ * initialize release global at startup from uname().
+ */
+#define GET_DARWIN_RELEASE 1
+MODULE_SCOPE long tclMacOSXDarwinRelease;
+long tclMacOSXDarwinRelease = 0;
+#endif
/*
@@ -233,7 +355,7 @@ static int MacOSXGetLibraryPath _ANSI_ARGS_((
*/
void
-TclpInitPlatform()
+TclpInitPlatform(void)
{
#ifdef DJGPP
tclPlatform = TCL_PLATFORM_WINDOWS;
@@ -256,20 +378,26 @@ TclpInitPlatform()
}
/*
- * 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
(void) signal(SIGPIPE, SIG_IGN);
#endif /* SIGPIPE */
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) && defined(__GNUC__)
+ /*
+ * Adjust the rounding mode to be more conventional. Note that FreeBSD
+ * only provides the __fpsetreg() used by the following two for the GNU
+ * Compiler. When using, say, Intel's icc they break. (Partially based on
+ * patch in BSD ports system from root@celsius.bychok.com)
+ */
+
fpsetround(FP_RN);
(void) fpsetmask(0L);
#endif
@@ -278,7 +406,38 @@ TclpInitPlatform()
/*
* 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);
+ }
+ }
#endif
}
@@ -287,84 +446,36 @@ TclpInitPlatform()
*
* TclpInitLibraryPath --
*
- * Initialize the library path at startup. We have a minor
- * metacircular problem that we don't know the encoding of the
- * operating system but we may need to talk to operating system
- * to find the library directories so that we know how to talk to
- * the operating system.
- *
- * We do not know the encoding of the operating system.
- * We do know that the encoding is some multibyte encoding.
- * In that multibyte encoding, the characters 0..127 are equivalent
- * to ascii.
- *
- * So although we don't know the encoding, it's safe:
- * to look for the last slash character in a path in the encoding.
- * to append an ascii string to a path.
- * to pass those strings back to the operating system.
- *
- * But any strings that we remembered before we knew the encoding of
- * the operating system must be translated to UTF-8 once we know the
- * encoding so that the rest of Tcl can use those strings.
- *
- * This call sets the library path to strings in the unknown native
- * encoding. TclpSetInitialEncodings() will translate the library
- * path from the native encoding to UTF-8 as soon as it determines
- * what the native encoding actually is.
- *
- * Called at process initialization time.
+ * This is the fallback routine that sets the library path if the
+ * application has not set one by the first time it is needed.
*
* Results:
- * Return 1, indicating that the UTF may be dirty and require "cleanup"
- * after encodings are initialized.
+ * None.
*
* Side effects:
- * None.
+ * Sets the library path to an initial value.
*
- *---------------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*/
-int
-TclpInitLibraryPath(path)
-CONST char *path; /* Path to the executable in native
- * multi-byte encoding. */
+void
+TclpInitLibraryPath(
+ char **valuePtr,
+ int *lengthPtr,
+ Tcl_Encoding *encodingPtr)
{
#define LIBRARY_SIZE 32
Tcl_Obj *pathPtr, *objPtr;
- CONST char *str;
- Tcl_DString buffer, ds;
- int pathc;
- CONST char **pathv;
- char installLib[LIBRARY_SIZE], developLib[LIBRARY_SIZE];
+ const char *str;
+ Tcl_DString buffer;
- Tcl_DStringInit(&ds);
pathPtr = Tcl_NewObj();
/*
- * 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);
-
- /*
- * Look for the library relative to default encoding dir.
- */
-
- str = Tcl_GetDefaultEncodingDir();
- if ((str != NULL) && (str[0] != '\0')) {
- objPtr = Tcl_NewStringObj(str, -1);
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- }
-
- /*
- * Look for the library relative to the TCL_LIBRARY env variable.
- * If the last dirname in the TCL_LIBRARY path does not match the
- * last dirname in the installLib variable, use the last dir name
- * of installLib in addition to the orginal TCL_LIBRARY path.
+ * 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.
*/
str = getenv("TCL_LIBRARY"); /* INTL: Native. */
@@ -372,12 +483,26 @@ CONST char *path; /* Path to the executable in native
str = Tcl_DStringValue(&buffer);
if ((str != NULL) && (str[0] != '\0')) {
+ Tcl_DString ds;
+ int pathc;
+ const char **pathv;
+ char installLib[LIBRARY_SIZE];
+
+ Tcl_DStringInit(&ds);
+
+ /*
+ * Initialize the substrings used when locating an executable. The
+ * installLib variable computes the path as though the executable is
+ * installed.
+ */
+
+ sprintf(installLib, "lib/tcl%s", TCL_VERSION);
+
/*
* If TCL_LIBRARY is set, search there.
*/
- objPtr = Tcl_NewStringObj(str, -1);
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ Tcl_ListObjAppendElement(NULL, pathPtr, Tcl_NewStringObj(str, -1));
Tcl_SplitPath(str, &pathc, &pathv);
if ((pathc > 0) && (strcasecmp(installLib + 4, pathv[pathc-1]) != 0)) {
@@ -385,149 +510,50 @@ CONST char *path; /* Path to the executable in native
* 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));
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- Tcl_DStringFree(&ds);
+ Tcl_ListObjAppendElement(NULL, pathPtr, TclDStringToObj(&ds));
}
- ckfree((char *) pathv);
+ ckfree(pathv);
}
/*
- * 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)
+ * 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.
*/
- /*
- * The variable path holds an absolute path. Take care not to
- * overwrite pathv[0] since that might produce a relative path.
- */
-
- if (0 && 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);
+ {
+#ifdef HAVE_COREFOUNDATION
+ char tclLibPath[MAXPATHLEN + 1];
+
+ 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 (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));
+ if (str[0] != '\0') {
+ objPtr = Tcl_NewStringObj(str, -1);
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_CFBUNDLE
- char tclLibPath[MAXPATHLEN + 1];
-
- if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
- str = tclLibPath;
- } else
-#endif /* HAVE_CFBUNDLE */
- {
- str = defaultLibraryDir;
- }
- if (str[0] != '\0') {
- objPtr = Tcl_NewStringObj(str, -1);
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- }
}
-
- TclSetLibraryPath(pathPtr);
Tcl_DStringFree(&buffer);
- return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */
+ *encodingPtr = Tcl_GetEncoding(NULL, NULL);
+ str = Tcl_GetStringFromObj(pathPtr, lengthPtr);
+ *valuePtr = ckalloc((*lengthPtr) + 1);
+ memcpy(*valuePtr, str, (size_t)(*lengthPtr)+1);
+ Tcl_DecrRefCount(pathPtr);
}
/*
@@ -535,245 +561,168 @@ CONST char *path; /* Path to the executable in native
*
* 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()
+TclpSetInitialEncodings(void)
{
- if (libraryPathEncodingFixed == 0) {
- CONST char *encoding = NULL;
- int i, setSysEncCode = TCL_ERROR;
- Tcl_Obj *pathPtr;
+ Tcl_DString encodingName;
+ Tcl_SetSystemEncoding(NULL,
+ Tcl_GetEncodingNameFromEnvironment(&encodingName));
+ Tcl_DStringFree(&encodingName);
+}
- /*
- * Determine the current encoding from the LC_* or LANG environment
- * variables. We previously used setlocale() to determine the locale,
- * but this does not work on some systems (e.g. Linux/i386 RH 5.0).
- */
-#ifdef HAVE_LANGINFO
- if (setlocale(LC_CTYPE, "") != NULL) {
- Tcl_DString ds;
+void
+TclpSetInterfaces(void)
+{
+ /* do nothing */
+}
- /*
- * Use a DString so we can overwrite it in name compatability
- * checks below.
- */
+static const char *
+SearchKnownEncodings(
+ const char *encoding)
+{
+ int left = 0;
+ int right = sizeof(localeTable)/sizeof(LocaleTable);
- Tcl_DStringInit(&ds);
- encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
+ while (left <= right) {
+ int test = (left + right)/2;
+ int code = strcmp(localeTable[test].lang, encoding);
- 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);
+ if (code == 0) {
+ return localeTable[test].encoding;
}
-#ifdef HAVE_LANGINFO_DEBUG
- else {
- fprintf(stderr, "setlocale returned NULL\n");
+ if (code < 0) {
+ left = test+1;
+ } else {
+ right = test-1;
}
-#endif
-#endif /* HAVE_LANGINFO */
-
- if (setSysEncCode != TCL_OK) {
- /*
- * Classic fallback check. This tries a homebrew algorithm to
- * determine what encoding should be used based on env vars.
- */
- char *langEnv = getenv("LC_ALL");
- encoding = NULL;
+ }
+ return 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;
- }
+const char *
+Tcl_GetEncodingNameFromEnvironment(
+ Tcl_DString *bufPtr)
+{
+ const char *encoding;
+ const char *knownEncoding;
- 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(bufPtr);
- Tcl_SetSystemEncoding(NULL, encoding);
- }
+ /*
+ * 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).
+ */
- /*
- * 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, "");
+#ifdef HAVE_LANGINFO
+ if (
+#ifdef WEAK_IMPORT_NL_LANGINFO
+ nl_langinfo != NULL &&
#endif
- }
+ setlocale(LC_CTYPE, "") != NULL) {
+ Tcl_DString ds;
/*
- * 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.
+ * Use a DString so we can modify case.
*/
- setlocale(LC_NUMERIC, "C");
+ 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_DStringFree(&ds);
+ if (Tcl_DStringLength(bufPtr)) {
+ return Tcl_DStringValue(bufPtr);
+ }
+ }
+#endif /* HAVE_LANGINFO */
- /*
- * 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.
- */
+ /*
+ * Classic fallback check. This tries a homebrew algorithm to determine
+ * what encoding should be used based on env vars.
+ */
- 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);
- }
- }
+ encoding = getenv("LC_ALL");
- libraryPathEncodingFixed = 1;
+ 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 (encoding != NULL) {
+ const char *p;
+ Tcl_DString ds;
+
+ Tcl_DStringInit(&ds);
+ p = encoding;
+ encoding = Tcl_DStringAppend(&ds, p, -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);
+ }
+ if (Tcl_DStringLength(bufPtr)) {
+ Tcl_DStringFree(&ds);
+ return Tcl_DStringValue(bufPtr);
+ }
- /* This is only ever called from the startup thread */
- if (binaryEncoding == NULL) {
/*
- * Keep the iso8859-1 encoding preloaded. The IO package uses
- * it for gets on a binary channel.
+ * We didn't recognize the full value as an encoding name. If there is
+ * an encoding subfield, we can try to guess from that.
*/
- binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");
+
+ 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);
+ }
+ }
+ Tcl_DStringFree(&ds);
+ if (Tcl_DStringLength(bufPtr)) {
+ return Tcl_DStringValue(bufPtr);
+ }
}
+ return Tcl_DStringAppend(bufPtr, TCL_DEFAULT_ENCODING, -1);
}
/*
@@ -781,9 +730,9 @@ TclpSetInitialEncodings()
*
* 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.
@@ -796,77 +745,114 @@ TclpSetInitialEncodings()
*/
void
-TclpSetVariables(interp)
- Tcl_Interp *interp;
+TclpSetVariables(
+ Tcl_Interp *interp)
{
-#ifndef NO_UNAME
+#ifdef __CYGWIN__
+ SYSTEM_INFO sysInfo;
+ static OSVERSIONINFOW osInfo;
+ static int osInfoInitialized = 0;
+ char buffer[TCL_INTEGER_SPACE * 2];
+#elif !defined(NO_UNAME)
struct utsname name;
#endif
int unameOK;
- CONST char *user;
Tcl_DString ds;
-#ifdef HAVE_CFBUNDLE
+#ifdef HAVE_COREFOUNDATION
char tclLibPath[MAXPATHLEN + 1];
+#if MAC_OS_X_VERSION_MAX_ALLOWED > 1020
+ /*
+ * Set msgcat fallback locale to current CFLocale identifier.
+ */
+
+ CFLocaleRef localeRef;
+
+ if (CFLocaleCopyCurrent != NULL && CFLocaleGetIdentifier != NULL &&
+ (localeRef = CFLocaleCopyCurrent())) {
+ CFStringRef locale = CFLocaleGetIdentifier(localeRef);
+
+ if (locale) {
+ char loc[256];
+
+ if (CFStringGetCString(locale, loc, 256, kCFStringEncodingUTF8)) {
+ if (!Tcl_CreateNamespace(interp, "::tcl::mac", NULL, NULL)) {
+ Tcl_ResetResult(interp);
+ }
+ Tcl_SetVar(interp, "::tcl::mac::locale", loc, TCL_GLOBAL_ONLY);
+ }
+ }
+ CFRelease(localeRef);
+ }
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED > 1020 */
+
if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) {
- 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,
- 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,
- 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;
+ 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);
} else
-#endif /* HAVE_CFBUNDLE */
+#endif /* HAVE_COREFOUNDATION */
{
- Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
}
#ifdef DJGPP
@@ -874,10 +860,41 @@ TclpSetVariables(interp)
#else
Tcl_SetVar2(interp, "tcl_platform", "platform", "unix", TCL_GLOBAL_ONLY);
#endif
+
unameOK = 0;
-#ifndef NO_UNAME
+#ifdef __CYGWIN__
+ unameOK = 1;
+ if (!osInfoInitialized) {
+ HANDLE handle = LoadLibraryW(L"NTDLL");
+ int(__stdcall *getversion)(void *) =
+ (int(__stdcall *)(void *))GetProcAddress(handle, "RtlGetVersion");
+ osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+ if (!getversion || getversion(&osInfo)) {
+ GetVersionExW(&osInfo);
+ }
+ if (handle) {
+ FreeLibrary(handle);
+ }
+ osInfoInitialized = 1;
+ }
+
+ GetSystemInfo(&sysInfo);
+
+ if (osInfo.dwPlatformId < NUMPLATFORMS) {
+ Tcl_SetVar2(interp, "tcl_platform", "os",
+ platforms[osInfo.dwPlatformId], TCL_GLOBAL_ONLY);
+ }
+ sprintf(buffer, "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", buffer, TCL_GLOBAL_ONLY);
+ if (sysInfo.wProcessorArchitecture < NUMPROCESSORS) {
+ Tcl_SetVar2(interp, "tcl_platform", "machine",
+ processors[sysInfo.wProcessorArchitecture],
+ TCL_GLOBAL_ONLY);
+ }
+
+#elif !defined NO_UNAME
if (uname(&name) >= 0) {
- CONST char *native;
+ const char *native;
unameOK = 1;
@@ -886,11 +903,11 @@ TclpSetVariables(interp)
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)
@@ -899,9 +916,12 @@ TclpSetVariables(interp)
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*/
+ /*
+ * 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", ".",
@@ -916,12 +936,12 @@ TclpSetVariables(interp)
Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
-#endif
+#endif /* DJGPP */
}
Tcl_SetVar2(interp, "tcl_platform", "machine", name.machine,
TCL_GLOBAL_ONLY);
}
-#endif
+#endif /* !NO_UNAME */
if (!unameOK) {
Tcl_SetVar2(interp, "tcl_platform", "os", "", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "tcl_platform", "osVersion", "", TCL_GLOBAL_ONLY);
@@ -929,20 +949,30 @@ TclpSetVariables(interp)
}
/*
- * Copy USER or LOGNAME environment variable into tcl_platform(user)
+ * Copy the username of the real user (according to getuid()) into
+ * tcl_platform(user).
*/
- Tcl_DStringInit(&ds);
- user = TclGetEnv("USER", &ds);
- if (user == NULL) {
- user = TclGetEnv("LOGNAME", &ds);
- if (user == NULL) {
+ {
+ struct passwd *pwEnt = TclpGetPwUid(getuid());
+ const char *user;
+
+ if (pwEnt == 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);
+ /*
+ * Define what the platform PATH separator is. [TIP #315]
+ */
+
+ Tcl_SetVar2(interp, "tcl_platform","pathSeparator", ":", TCL_GLOBAL_ONLY);
}
/*
@@ -950,15 +980,14 @@ TclpSetVariables(interp)
*
* 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.
@@ -967,16 +996,16 @@ TclpSetVariables(interp)
*/
int
-TclpFindVariable(name, lengthPtr)
- CONST char *name; /* Name of desired environment variable
+TclpFindVariable(
+ 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). */
{
int i, result = -1;
- register CONST char *env, *p1, *p2;
+ register const char *env, *p1, *p2;
Tcl_DString envString;
Tcl_DStringInit(&envString);
@@ -998,230 +1027,52 @@ TclpFindVariable(name, lengthPtr)
*lengthPtr = i;
- done:
+ done:
Tcl_DStringFree(&envString);
return result;
}
-/*
- *----------------------------------------------------------------------
- *
- * TclpCheckStackSpace --
- *
- * Detect if we are about to blow the stack. Called before an
- * evaluation can happen when nesting depth is checked.
- *
- * Results:
- * 1 if there is enough stack space to continue; 0 if not.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpCheckStackSpace()
-{
-#ifdef TCL_NO_STACK_CHECK
-
- /*
- * This function was normally unimplemented on Unix platforms and
- * this implements old behavior, i.e. no stack checking performed.
- */
-
- return 1;
-
-#else
-
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- /* Most variables are actually in a
- * thread-specific data block to minimise the
- * impact on the stack. */
- register ptrdiff_t stackUsed;
- int localVar; /* Reference to somewhere on the local stack.
- * This is declared last so it's as "deep" as
- * possible. */
-
- if (tsdPtr == NULL) {
- /* this should probably be a panic(). */
- Tcl_Panic("failed to get thread specific stack check data");
- }
-
- /*
- * The first time through, we record the "outermost" stack frame.
- */
-
- if (tsdPtr->outerVarPtr == NULL) {
- tsdPtr->outerVarPtr = &localVar;
- }
-
- if (tsdPtr->initialised == 0) {
- /*
- * We appear to have not computed the stack size before.
- * Attempt to retrieve it from either the current thread or,
- * failing that, the process accounting limit. Note that we
- * assume that stack sizes do not change throughout the
- * lifespan of the thread/process; this is almost always true.
- */
-
- tsdPtr->stackDetermineResult = GetStackSize(&tsdPtr->stackSize);
- tsdPtr->initialised = 1;
- }
-
- switch (tsdPtr->stackDetermineResult) {
- case TCL_BREAK:
- STACK_DEBUG(("skipping stack check with failure\n"));
- return 0;
- case TCL_CONTINUE:
- STACK_DEBUG(("skipping stack check with success\n"));
- return 1;
- }
-
- /*
- * Sanity check to see if somehow the stack started going the
- * other way.
- */
-
- if (&localVar > tsdPtr->outerVarPtr) {
- stackUsed = (char *)&localVar - (char *)tsdPtr->outerVarPtr;
- } else {
- stackUsed = (char *)tsdPtr->outerVarPtr - (char *)&localVar;
- }
-
- /*
- * Now we perform the actual check. Are we about to blow
- * our stack frame?
- */
-
- if (stackUsed < (ptrdiff_t) tsdPtr->stackSize) {
- STACK_DEBUG(("stack OK\tin:%p\tout:%p\tuse:%04X\tmax:%04X\n",
- &localVar, tsdPtr->outerVarPtr, stackUsed, tsdPtr->stackSize));
- return 1;
- } else {
- STACK_DEBUG(("stack OVERFLOW\tin:%p\tout:%p\tuse:%04X\tmax:%04X\n",
- &localVar, tsdPtr->outerVarPtr, stackUsed, tsdPtr->stackSize));
- return 0;
- }
-#endif /* TCL_NO_STACK_CHECK */
-}
/*
*----------------------------------------------------------------------
*
- * GetStackSize --
+ * MacOSXGetLibraryPath --
*
- * 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.
+ * 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 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.
+ * TCL_OK if we have found the tcl library; TCL_ERROR otherwise.
*
* Side effects:
- * None
+ * Same as for Tcl_MacOSXOpenVersionedBundleResources.
*
*----------------------------------------------------------------------
*/
-#ifndef TCL_NO_STACK_CHECK
+#ifdef HAVE_COREFOUNDATION
static int
-GetStackSize(stackSizePtr)
- size_t *stackSizePtr;
+MacOSXGetLibraryPath(
+ Tcl_Interp *interp,
+ int maxPathLen,
+ char *tclLibPath)
{
- size_t rawStackSize;
- struct rlimit rLimit; /* The result from getrlimit(). */
-
-#ifdef TCL_THREADS
- rawStackSize = (size_t) TclpThreadGetStackSize();
- if (rawStackSize == (size_t) -1) {
- /*
- * Some kind of confirmed error?!
- */
- return TCL_BREAK;
- }
- 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.
- */
-#endif /* TCL_THREADS */
-
- if (getrlimit(RLIMIT_STACK, &rLimit) != 0) {
- /*
- * getrlimit() failed, just fail the whole thing.
- */
- return TCL_BREAK;
- }
- if (rLimit.rlim_cur == RLIM_INFINITY) {
- /*
- * Limit is "infinite"; there is no stack limit.
- */
- 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.
- */
+ int foundInFramework = TCL_ERROR;
-#ifdef TCL_THREADS /* Stop warning... */
- finalSanityCheck:
+#ifdef TCL_FRAMEWORK
+ foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
+ "com.tcltk.tcllibrary", TCL_FRAMEWORK_VERSION, 0, maxPathLen,
+ tclLibPath);
#endif
- if (rawStackSize <= 0) {
- 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 foundInFramework;
}
-#endif /* TCL_NO_STACK_CHECK */
+#endif /* HAVE_COREFOUNDATION */
/*
- *----------------------------------------------------------------------
- *
- * MacOSXGetLibraryPath --
- *
- * 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.
- *
- * Side effects:
- * Same as for Tcl_MacOSXOpenVersionedBundleResources.
- *
- *----------------------------------------------------------------------
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
*/
-
-#ifdef HAVE_CFBUNDLE
-static int
-MacOSXGetLibraryPath(Tcl_Interp *interp, int maxPathLen, char *tclLibPath)
-{
- int foundInFramework = TCL_ERROR;
- if (strcmp(defaultLibraryDir, "@TCL_IN_FRAMEWORK@") == 0) {
- foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
- "com.tcltk.tcllibrary", TCL_VERSION, 0, maxPathLen, tclLibPath);
- }
- return foundInFramework;
-}
-#endif /* HAVE_CFBUNDLE */