#if defined(HAVE_CFBUNDLE)
#include <CoreFoundation/CoreFoundation.h>
#endif
#include "tclInt.h"
#include "tclPort.h"
#include <locale.h>
#ifdef HAVE_LANGINFO
#include <langinfo.h>
#endif
#if defined(__FreeBSD__)
# include <floatingpoint.h>
#endif
#if defined(__bsdi__)
# include <sys/param.h>
# if _BSDI_VERSION > 199501
# include <dlfcn.h>
# endif
#endif
#include "tclInitScript.h"
static Tcl_Encoding binaryEncoding = NULL;
static int libraryPathEncodingFixed = 0;
#ifndef TCL_DEFAULT_ENCODING
#define TCL_DEFAULT_ENCODING "iso8859-1"
#endif
static char defaultLibraryDir[sizeof(TCL_LIBRARY)+200] = TCL_LIBRARY;
static char pkgPath[sizeof(TCL_PACKAGE_PATH)+200] = TCL_PACKAGE_PATH;
typedef struct LocaleTable {
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
#endif
{"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"},
{"ja", "shiftjis"},
#else
{"japanese", "euc-jp"},
{"ja", "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"},
{NULL, NULL}
};
#ifdef HAVE_CFBUNDLE
static int Tcl_MacOSXGetLibraryPath(Tcl_Interp *interp, int maxPathLen, char *tclLibPath);
#endif
void
TclpInitPlatform()
{
tclPlatform = TCL_PLATFORM_UNIX;
#ifdef SIGPIPE
(void) signal(SIGPIPE, SIG_IGN);
#endif
#ifdef __FreeBSD__
fpsetround(FP_RN);
fpsetmask(0L);
#endif
#if defined(__bsdi__) && (_BSDI_VERSION > 199501)
(void) dlopen (NULL, RTLD_NOW);
#endif
}
void
TclpInitLibraryPath(path)
CONST char *path;
{
#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];
Tcl_DStringInit(&ds);
pathPtr = Tcl_NewObj();
sprintf(installLib, "share/tcl%s", TCL_VERSION);
sprintf(developLib, "tcl%s/library", TCL_PATCH_LEVEL);
str = Tcl_GetDefaultEncodingDir();
if ((str != NULL) && (str[0] != '\0')) {
objPtr = Tcl_NewStringObj(str, -1);
Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
}
str = getenv("TCL_LIBRARY");
Tcl_ExternalToUtfDString(NULL, str, -1, &buffer);
str = Tcl_DStringValue(&buffer);
if ((str != NULL) && (str[0] != '\0')) {
objPtr = Tcl_NewStringObj(str, -1);
Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
Tcl_SplitPath(str, &pathc, &pathv);
if ((pathc > 0) && (strcasecmp(installLib + 4, pathv[pathc-1]) != 0)) {
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);
}
ckfree((char *) pathv);
}
if (path != NULL) {
Tcl_SplitPath(path, &pathc, &pathv);
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 *) pathv);
}
{
#ifdef HAVE_CFBUNDLE
char tclLibPath[MAXPATHLEN + 1];
if (Tcl_MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
str = tclLibPath;
} else
#endif
{
str = defaultLibraryDir;
}
if (str[0] != '\0') {
objPtr = Tcl_NewStringObj(str, -1);
Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
}
}
TclSetLibraryPath(pathPtr);
Tcl_DStringFree(&buffer);
}
void
TclpSetInitialEncodings()
{
if (libraryPathEncodingFixed == 0) {
CONST char *encoding = NULL;
int i, setSysEncCode = TCL_ERROR;
Tcl_Obj *pathPtr;
#ifdef HAVE_LANGINFO
if (setlocale(LC_CTYPE, "") != NULL) {
Tcl_DString ds;
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;
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;
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")) {
encoding = "iso8859-1";
}
#ifdef HAVE_LANGINFO_DEBUG
fprintf(stderr, " ?%s?", encoding);
#endif
setSysEncCode = Tcl_SetSystemEncoding(NULL, encoding);
if (setSysEncCode != TCL_OK) {
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);
}
#ifdef HAVE_LANGINFO_DEBUG
else {
fprintf(stderr, "setlocale returned NULL\n");
}
#endif
#endif
if (setSysEncCode != TCL_OK) {
char *langEnv = getenv("LC_ALL");
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 (langEnv != NULL) {
for (i = 0; localeTable[i].lang != NULL; i++) {
if (strcmp(localeTable[i].lang, langEnv) == 0) {
encoding = localeTable[i].encoding;
break;
}
}
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_SetSystemEncoding(NULL, encoding);
}
#ifndef HAVE_LANGINFO
setlocale(LC_CTYPE, "");
#endif
}
setlocale(LC_NUMERIC, "C");
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);
}
}
libraryPathEncodingFixed = 1;
}
if (binaryEncoding == NULL) {
binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");
}
}
void
TclpSetVariables(interp)
Tcl_Interp *interp;
{
#ifndef NO_UNAME
struct utsname name;
#endif
int unameOK;
CONST char *user;
Tcl_DString ds;
#ifdef HAVE_CFBUNDLE
char tclLibPath[MAXPATHLEN + 1];
if (Tcl_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);
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);
} else
#endif
{
Tcl_SetVar(interp, "tclDefaultLibrary", defaultLibraryDir,
TCL_GLOBAL_ONLY);
Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
}
#ifdef DJGPP
Tcl_SetVar2(interp, "tcl_platform", "platform", "dos", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "tcl_platform", "platform", "unix", TCL_GLOBAL_ONLY);
#endif
unameOK = 0;
#ifndef 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);
if ((strchr(name.release, '.') != NULL)
|| !isdigit(UCHAR(name.version[0]))) {
Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
TCL_GLOBAL_ONLY);
} 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);
}
Tcl_SetVar2(interp, "tcl_platform", "machine", name.machine,
TCL_GLOBAL_ONLY);
}
#endif
if (!unameOK) {
Tcl_SetVar2(interp, "tcl_platform", "os", "", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "tcl_platform", "osVersion", "", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "tcl_platform", "machine", "", TCL_GLOBAL_ONLY);
}
Tcl_DStringInit(&ds);
user = TclGetEnv("USER", &ds);
if (user == NULL) {
user = TclGetEnv("LOGNAME", &ds);
if (user == NULL) {
user = "";
}
}
Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
Tcl_DStringFree(&ds);
}
int
TclpFindVariable(name, lengthPtr)
CONST char *name;
int *lengthPtr;
{
int i, result = -1;
register CONST char *env, *p1, *p2;
Tcl_DString envString;
Tcl_DStringInit(&envString);
for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) {
p1 = Tcl_ExternalToUtfDString(NULL, env, -1, &envString);
p2 = name;
for (; *p2 == *p1; p1++, p2++) {
}
if ((*p1 == '=') && (*p2 == '\0')) {
*lengthPtr = p2 - name;
result = i;
goto done;
}
Tcl_DStringFree(&envString);
}
*lengthPtr = i;
done:
Tcl_DStringFree(&envString);
return result;
}
int
Tcl_Init(interp)
Tcl_Interp *interp;
{
Tcl_Obj *pathPtr;
if (tclPreInitScript != NULL) {
if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
return (TCL_ERROR);
};
}
pathPtr = TclGetLibraryPath();
if (pathPtr == NULL) {
pathPtr = Tcl_NewObj();
}
Tcl_SetVar2Ex(interp, "tcl_libPath", NULL, pathPtr, TCL_GLOBAL_ONLY);
return Tcl_Eval(interp, initScript);
}
void
Tcl_SourceRCFile(interp)
Tcl_Interp *interp;
{
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;
Tcl_DStringInit(&temp);
fullName = Tcl_TranslateFileName(interp, fileName, &temp);
if (fullName == NULL) {
} else {
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);
}
}
int
TclpCheckStackSpace()
{
return 1;
}
#ifdef HAVE_CFBUNDLE
static int Tcl_MacOSXGetLibraryPath(Tcl_Interp *interp, int maxPathLen, char *tclLibPath)
{
int foundInFramework = TCL_ERROR;
if (strcmp(defaultLibraryDir, "@TCL_IN_FRAMEWORK@") == 0) {
foundInFramework = Tcl_MacOSXOpenBundleResources(interp,
"com.tcltk.tcllibrary", 0, maxPathLen, tclLibPath);
}
return foundInFramework;
}
#endif