📄 tclwininit.c
字号:
/* * tclWinInit.c -- * * Contains the Windows-specific interpreter initialization functions. * * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * All rights reserved. * * RCS: @(#) $Id: tclWinInit.c,v 1.35 2002/02/08 02:52:55 dgp Exp $ */#include "tclWinInt.h"#include <winnt.h>#include <winbase.h>/* * The following declaration is a workaround for some Microsoft brain damage. * The SYSTEM_INFO structure is different in various releases, even though the * layout is the same. So we overlay our own structure on top of it so we * can access the interesting slots in a uniform way. */typedef struct { WORD wProcessorArchitecture; WORD wReserved;} OemId;/* * The following macros are missing from some versions of winnt.h. */#ifndef PROCESSOR_ARCHITECTURE_INTEL#define PROCESSOR_ARCHITECTURE_INTEL 0#endif#ifndef PROCESSOR_ARCHITECTURE_MIPS#define PROCESSOR_ARCHITECTURE_MIPS 1#endif#ifndef PROCESSOR_ARCHITECTURE_ALPHA#define PROCESSOR_ARCHITECTURE_ALPHA 2#endif#ifndef PROCESSOR_ARCHITECTURE_PPC#define PROCESSOR_ARCHITECTURE_PPC 3#endif#ifndef PROCESSOR_ARCHITECTURE_SHX #define PROCESSOR_ARCHITECTURE_SHX 4#endif#ifndef PROCESSOR_ARCHITECTURE_ARM#define PROCESSOR_ARCHITECTURE_ARM 5#endif#ifndef PROCESSOR_ARCHITECTURE_IA64#define PROCESSOR_ARCHITECTURE_IA64 6#endif#ifndef PROCESSOR_ARCHITECTURE_ALPHA64#define PROCESSOR_ARCHITECTURE_ALPHA64 7#endif#ifndef PROCESSOR_ARCHITECTURE_MSIL#define PROCESSOR_ARCHITECTURE_MSIL 8#endif#ifndef PROCESSOR_ARCHITECTURE_UNKNOWN#define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF#endif/* * The following arrays contain the human readable strings for the Windows * platform and processor values. */#define NUMPLATFORMS 3static char* platforms[NUMPLATFORMS] = { "Win32s", "Windows 95", "Windows NT"};#define NUMPROCESSORS 9static char* processors[NUMPROCESSORS] = { "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil"};/* 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;/* * The Init script (common to Windows and Unix platforms) is * defined in tkInitScript.h */#include "tclInitScript.h"static void AppendEnvironment(Tcl_Obj *listPtr, CONST char *lib);static void AppendDllPath(Tcl_Obj *listPtr, HMODULE hModule, CONST char *lib);static int ToUtf(CONST WCHAR *wSrc, char *dst);/* *--------------------------------------------------------------------------- * * TclpInitPlatform -- * * Initialize all the platform-dependant things like signals and * floating-point error handling. * * Called at process initialization time. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */voidTclpInitPlatform(){ tclPlatform = TCL_PLATFORM_WINDOWS; /* * The following code stops Windows 3.X and Windows NT 3.51 from * automatically putting up Sharing Violation dialogs, e.g, when * someone tries to access a file that is locked or a drive with no * disk in it. Tcl already returns the appropriate error to the * caller, and they can decide to put up their own dialog in response * to that failure. * * Under 95 and NT 4.0, this is a NOOP because the system doesn't * automatically put up dialogs when the above operations fail. */ SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS);#ifdef STATIC_BUILD /* * If we are in a statically linked executable, then we need to * explicitly initialize the Windows function tables here since * DllMain() will not be invoked. */ TclWinInit(GetModuleHandle(NULL));#endif}/* *--------------------------------------------------------------------------- * * TclpInitLibraryPath -- * * Initialize the library path at startup. * * This call sets the library path to strings in UTF-8. Any * pre-existing library path information is assumed to have been * in the native multibyte encoding. * * Called at process initialization time. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */voidTclpInitLibraryPath(path) CONST char *path; /* Potentially dirty UTF string that is */ /* the path to the executable name. */{#define LIBRARY_SIZE 32 Tcl_Obj *pathPtr, *objPtr; CONST char *str; Tcl_DString ds; int pathc; CONST char **pathv; char installLib[LIBRARY_SIZE], developLib[LIBRARY_SIZE];#ifdef __CYGWIN__ char installLib2[LIBRARY_SIZE];#endif 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. */ /* REDHAT LOCAL */ /* Due to cygwin standard practice, the tcl binary will be installed in /bin rather than /usr/bin. This means that, without this change, tcl will search in x:\share rather than x:\usr\share. */ /* sprintf(installLib, "lib/tcl%s", TCL_VERSION); */ sprintf(installLib, "share/tcl%s", TCL_VERSION);#ifdef __CYGWIN__ sprintf(installLib2, "usr/share/tcl%s", TCL_VERSION);#endif /* END REDHAT LOCAL */ 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. */ AppendEnvironment(pathPtr, installLib); /* * Look for the library relative to the DLL. Only use the installLib * because in practice, the DLL is always installed. */ AppendDllPath(pathPtr, TclWinGetTclInstance(), installLib); /* * 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) { 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); /* REDHAT LOCAL */#ifdef __CYGWIN__ pathv[pathc - 2] = installLib2; 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);#endif /* END REDHAT LOCAL */ } 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); } TclSetLibraryPath(pathPtr);}/* *--------------------------------------------------------------------------- * * AppendEnvironment -- * * Append the value of the TCL_LIBRARY environment variable onto the * path pointer. If the env variable points to another version of * tcl (e.g. "tcl7.6") also append the path to this version (e.g., * "tcl7.6/../tcl8.2") * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */static voidAppendEnvironment( Tcl_Obj *pathPtr, CONST char *lib){ int pathc; WCHAR wBuf[MAX_PATH]; char buf[MAX_PATH * TCL_UTF_MAX]; Tcl_Obj *objPtr; Tcl_DString ds; CONST char **pathv; /* * The "L" preceeding the TCL_LIBRARY string is used to tell VC++ * that this is a unicode string. */ if (GetEnvironmentVariableW(L"TCL_LIBRARY", wBuf, MAX_PATH) == 0) { buf[0] = '\0'; GetEnvironmentVariableA("TCL_LIBRARY", buf, MAX_PATH); } else { ToUtf(wBuf, buf); } if (buf[0] != '\0') { objPtr = Tcl_NewStringObj(buf, -1); Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); TclWinNoBackslash(buf); Tcl_SplitPath(buf, &pathc, &pathv); /* * The lstrcmpi() will work even if pathv[pathc - 1] is random * UTF-8 chars because I know lib is ascii. */ if ((pathc > 0) && (lstrcmpiA(lib + 4, pathv[pathc - 1]) != 0)) { CONST char *str; /* * 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. */ pathv[pathc - 1] = (lib + 4); Tcl_DStringInit(&ds); str = Tcl_JoinPath(pathc, pathv, &ds); objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&ds)); Tcl_DStringFree(&ds); } else { objPtr = Tcl_NewStringObj(buf, -1); } Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); ckfree((char *) pathv); }}/* *--------------------------------------------------------------------------- * * AppendDllPath -- * * Append a path onto the path pointer that tries to locate the Tcl * library relative to the location of the Tcl DLL. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */static void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -