tclWinInit.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:24k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tclWinInit.c --
  3.  *
  4.  * Contains the Windows-specific interpreter initialization functions.
  5.  *
  6.  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
  7.  * Copyright (c) 1998-1999 by Scriptics Corporation.
  8.  * All rights reserved.
  9.  *
  10.  * RCS: @(#) $Id: tclWinInit.c,v 1.40.2.6 2005/10/23 22:01:31 msofer Exp $
  11.  */
  12. #include "tclWinInt.h"
  13. #include <winnt.h>
  14. #include <winbase.h>
  15. #include <lmcons.h>
  16. /*
  17.  * The following declaration is a workaround for some Microsoft brain damage.
  18.  * The SYSTEM_INFO structure is different in various releases, even though the
  19.  * layout is the same.  So we overlay our own structure on top of it so we
  20.  * can access the interesting slots in a uniform way.
  21.  */
  22. typedef struct {
  23.     WORD wProcessorArchitecture;
  24.     WORD wReserved;
  25. } OemId;
  26. /*
  27.  * The following macros are missing from some versions of winnt.h.
  28.  */
  29. #ifndef PROCESSOR_ARCHITECTURE_INTEL
  30. #define PROCESSOR_ARCHITECTURE_INTEL 0
  31. #endif
  32. #ifndef PROCESSOR_ARCHITECTURE_MIPS
  33. #define PROCESSOR_ARCHITECTURE_MIPS  1
  34. #endif
  35. #ifndef PROCESSOR_ARCHITECTURE_ALPHA
  36. #define PROCESSOR_ARCHITECTURE_ALPHA 2
  37. #endif
  38. #ifndef PROCESSOR_ARCHITECTURE_PPC
  39. #define PROCESSOR_ARCHITECTURE_PPC   3
  40. #endif
  41. #ifndef PROCESSOR_ARCHITECTURE_SHX  
  42. #define PROCESSOR_ARCHITECTURE_SHX   4
  43. #endif
  44. #ifndef PROCESSOR_ARCHITECTURE_ARM
  45. #define PROCESSOR_ARCHITECTURE_ARM   5
  46. #endif
  47. #ifndef PROCESSOR_ARCHITECTURE_IA64
  48. #define PROCESSOR_ARCHITECTURE_IA64  6
  49. #endif
  50. #ifndef PROCESSOR_ARCHITECTURE_ALPHA64
  51. #define PROCESSOR_ARCHITECTURE_ALPHA64 7
  52. #endif
  53. #ifndef PROCESSOR_ARCHITECTURE_MSIL
  54. #define PROCESSOR_ARCHITECTURE_MSIL  8
  55. #endif
  56. #ifndef PROCESSOR_ARCHITECTURE_AMD64
  57. #define PROCESSOR_ARCHITECTURE_AMD64 9
  58. #endif
  59. #ifndef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
  60. #define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10
  61. #endif
  62. #ifndef PROCESSOR_ARCHITECTURE_UNKNOWN
  63. #define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF
  64. #endif
  65. /*
  66.  * The following arrays contain the human readable strings for the Windows
  67.  * platform and processor values.
  68.  */
  69. #define NUMPLATFORMS 4
  70. static char* platforms[NUMPLATFORMS] = {
  71.     "Win32s", "Windows 95", "Windows NT", "Windows CE"
  72. };
  73. #define NUMPROCESSORS 11
  74. static char* processors[NUMPROCESSORS] = {
  75.     "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
  76.     "amd64", "ia32_on_win64"
  77. };
  78. /* Used to store the encoding used for binary files */
  79. static Tcl_Encoding binaryEncoding = NULL;
  80. /* Has the basic library path encoding issue been fixed */
  81. static int libraryPathEncodingFixed = 0;
  82. /*
  83.  * The Init script (common to Windows and Unix platforms) is
  84.  * defined in tkInitScript.h
  85.  */
  86. #include "tclInitScript.h"
  87. static void AppendEnvironment(Tcl_Obj *listPtr, CONST char *lib);
  88. static void AppendDllPath(Tcl_Obj *listPtr, HMODULE hModule,
  89.     CONST char *lib);
  90. static int ToUtf(CONST WCHAR *wSrc, char *dst);
  91. /*
  92.  *---------------------------------------------------------------------------
  93.  *
  94.  * TclpInitPlatform --
  95.  *
  96.  * Initialize all the platform-dependant things like signals and
  97.  * floating-point error handling.
  98.  *
  99.  * Called at process initialization time.
  100.  *
  101.  * Results:
  102.  * None.
  103.  *
  104.  * Side effects:
  105.  * None.
  106.  *
  107.  *---------------------------------------------------------------------------
  108.  */
  109. void
  110. TclpInitPlatform()
  111. {
  112.     tclPlatform = TCL_PLATFORM_WINDOWS;
  113.     /*
  114.      * The following code stops Windows 3.X and Windows NT 3.51 from 
  115.      * automatically putting up Sharing Violation dialogs, e.g, when 
  116.      * someone tries to access a file that is locked or a drive with no 
  117.      * disk in it.  Tcl already returns the appropriate error to the 
  118.      * caller, and they can decide to put up their own dialog in response 
  119.      * to that failure.  
  120.      *
  121.      * Under 95 and NT 4.0, this is a NOOP because the system doesn't 
  122.      * automatically put up dialogs when the above operations fail.
  123.      */
  124.     SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS);
  125. #ifdef STATIC_BUILD
  126.     /*
  127.      * If we are in a statically linked executable, then we need to
  128.      * explicitly initialize the Windows function tables here since
  129.      * DllMain() will not be invoked.
  130.      */
  131.     TclWinInit(GetModuleHandle(NULL));
  132. #endif
  133. }
  134. /*
  135.  *---------------------------------------------------------------------------
  136.  *
  137.  * TclpInitLibraryPath --
  138.  *
  139.  * Initialize the library path at startup.  
  140.  *
  141.  * This call sets the library path to strings in UTF-8. Any 
  142.  * pre-existing library path information is assumed to have been 
  143.  * in the native multibyte encoding.
  144.  *
  145.  * Called at process initialization time.
  146.  *
  147.  * Results:
  148.  * Return 0, indicating that the UTF is clean.
  149.  *
  150.  * Side effects:
  151.  * None.
  152.  *
  153.  *---------------------------------------------------------------------------
  154.  */
  155. int
  156. TclpInitLibraryPath(path)
  157.     CONST char *path; /* Potentially dirty UTF string that is */
  158. /* the path to the executable name.     */
  159. {
  160. #define LIBRARY_SIZE     32
  161.     Tcl_Obj *pathPtr, *objPtr;
  162.     CONST char *str;
  163.     Tcl_DString ds;
  164.     int pathc;
  165.     CONST char **pathv;
  166.     char installLib[LIBRARY_SIZE], developLib[LIBRARY_SIZE];
  167.     Tcl_DStringInit(&ds);
  168.     pathPtr = Tcl_NewObj();
  169.     /*
  170.      * Initialize the substrings used when locating an executable.  The
  171.      * installLib variable computes the path as though the executable
  172.      * is installed.  The developLib computes the path as though the
  173.      * executable is run from a develpment directory.
  174.      */
  175.     sprintf(installLib, "lib/tcl%s", TCL_VERSION);
  176.     sprintf(developLib, "tcl%s/library", TCL_PATCH_LEVEL);
  177.     /*
  178.      * Look for the library relative to default encoding dir.
  179.      */
  180.     str = Tcl_GetDefaultEncodingDir();
  181.     if ((str != NULL) && (str[0] != '')) {
  182. objPtr = Tcl_NewStringObj(str, -1);
  183. Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
  184.     }
  185.     /*
  186.      * Look for the library relative to the TCL_LIBRARY env variable.
  187.      * If the last dirname in the TCL_LIBRARY path does not match the
  188.      * last dirname in the installLib variable, use the last dir name
  189.      * of installLib in addition to the orginal TCL_LIBRARY path.
  190.      */
  191.     AppendEnvironment(pathPtr, installLib);
  192.     /*
  193.      * Look for the library relative to the DLL.  Only use the installLib
  194.      * because in practice, the DLL is always installed.
  195.      */
  196.     AppendDllPath(pathPtr, TclWinGetTclInstance(), installLib);
  197.     
  198.     /*
  199.      * Look for the library relative to the executable.  This algorithm
  200.      * should be the same as the one in the tcl_findLibrary procedure.
  201.      *
  202.      * This code looks in the following directories:
  203.      *
  204.      * <bindir>/../<installLib>
  205.      *   (e.g. /usr/local/bin/../lib/tcl8.4)
  206.      * <bindir>/../../<installLib>
  207.      *    (e.g. /usr/local/TclPro/solaris-sparc/bin/../../lib/tcl8.4)
  208.      * <bindir>/../library
  209.      *    (e.g. /usr/src/tcl8.4.0/unix/../library)
  210.      * <bindir>/../../library
  211.      *   (e.g. /usr/src/tcl8.4.0/unix/solaris-sparc/../../library)
  212.      * <bindir>/../../<developLib>
  213.      *   (e.g. /usr/src/tcl8.4.0/unix/../../tcl8.4.0/library)
  214.      * <bindir>/../../../<developLib>
  215.      *    (e.g. /usr/src/tcl8.4.0/unix/solaris-sparc/../../../tcl8.4.0/library)
  216.      */
  217.      
  218.     /*
  219.      * The variable path holds an absolute path.  Take care not to
  220.      * overwrite pathv[0] since that might produce a relative path.
  221.      */
  222.     if (path != NULL) {
  223. int i, origc;
  224. CONST char **origv;
  225. Tcl_SplitPath(path, &origc, &origv);
  226. pathc = 0;
  227. pathv = (CONST char **) ckalloc((unsigned int)(origc * sizeof(char *)));
  228. for (i=0; i< origc; i++) {
  229.     if (origv[i][0] == '.') {
  230. if (strcmp(origv[i], ".") == 0) {
  231.     /* do nothing */
  232. } else if (strcmp(origv[i], "..") == 0) {
  233.     pathc--;
  234. } else {
  235.     pathv[pathc++] = origv[i];
  236. }
  237.     } else {
  238. pathv[pathc++] = origv[i];
  239.     }
  240. }
  241. if (pathc > 2) {
  242.     str = pathv[pathc - 2];
  243.     pathv[pathc - 2] = installLib;
  244.     path = Tcl_JoinPath(pathc - 1, pathv, &ds);
  245.     pathv[pathc - 2] = str;
  246.     objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
  247.     Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
  248.     Tcl_DStringFree(&ds);
  249. }
  250. if (pathc > 3) {
  251.     str = pathv[pathc - 3];
  252.     pathv[pathc - 3] = installLib;
  253.     path = Tcl_JoinPath(pathc - 2, pathv, &ds);
  254.     pathv[pathc - 3] = str;
  255.     objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
  256.     Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
  257.     Tcl_DStringFree(&ds);
  258. }
  259. if (pathc > 2) {
  260.     str = pathv[pathc - 2];
  261.     pathv[pathc - 2] = "library";
  262.     path = Tcl_JoinPath(pathc - 1, pathv, &ds);
  263.     pathv[pathc - 2] = str;
  264.     objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
  265.     Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
  266.     Tcl_DStringFree(&ds);
  267. }
  268. if (pathc > 3) {
  269.     str = pathv[pathc - 3];
  270.     pathv[pathc - 3] = "library";
  271.     path = Tcl_JoinPath(pathc - 2, pathv, &ds);
  272.     pathv[pathc - 3] = str;
  273.     objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
  274.     Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
  275.     Tcl_DStringFree(&ds);
  276. }
  277. if (pathc > 3) {
  278.     str = pathv[pathc - 3];
  279.     pathv[pathc - 3] = developLib;
  280.     path = Tcl_JoinPath(pathc - 2, pathv, &ds);
  281.     pathv[pathc - 3] = str;
  282.     objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
  283.     Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
  284.     Tcl_DStringFree(&ds);
  285. }
  286. if (pathc > 4) {
  287.     str = pathv[pathc - 4];
  288.     pathv[pathc - 4] = developLib;
  289.     path = Tcl_JoinPath(pathc - 3, pathv, &ds);
  290.     pathv[pathc - 4] = str;
  291.     objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
  292.     Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
  293.     Tcl_DStringFree(&ds);
  294. }
  295. ckfree((char *) origv);
  296. ckfree((char *) pathv);
  297.     }
  298.     TclSetLibraryPath(pathPtr);
  299.     return 0; /* 0 indicates that pathPtr is clean (true) utf */
  300. }
  301. /*
  302.  *---------------------------------------------------------------------------
  303.  *
  304.  * AppendEnvironment --
  305.  *
  306.  * Append the value of the TCL_LIBRARY environment variable onto the
  307.  * path pointer.  If the env variable points to another version of
  308.  * tcl (e.g. "tcl7.6") also append the path to this version (e.g.,
  309.  * "tcl7.6/../tcl8.2")
  310.  *
  311.  * Results:
  312.  * None.
  313.  *
  314.  * Side effects:
  315.  * None.
  316.  *
  317.  *---------------------------------------------------------------------------
  318.  */
  319. static void
  320. AppendEnvironment(
  321.     Tcl_Obj *pathPtr,
  322.     CONST char *lib)
  323. {
  324.     int pathc;
  325.     WCHAR wBuf[MAX_PATH];
  326.     char buf[MAX_PATH * TCL_UTF_MAX];
  327.     Tcl_Obj *objPtr;
  328.     Tcl_DString ds;
  329.     CONST char **pathv;
  330.     char *shortlib;
  331.     /*
  332.      * The shortlib value needs to be the tail component of the
  333.      * lib path. For example, "lib/tcl8.4" -> "tcl8.4" while
  334.      * "usr/share/tcl8.5" -> "tcl8.5".
  335.      */
  336.     for (shortlib = (char *) (lib + strlen(lib) - 1); shortlib > lib ; shortlib--) {
  337.         if (*shortlib == '/') { 
  338.             if (shortlib == (lib + strlen(lib) - 1)) {
  339.                 Tcl_Panic("last character in lib cannot be '/'");
  340.             }
  341.             shortlib++;
  342.             break;
  343.         }
  344.     }
  345.     if (shortlib == lib) {
  346.         Tcl_Panic("no '/' character found in lib");
  347.     }
  348.     /*
  349.      * The "L" preceeding the TCL_LIBRARY string is used to tell VC++
  350.      * that this is a unicode string.
  351.      */
  352.     
  353.     if (GetEnvironmentVariableW(L"TCL_LIBRARY", wBuf, MAX_PATH) == 0) {
  354.         buf[0] = '';
  355. GetEnvironmentVariableA("TCL_LIBRARY", buf, MAX_PATH);
  356.     } else {
  357. ToUtf(wBuf, buf);
  358.     }
  359.     if (buf[0] != '') {
  360. objPtr = Tcl_NewStringObj(buf, -1);
  361. Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
  362. TclWinNoBackslash(buf);
  363. Tcl_SplitPath(buf, &pathc, &pathv);
  364. /* 
  365.  * The lstrcmpi() will work even if pathv[pathc - 1] is random
  366.  * UTF-8 chars because I know shortlib is ascii.
  367.  */
  368. if ((pathc > 0) && (lstrcmpiA(shortlib, pathv[pathc - 1]) != 0)) {
  369.     CONST char *str;
  370.     /*
  371.      * TCL_LIBRARY is set but refers to a different tcl
  372.      * installation than the current version.  Try fiddling with the
  373.      * specified directory to make it refer to this installation by
  374.      * removing the old "tclX.Y" and substituting the current
  375.      * version string.
  376.      */
  377.     
  378.     pathv[pathc - 1] = shortlib;
  379.     Tcl_DStringInit(&ds);
  380.     str = Tcl_JoinPath(pathc, pathv, &ds);
  381.     objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&ds));
  382.     Tcl_DStringFree(&ds);
  383. } else {
  384.     objPtr = Tcl_NewStringObj(buf, -1);
  385. }
  386. Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
  387. ckfree((char *) pathv);
  388.     }
  389. }
  390. /*
  391.  *---------------------------------------------------------------------------
  392.  *
  393.  * AppendDllPath --
  394.  *
  395.  * Append a path onto the path pointer that tries to locate the Tcl
  396.  * library relative to the location of the Tcl DLL.
  397.  *
  398.  * Results:
  399.  * None.
  400.  *
  401.  * Side effects:
  402.  * None.
  403.  *
  404.  *---------------------------------------------------------------------------
  405.  */
  406. static void 
  407. AppendDllPath(
  408.     Tcl_Obj *pathPtr, 
  409.     HMODULE hModule,
  410.     CONST char *lib)
  411. {
  412.     WCHAR wName[MAX_PATH + LIBRARY_SIZE];
  413.     char name[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX];
  414.     if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) {
  415. GetModuleFileNameA(hModule, name, MAX_PATH);
  416.     } else {
  417. ToUtf(wName, name);
  418.     }
  419.     if (lib != NULL) {
  420. char *end, *p;
  421. end = strrchr(name, '\');
  422. *end = '';
  423. p = strrchr(name, '\');
  424. if (p != NULL) {
  425.     end = p;
  426. }
  427. *end = '\';
  428. strcpy(end + 1, lib);
  429.     }
  430.     TclWinNoBackslash(name);
  431.     Tcl_ListObjAppendElement(NULL, pathPtr, Tcl_NewStringObj(name, -1));
  432. }
  433. /*
  434.  *---------------------------------------------------------------------------
  435.  *
  436.  * ToUtf --
  437.  *
  438.  * Convert a char string to a UTF string.  
  439.  *
  440.  * Results:
  441.  * None.
  442.  *
  443.  * Side effects:
  444.  * None.
  445.  *
  446.  *---------------------------------------------------------------------------
  447.  */
  448. static int
  449. ToUtf(
  450.     CONST WCHAR *wSrc,
  451.     char *dst)
  452. {
  453.     char *start;
  454.     start = dst;
  455.     while (*wSrc != '') {
  456. dst += Tcl_UniCharToUtf(*wSrc, dst);
  457. wSrc++;
  458.     }
  459.     *dst = '';
  460.     return (int) (dst - start);
  461. }
  462. /*
  463.  *---------------------------------------------------------------------------
  464.  *
  465.  * TclWinEncodingsCleanup --
  466.  *
  467.  * Reset information to its original state in finalization to
  468.  * allow for reinitialization to be possible.  This must not
  469.  * be called until after the filesystem has been finalised, or
  470.  * exit crashes may occur when using virtual filesystems.
  471.  *
  472.  * Results:
  473.  * None.
  474.  *
  475.  * Side effects:
  476.  * Static information reset to startup state.
  477.  *
  478.  *---------------------------------------------------------------------------
  479.  */
  480. void
  481. TclWinEncodingsCleanup()
  482. {
  483.     TclWinResetInterfaceEncodings();
  484.     libraryPathEncodingFixed = 0;
  485.     if (binaryEncoding != NULL) {
  486. Tcl_FreeEncoding(binaryEncoding);
  487. binaryEncoding = NULL;
  488.     }
  489. }
  490. /*
  491.  *---------------------------------------------------------------------------
  492.  *
  493.  * TclpSetInitialEncodings --
  494.  *
  495.  * Based on the locale, determine the encoding of the operating
  496.  * system and the default encoding for newly opened files.
  497.  *
  498.  * Called at process initialization time, and part way through
  499.  * startup, we verify that the initial encodings were correctly
  500.  * setup.  Depending on Tcl's environment, there may not have been
  501.  * enough information first time through (above).
  502.  *
  503.  * Results:
  504.  * None.
  505.  *
  506.  * Side effects:
  507.  * The Tcl library path is converted from native encoding to UTF-8,
  508.  * on the first call, and the encodings may be changed on first or
  509.  * second call.
  510.  *
  511.  *---------------------------------------------------------------------------
  512.  */
  513. void
  514. TclpSetInitialEncodings()
  515. {
  516.     CONST char *encoding;
  517.     char buf[4 + TCL_INTEGER_SPACE];
  518.     if (libraryPathEncodingFixed == 0) {
  519. int platformId, useWide;
  520. platformId = TclWinGetPlatformId();
  521. useWide = ((platformId == VER_PLATFORM_WIN32_NT)
  522. || (platformId == VER_PLATFORM_WIN32_CE));
  523. TclWinSetInterfaces(useWide);
  524. wsprintfA(buf, "cp%d", GetACP());
  525. Tcl_SetSystemEncoding(NULL, buf);
  526. if (!useWide) {
  527.     Tcl_Obj *pathPtr = TclGetLibraryPath();
  528.     if (pathPtr != NULL) {
  529. int i, objc;
  530. Tcl_Obj **objv;
  531. objc = 0;
  532. Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv);
  533. for (i = 0; i < objc; i++) {
  534.     int length;
  535.     char *string;
  536.     Tcl_DString ds;
  537.     string = Tcl_GetStringFromObj(objv[i], &length);
  538.     Tcl_ExternalToUtfDString(NULL, string, length, &ds);
  539.     Tcl_SetStringObj(objv[i], Tcl_DStringValue(&ds), 
  540.     Tcl_DStringLength(&ds));
  541.     Tcl_DStringFree(&ds);
  542. }
  543.     }
  544. }
  545. libraryPathEncodingFixed = 1;
  546.     } else {
  547. wsprintfA(buf, "cp%d", GetACP());
  548. Tcl_SetSystemEncoding(NULL, buf);
  549.     }
  550.     /* This is only ever called from the startup thread */
  551.     if (binaryEncoding == NULL) {
  552. /*
  553.  * Keep this encoding preloaded.  The IO package uses it for
  554.  * gets on a binary channel.
  555.  */
  556. encoding = "iso8859-1";
  557. binaryEncoding = Tcl_GetEncoding(NULL, encoding);
  558.     }
  559. }
  560. /*
  561.  *---------------------------------------------------------------------------
  562.  *
  563.  * TclpSetVariables --
  564.  *
  565.  * Performs platform-specific interpreter initialization related to
  566.  * the tcl_platform and env variables, and other platform-specific
  567.  * things.
  568.  *
  569.  * Results:
  570.  * None.
  571.  *
  572.  * Side effects:
  573.  * Sets "tcl_platform", and "env(HOME)" Tcl variables.
  574.  *
  575.  *----------------------------------------------------------------------
  576.  */
  577. void
  578. TclpSetVariables(interp)
  579.     Tcl_Interp *interp; /* Interp to initialize. */
  580. {     
  581.     CONST char *ptr;
  582.     char buffer[TCL_INTEGER_SPACE * 2];
  583.     SYSTEM_INFO sysInfo;
  584.     OemId *oemId;
  585.     OSVERSIONINFOA osInfo;
  586.     Tcl_DString ds;
  587.     TCHAR szUserName[ UNLEN+1 ];
  588.     DWORD dwUserNameLen = sizeof(szUserName);
  589.     osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  590.     GetVersionExA(&osInfo);
  591.     oemId = (OemId *) &sysInfo;
  592.     GetSystemInfo(&sysInfo);
  593.     /*
  594.      * Define the tcl_platform array.
  595.      */
  596.     Tcl_SetVar2(interp, "tcl_platform", "platform", "windows",
  597.     TCL_GLOBAL_ONLY);
  598.     if (osInfo.dwPlatformId < NUMPLATFORMS) {
  599. Tcl_SetVar2(interp, "tcl_platform", "os",
  600. platforms[osInfo.dwPlatformId], TCL_GLOBAL_ONLY);
  601.     }
  602.     wsprintfA(buffer, "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
  603.     Tcl_SetVar2(interp, "tcl_platform", "osVersion", buffer, TCL_GLOBAL_ONLY);
  604.     if (oemId->wProcessorArchitecture < NUMPROCESSORS) {
  605. Tcl_SetVar2(interp, "tcl_platform", "machine",
  606. processors[oemId->wProcessorArchitecture],
  607. TCL_GLOBAL_ONLY);
  608.     }
  609. #ifdef _DEBUG
  610.     /*
  611.      * The existence of the "debug" element of the tcl_platform array indicates
  612.      * that this particular Tcl shell has been compiled with debug information.
  613.      * Using "info exists tcl_platform(debug)" a Tcl script can direct the 
  614.      * interpreter to load debug versions of DLLs with the load command.
  615.      */
  616.     Tcl_SetVar2(interp, "tcl_platform", "debug", "1",
  617.     TCL_GLOBAL_ONLY);
  618. #endif
  619.     /*
  620.      * Set up the HOME environment variable from the HOMEDRIVE & HOMEPATH
  621.      * environment variables, if necessary.
  622.      */
  623.     Tcl_DStringInit(&ds);
  624.     ptr = Tcl_GetVar2(interp, "env", "HOME", TCL_GLOBAL_ONLY);
  625.     if (ptr == NULL) {
  626. ptr = Tcl_GetVar2(interp, "env", "HOMEDRIVE", TCL_GLOBAL_ONLY);
  627. if (ptr != NULL) {
  628.     Tcl_DStringAppend(&ds, ptr, -1);
  629. }
  630. ptr = Tcl_GetVar2(interp, "env", "HOMEPATH", TCL_GLOBAL_ONLY);
  631. if (ptr != NULL) {
  632.     Tcl_DStringAppend(&ds, ptr, -1);
  633. }
  634. if (Tcl_DStringLength(&ds) > 0) {
  635.     Tcl_SetVar2(interp, "env", "HOME", Tcl_DStringValue(&ds),
  636.     TCL_GLOBAL_ONLY);
  637. } else {
  638.     Tcl_SetVar2(interp, "env", "HOME", "c:\", TCL_GLOBAL_ONLY);
  639. }
  640.     }
  641.     /*
  642.      * Initialize the user name from the environment first, since this is much
  643.      * faster than asking the system.
  644.      */
  645.     Tcl_DStringInit( &ds );
  646.     if (TclGetEnv("USERNAME", &ds) == NULL) {
  647. if ( GetUserName( szUserName, &dwUserNameLen ) != 0 ) {
  648.     Tcl_WinTCharToUtf( szUserName, dwUserNameLen, &ds );
  649. }
  650.     }
  651.     Tcl_SetVar2(interp, "tcl_platform", "user", Tcl_DStringValue(&ds),
  652.     TCL_GLOBAL_ONLY);
  653.     Tcl_DStringFree(&ds);
  654. }
  655. /*
  656.  *----------------------------------------------------------------------
  657.  *
  658.  * TclpFindVariable --
  659.  *
  660.  * Locate the entry in environ for a given name.  On Unix this 
  661.  * routine is case sensetive, on Windows this matches mioxed case.
  662.  *
  663.  * Results:
  664.  * The return value is the index in environ of an entry with the
  665.  * name "name", or -1 if there is no such entry.   The integer at
  666.  * *lengthPtr is filled in with the length of name (if a matching
  667.  * entry is found) or the length of the environ array (if no matching
  668.  * entry is found).
  669.  *
  670.  * Side effects:
  671.  * None.
  672.  *
  673.  *----------------------------------------------------------------------
  674.  */
  675. int
  676. TclpFindVariable(name, lengthPtr)
  677.     CONST char *name; /* Name of desired environment variable
  678.  * (UTF-8). */
  679.     int *lengthPtr; /* Used to return length of name (for
  680.  * successful searches) or number of non-NULL
  681.  * entries in environ (for unsuccessful
  682.  * searches). */
  683. {
  684.     int i, length, result = -1;
  685.     register CONST char *env, *p1, *p2;
  686.     char *envUpper, *nameUpper;
  687.     Tcl_DString envString;
  688.     /*
  689.      * Convert the name to all upper case for the case insensitive
  690.      * comparison.
  691.      */
  692.     length = strlen(name);
  693.     nameUpper = (char *) ckalloc((unsigned) length+1);
  694.     memcpy((VOID *) nameUpper, (VOID *) name, (size_t) length+1);
  695.     Tcl_UtfToUpper(nameUpper);
  696.     
  697.     Tcl_DStringInit(&envString);
  698.     for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) {
  699. /*
  700.  * Chop the env string off after the equal sign, then Convert
  701.  * the name to all upper case, so we do not have to convert
  702.  * all the characters after the equal sign.
  703.  */
  704. envUpper = Tcl_ExternalToUtfDString(NULL, env, -1, &envString);
  705. p1 = strchr(envUpper, '=');
  706. if (p1 == NULL) {
  707.     continue;
  708. }
  709. length = (int) (p1 - envUpper);
  710. Tcl_DStringSetLength(&envString, length+1);
  711. Tcl_UtfToUpper(envUpper);
  712. p1 = envUpper;
  713. p2 = nameUpper;
  714. for (; *p2 == *p1; p1++, p2++) {
  715.     /* NULL loop body. */
  716. }
  717. if ((*p1 == '=') && (*p2 == '')) {
  718.     *lengthPtr = length;
  719.     result = i;
  720.     goto done;
  721. }
  722. Tcl_DStringFree(&envString);
  723.     }
  724.     
  725.     *lengthPtr = i;
  726.     done:
  727.     Tcl_DStringFree(&envString);
  728.     ckfree(nameUpper);
  729.     return result;
  730. }
  731. /*
  732.  *----------------------------------------------------------------------
  733.  *
  734.  * Tcl_Init --
  735.  *
  736.  * This procedure is typically invoked by Tcl_AppInit procedures
  737.  * to perform additional initialization for a Tcl interpreter,
  738.  * such as sourcing the "init.tcl" script.
  739.  *
  740.  * Results:
  741.  * Returns a standard Tcl completion code and sets the interp's
  742.  * result if there is an error.
  743.  *
  744.  * Side effects:
  745.  * Depends on what's in the init.tcl script.
  746.  *
  747.  *----------------------------------------------------------------------
  748.  */
  749. int
  750. Tcl_Init(interp)
  751.     Tcl_Interp *interp; /* Interpreter to initialize. */
  752. {
  753.     Tcl_Obj *pathPtr;
  754.     if (tclPreInitScript != NULL) {
  755. if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
  756.     return (TCL_ERROR);
  757. };
  758.     }
  759.     pathPtr = TclGetLibraryPath();
  760.     if (pathPtr == NULL) {
  761. pathPtr = Tcl_NewObj();
  762.     }
  763.     Tcl_IncrRefCount(pathPtr);    
  764.     Tcl_SetVar2Ex(interp, "tcl_libPath", NULL, pathPtr, TCL_GLOBAL_ONLY);
  765.     Tcl_DecrRefCount(pathPtr);    
  766.     return Tcl_Eval(interp, initScript);
  767. }
  768. /*
  769.  *----------------------------------------------------------------------
  770.  *
  771.  * Tcl_SourceRCFile --
  772.  *
  773.  * This procedure is typically invoked by Tcl_Main of Tk_Main
  774.  * procedure to source an application specific rc file into the
  775.  * interpreter at startup time.
  776.  *
  777.  * Results:
  778.  * None.
  779.  *
  780.  * Side effects:
  781.  * Depends on what's in the rc script.
  782.  *
  783.  *----------------------------------------------------------------------
  784.  */
  785. void
  786. Tcl_SourceRCFile(interp)
  787.     Tcl_Interp *interp; /* Interpreter to source rc file into. */
  788. {
  789.     Tcl_DString temp;
  790.     CONST char *fileName;
  791.     Tcl_Channel errChannel;
  792.     fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
  793.     if (fileName != NULL) {
  794.         Tcl_Channel c;
  795. CONST char *fullName;
  796.         Tcl_DStringInit(&temp);
  797. fullName = Tcl_TranslateFileName(interp, fileName, &temp);
  798. if (fullName == NULL) {
  799.     /*
  800.      * Couldn't translate the file name (e.g. it referred to a
  801.      * bogus user or there was no HOME environment variable).
  802.      * Just do nothing.
  803.      */
  804. } else {
  805.     /*
  806.      * Test for the existence of the rc file before trying to read it.
  807.      */
  808.             c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
  809.             if (c != (Tcl_Channel) NULL) {
  810.                 Tcl_Close(NULL, c);
  811. if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
  812.     errChannel = Tcl_GetStdChannel(TCL_STDERR);
  813.     if (errChannel) {
  814. Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
  815. Tcl_WriteChars(errChannel, "n", 1);
  816.     }
  817. }
  818.     }
  819. }
  820.         Tcl_DStringFree(&temp);
  821.     }
  822. }