#if defined(HAVE_CFBUNDLE)
#include <CoreFoundation/CoreFoundation.h>
#endif
#define NO_UNAME
#include "Lang.h"
#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;
#if 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 /* __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"
},
{
"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 /* HAVE_CFBUNDLE */
void
TclpInitPlatform()
{
tclPlatform = TCL_PLATFORM_UNIX;
#ifdef SIGPIPE
(
void
)
signal
(SIGPIPE, SIG_IGN);
#endif /* SIGPIPE */
#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,
"lib/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) {
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) {
}
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);
}
{
#ifdef HAVE_CFBUNDLE
char
tclLibPath[MAXPATHLEN + 1];
if
(Tcl_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);
}
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 /* HAVE_LANGINFO */
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 /* HAVE_CFBUNDLE */
{
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_MacOSXOpenVersionedBundleResources(interp,
"com.tcltk.tcllibrary"
, TCL_VERSION, 0, maxPathLen, tclLibPath);
}
return
foundInFramework;
}
#endif /* HAVE_CFBUNDLE */