os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacInit.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2  * tclMacInit.c --
     3  *
     4  *	Contains the Mac-specific interpreter initialization functions.
     5  *
     6  * Copyright (c) 1995-1998 Sun Microsystems, Inc.
     7  *
     8  * See the file "license.terms" for information on usage and redistribution
     9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    10  *
    11  * RCS: @(#) $Id: tclMacInit.c,v 1.9.2.2 2005/10/23 22:01:31 msofer Exp $
    12  */
    13 
    14 #include <AppleEvents.h>
    15 #include <AEDataModel.h>
    16 #include <AEObjects.h>
    17 #include <AEPackObject.h>
    18 #include <AERegistry.h>
    19 #include <Files.h>
    20 #include <Folders.h>
    21 #include <Gestalt.h>
    22 #include <TextUtils.h>
    23 #include <Resources.h>
    24 #include <Strings.h>
    25 #include "tclInt.h"
    26 #include "tclMacInt.h"
    27 #include "tclPort.h"
    28 #include "tclInitScript.h"
    29 
    30 /*
    31  * The following string is the startup script executed in new
    32  * interpreters.  It looks on the library path and in the resource fork for
    33  * a script "init.tcl" that is compatible with this version of Tcl.  The
    34  * init.tcl script does all of the real work of initialization.
    35  */
    36  
    37 static char initCmd[] = "if {[info proc tclInit]==\"\"} {\n\
    38 proc tclInit {} {\n\
    39 global tcl_pkgPath env\n\
    40 proc sourcePath {file} {\n\
    41   foreach i $::auto_path {\n\
    42     set init [file join $i $file.tcl]\n\
    43     if {[catch {uplevel #0 [list source $init]}] == 0} {\n\
    44       return\n\
    45     }\n\
    46   }\n\
    47   if {[catch {uplevel #0 [list source -rsrc $file]}] == 0} {\n\
    48     return\n\
    49   }\n\
    50   rename sourcePath {}\n\
    51   set msg \"Can't find $file resource or a usable $file.tcl file\"\n\
    52   append msg \" in the following directories:\"\n\
    53   append msg \" $::auto_path\"\n\
    54   append msg \" perhaps you need to install Tcl or set your\"\n\
    55   append msg \" TCL_LIBRARY environment variable?\"\n\
    56   error $msg\n\
    57 }\n\
    58 if {[info exists env(EXT_FOLDER)]} {\n\
    59   lappend tcl_pkgPath [file join $env(EXT_FOLDER) {Tool Command Language}]\n\
    60 }\n\
    61 if {[info exists tcl_pkgPath] == 0} {\n\
    62   set tcl_pkgPath {no extension folder}\n\
    63 }\n\
    64 sourcePath init\n\
    65 sourcePath auto\n\
    66 sourcePath package\n\
    67 sourcePath history\n\
    68 sourcePath word\n\
    69 sourcePath parray\n\
    70 rename sourcePath {}\n\
    71 } }\n\
    72 tclInit";
    73 
    74 /*
    75  * The following structures are used to map the script/language codes of a 
    76  * font to the name that should be passed to Tcl_GetEncoding() to obtain
    77  * the encoding for that font.  The set of numeric constants is fixed and 
    78  * defined by Apple.
    79  */
    80  
    81 typedef struct Map {
    82     int numKey;
    83     char *strKey;
    84 } Map;
    85  
    86 static Map scriptMap[] = {
    87     {smRoman,		"macRoman"},
    88     {smJapanese,	"macJapan"},
    89     {smTradChinese,	"macChinese"},
    90     {smKorean,		"macKorean"},
    91     {smArabic,		"macArabic"},
    92     {smHebrew,		"macHebrew"},
    93     {smGreek,		"macGreek"},
    94     {smCyrillic,	"macCyrillic"},
    95     {smRSymbol,		"macRSymbol"},
    96     {smDevanagari,	"macDevanagari"},
    97     {smGurmukhi,	"macGurmukhi"},
    98     {smGujarati,	"macGujarati"},
    99     {smOriya,		"macOriya"},
   100     {smBengali,		"macBengali"},
   101     {smTamil,		"macTamil"},
   102     {smTelugu,		"macTelugu"},
   103     {smKannada,		"macKannada"},
   104     {smMalayalam,	"macMalayalam"},
   105     {smSinhalese,	"macSinhalese"},
   106     {smBurmese,		"macBurmese"},
   107     {smKhmer,		"macKhmer"},
   108     {smThai,		"macThailand"},
   109     {smLaotian,		"macLaos"},
   110     {smGeorgian,	"macGeorgia"},
   111     {smArmenian,	"macArmenia"},
   112     {smSimpChinese,	"macSimpChinese"},
   113     {smTibetan,		"macTIbet"},
   114     {smMongolian,	"macMongolia"},
   115     {smGeez,		"macEthiopia"},
   116     {smEastEurRoman,	"macCentEuro"},
   117     {smVietnamese,	"macVietnam"},
   118     {smExtArabic,	"macSindhi"},
   119     {NULL,		NULL}
   120 };    
   121 
   122 static Map romanMap[] = {
   123     {langCroatian,	"macCroatian"},
   124     {langSlovenian,	"macCroatian"},
   125     {langIcelandic,	"macIceland"},
   126     {langRomanian,	"macRomania"},
   127     {langTurkish,	"macTurkish"},
   128     {langGreek,		"macGreek"},
   129     {NULL,		NULL}
   130 };
   131 
   132 static Map cyrillicMap[] = {
   133     {langUkrainian,	"macUkraine"},
   134     {langBulgarian,	"macBulgaria"},
   135     {NULL,		NULL}
   136 };
   137 
   138 static int		GetFinderFont(int *finderID);
   139 
   140 /* Used to store the encoding used for binary files */
   141 static Tcl_Encoding binaryEncoding = NULL;
   142 /* Has the basic library path encoding issue been fixed */
   143 static int libraryPathEncodingFixed = 0;
   144 
   145 
   146 /*
   147  *----------------------------------------------------------------------
   148  *
   149  * GetFinderFont --
   150  *
   151  *	Gets the "views" font of the Macintosh Finder
   152  *
   153  * Results:
   154  *	Standard Tcl result, and sets finderID to the font family
   155  *      id for the current finder font.
   156  *
   157  * Side effects:
   158  *	None.
   159  *
   160  *----------------------------------------------------------------------
   161  */
   162 static int
   163 GetFinderFont(int *finderID)
   164 {
   165     OSErr err = noErr;
   166     OSType finderPrefs, viewFont = 'vfnt';
   167     DescType returnType;
   168     Size returnSize;
   169     long result, sys8Mask = 0x0800;
   170     static AppleEvent outgoingAevt = {typeNull, NULL};
   171     AppleEvent returnAevt;
   172     AEAddressDesc fndrAddress;
   173     AEDesc nullContainer = {typeNull, NULL}, 
   174            tempDesc = {typeNull, NULL}, 
   175            tempDesc2 = {typeNull, NULL}, 
   176            finalDesc = {typeNull, NULL};
   177     const OSType finderSignature = 'MACS';
   178     
   179     
   180     if (outgoingAevt.descriptorType == typeNull) {
   181         if ((Gestalt(gestaltSystemVersion, &result) != noErr)
   182 	        || (result >= sys8Mask)) {
   183             finderPrefs = 'pfrp';
   184         } else {
   185 	    finderPrefs = 'pvwp';
   186         }
   187         
   188         AECreateDesc(typeApplSignature, &finderSignature,
   189 		sizeof(finderSignature), &fndrAddress);
   190             
   191         err = AECreateAppleEvent(kAECoreSuite, kAEGetData, &fndrAddress, 
   192                 kAutoGenerateReturnID, kAnyTransactionID, &outgoingAevt);
   193                 
   194         AEDisposeDesc(&fndrAddress);
   195     
   196         /*
   197          * The structure is:
   198          * the property view font ('vfnt')
   199          *    of the property view preferences ('pvwp')
   200          *        of the Null Container (i.e. the Finder itself). 
   201          */
   202          
   203         AECreateDesc(typeType, &finderPrefs, sizeof(finderPrefs), &tempDesc);
   204         err = CreateObjSpecifier(typeType, &nullContainer, formPropertyID,
   205 		&tempDesc, true, &tempDesc2);
   206         AECreateDesc(typeType, &viewFont, sizeof(viewFont), &tempDesc);
   207         err = CreateObjSpecifier(typeType, &tempDesc2, formPropertyID,
   208 		&tempDesc, true, &finalDesc);
   209     
   210         AEPutKeyDesc(&outgoingAevt, keyDirectObject, &finalDesc);
   211         AEDisposeDesc(&finalDesc);
   212     }
   213              
   214     err = AESend(&outgoingAevt, &returnAevt, kAEWaitReply, kAEHighPriority,
   215 	    kAEDefaultTimeout, NULL, NULL);
   216     if (err == noErr) {
   217         err = AEGetKeyPtr(&returnAevt, keyDirectObject, typeInteger, 
   218                 &returnType, (void *) finderID, sizeof(int), &returnSize);
   219         if (err == noErr) {
   220             return TCL_OK;
   221         }
   222     }
   223     return TCL_ERROR;
   224 }
   225 
   226 /*
   227  *---------------------------------------------------------------------------
   228  *
   229  * TclMacGetFontEncoding --
   230  *
   231  *	Determine the encoding of the specified font.  The encoding
   232  *	can be used to convert bytes from UTF-8 into the encoding of
   233  *	that font.
   234  *
   235  * Results:
   236  *	The return value is a string that specifies the font's encoding
   237  *	and that can be passed to Tcl_GetEncoding() to construct the
   238  *	encoding.  If the font's encoding could not be identified, NULL
   239  *	is returned.
   240  *
   241  * Side effects:
   242  *	None.
   243  *
   244  *---------------------------------------------------------------------------
   245  */
   246  
   247 char *
   248 TclMacGetFontEncoding(
   249     int fontId)
   250 {
   251     int script, lang;
   252     char *name;
   253     Map *mapPtr;
   254     
   255     script = FontToScript(fontId);    
   256     lang = GetScriptVariable(script, smScriptLang);
   257     name = NULL;
   258     if (script == smRoman) {
   259         for (mapPtr = romanMap; mapPtr->strKey != NULL; mapPtr++) {
   260             if (mapPtr->numKey == lang) {
   261                 name = mapPtr->strKey;
   262                 break;
   263             }
   264         }
   265     } else if (script == smCyrillic) {
   266         for (mapPtr = cyrillicMap; mapPtr->strKey != NULL; mapPtr++) {
   267             if (mapPtr->numKey == lang) {
   268                 name = mapPtr->strKey;
   269                 break;
   270             }
   271         }
   272     }
   273     if (name == NULL) {
   274         for (mapPtr = scriptMap; mapPtr->strKey != NULL; mapPtr++) {
   275             if (mapPtr->numKey == script) {
   276                 name = mapPtr->strKey;
   277                 break;
   278             }
   279         }
   280     }
   281     return name;
   282 }
   283 
   284 /*
   285  *---------------------------------------------------------------------------
   286  *
   287  * TclpInitPlatform --
   288  *
   289  *	Initialize all the platform-dependant things like signals and
   290  *	floating-point error handling.
   291  *
   292  *	Called at process initialization time.
   293  *
   294  * Results:
   295  *	None.
   296  *
   297  * Side effects:
   298  *	None.
   299  *
   300  *---------------------------------------------------------------------------
   301  */
   302 
   303 void
   304 TclpInitPlatform()
   305 {
   306     tclPlatform = TCL_PLATFORM_MAC;
   307 }
   308 
   309 /*
   310  *---------------------------------------------------------------------------
   311  *
   312  * TclpInitLibraryPath --
   313  *
   314  *	Initialize the library path at startup.  We have a minor
   315  *	metacircular problem that we don't know the encoding of the
   316  *	operating system but we may need to talk to operating system
   317  *	to find the library directories so that we know how to talk to
   318  *	the operating system.
   319  *
   320  *	We do not know the encoding of the operating system.
   321  *	We do know that the encoding is some multibyte encoding.
   322  *	In that multibyte encoding, the characters 0..127 are equivalent
   323  *	    to ascii.
   324  *
   325  *	So although we don't know the encoding, it's safe:
   326  *	    to look for the last colon character in a path in the encoding.
   327  *	    to append an ascii string to a path.
   328  *	    to pass those strings back to the operating system.
   329  *
   330  *	But any strings that we remembered before we knew the encoding of
   331  *	the operating system must be translated to UTF-8 once we know the
   332  *	encoding so that the rest of Tcl can use those strings.
   333  *
   334  *	This call sets the library path to strings in the unknown native
   335  *	encoding.  TclpSetInitialEncodings() will translate the library
   336  *	path from the native encoding to UTF-8 as soon as it determines
   337  *	what the native encoding actually is.
   338  *
   339  *	Called at process initialization time.
   340  *
   341  * Results:
   342  *	Return 1, indicating that the UTF may be dirty and require "cleanup"
   343  *	after encodings are initialized.
   344  *
   345  * Side effects:
   346  *	None.
   347  *
   348  *---------------------------------------------------------------------------
   349  */
   350 
   351 int
   352 TclpInitLibraryPath(argv0)
   353     CONST char *argv0;		/* Name of executable from argv[0] to main().
   354 				 * Not used because we can determine the name
   355 				 * by querying the module handle. */
   356 {
   357     Tcl_Obj *objPtr, *pathPtr;
   358     CONST char *str;
   359     Tcl_DString ds;
   360     
   361     TclMacCreateEnv();
   362 
   363     pathPtr = Tcl_NewObj();
   364     
   365     /*
   366      * Look for the library relative to default encoding dir.
   367      */
   368 
   369     str = Tcl_GetDefaultEncodingDir();
   370     if ((str != NULL) && (str[0] != '\0')) {
   371 	objPtr = Tcl_NewStringObj(str, -1);
   372 	Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
   373     }
   374 
   375     str = TclGetEnv("TCL_LIBRARY", &ds);
   376     if ((str != NULL) && (str[0] != '\0')) {
   377 	/*
   378 	 * If TCL_LIBRARY is set, search there.
   379 	 */
   380 	 
   381 	objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&ds));
   382 	Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
   383 	Tcl_DStringFree(&ds);
   384     }
   385     
   386     objPtr = TclGetLibraryPath();
   387     if (objPtr != NULL) {
   388         Tcl_ListObjAppendList(NULL, pathPtr, objPtr);
   389     }
   390     
   391     /*
   392      * lappend path [file join $env(EXT_FOLDER) \
   393      *      "Tool Command Language" "tcl[info version]"
   394      */
   395 
   396     str = TclGetEnv("EXT_FOLDER", &ds);
   397     if ((str != NULL) && (str[0] != '\0')) {
   398 	    Tcl_DString libPath, path;
   399 	    CONST char *argv[3];
   400 	    
   401 	    argv[0] = str;
   402 	    argv[1] = "Tool Command Language";	    
   403 	    Tcl_DStringInit(&libPath);
   404 	    Tcl_DStringAppend(&libPath, "tcl", -1);
   405 	    argv[2] = Tcl_DStringAppend(&libPath, TCL_VERSION, -1);
   406 	    Tcl_DStringInit(&path);
   407 	    str = Tcl_JoinPath(3, argv, &path);
   408         objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&path));
   409 	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
   410 	    Tcl_DStringFree(&ds);
   411 	    Tcl_DStringFree(&libPath);
   412 	    Tcl_DStringFree(&path);
   413     }    
   414     TclSetLibraryPath(pathPtr);
   415 
   416     return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */
   417 }
   418 
   419 /*
   420  *---------------------------------------------------------------------------
   421  *
   422  * TclpSetInitialEncodings --
   423  *
   424  *	Based on the locale, determine the encoding of the operating
   425  *	system and the default encoding for newly opened files.
   426  *
   427  *	Called at process initialization time, and part way through
   428  *	startup, we verify that the initial encodings were correctly
   429  *	setup.  Depending on Tcl's environment, there may not have been
   430  *	enough information first time through (above).
   431  *
   432  * Results:
   433  *	None.
   434  *
   435  * Side effects:
   436  *	The Tcl library path is converted from native encoding to UTF-8,
   437  *	on the first call, and the encodings may be changed on first or
   438  *	second call.
   439  *
   440  *---------------------------------------------------------------------------
   441  */
   442 
   443 void
   444 TclpSetInitialEncodings()
   445 {
   446     CONST char *encoding;
   447     Tcl_Obj *pathPtr;
   448     int fontId, err;
   449     
   450     fontId = 0;
   451     GetFinderFont(&fontId);
   452     encoding = TclMacGetFontEncoding(fontId);
   453     if (encoding == NULL) {
   454         encoding = "macRoman";
   455     }
   456     
   457     err = Tcl_SetSystemEncoding(NULL, encoding);
   458 
   459     if (err == TCL_OK && libraryPathEncodingFixed == 0) {
   460 	
   461     /*
   462      * Until the system encoding was actually set, the library path was
   463      * actually in the native multi-byte encoding, and not really UTF-8
   464      * as advertised.  We cheated as follows:
   465      *
   466      * 1. It was safe to allow the Tcl_SetSystemEncoding() call to 
   467      * append the ASCII chars that make up the encoding's filename to 
   468      * the names (in the native encoding) of directories in the library 
   469      * path, since all Unix multi-byte encodings have ASCII in the
   470      * beginning.
   471      *
   472      * 2. To open the encoding file, the native bytes in the file name
   473      * were passed to the OS, without translating from UTF-8 to native,
   474      * because the name was already in the native encoding.
   475      *
   476      * Now that the system encoding was actually successfully set,
   477      * translate all the names in the library path to UTF-8.  That way,
   478      * next time we search the library path, we'll translate the names 
   479      * from UTF-8 to the system encoding which will be the native 
   480      * encoding.
   481      */
   482 
   483     pathPtr = TclGetLibraryPath();
   484     if (pathPtr != NULL) {
   485     	int i, objc;
   486 	Tcl_Obj **objv;
   487 	
   488 	objc = 0;
   489 	Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv);
   490 	for (i = 0; i < objc; i++) {
   491 	    int length;
   492 	    char *string;
   493 	    Tcl_DString ds;
   494 
   495 	    string = Tcl_GetStringFromObj(objv[i], &length);
   496 	    Tcl_ExternalToUtfDString(NULL, string, length, &ds);
   497 	    Tcl_SetStringObj(objv[i], Tcl_DStringValue(&ds), 
   498 		    Tcl_DStringLength(&ds));
   499 	    Tcl_DStringFree(&ds);
   500 	}
   501 	Tcl_InvalidateStringRep(pathPtr);
   502     }
   503 	libraryPathEncodingFixed = 1;
   504     }
   505     
   506     /* This is only ever called from the startup thread */
   507     if (binaryEncoding == NULL) {
   508 	/*
   509 	 * Keep the iso8859-1 encoding preloaded.  The IO package uses
   510 	 * it for gets on a binary channel.
   511 	 */
   512 	binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");
   513     }
   514 }   
   515 
   516 /*
   517  *---------------------------------------------------------------------------
   518  *
   519  * TclpSetVariables --
   520  *
   521  *	Performs platform-specific interpreter initialization related to
   522  *	the tcl_library and tcl_platform variables, and other platform-
   523  *	specific things.
   524  *
   525  * Results:
   526  *	None.
   527  *
   528  * Side effects:
   529  *	Sets "tcl_library" and "tcl_platform" Tcl variables.
   530  *
   531  *----------------------------------------------------------------------
   532  */
   533 
   534 void
   535 TclpSetVariables(interp)
   536     Tcl_Interp *interp;
   537 {
   538     long int gestaltResult;
   539     int minor, major, objc;
   540     Tcl_Obj **objv;
   541     char versStr[2 * TCL_INTEGER_SPACE];
   542     CONST char *str;
   543     Tcl_Obj *pathPtr;
   544     Tcl_DString ds;
   545 
   546     str = "no library";
   547     pathPtr = TclGetLibraryPath();
   548     if (pathPtr != NULL) {
   549         objc = 0;
   550         Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv);
   551         if (objc > 0) {
   552             str = Tcl_GetStringFromObj(objv[0], NULL);
   553         }
   554     }
   555     Tcl_SetVar(interp, "tcl_library", str, TCL_GLOBAL_ONLY);
   556     
   557     if (pathPtr != NULL) {
   558         Tcl_SetVar2Ex(interp, "tcl_pkgPath", NULL, pathPtr, TCL_GLOBAL_ONLY);
   559     }
   560     
   561     Tcl_SetVar2(interp, "tcl_platform", "platform", "macintosh",
   562 	    TCL_GLOBAL_ONLY);
   563     Tcl_SetVar2(interp, "tcl_platform", "os", "MacOS", TCL_GLOBAL_ONLY);
   564     Gestalt(gestaltSystemVersion, &gestaltResult);
   565     major = (gestaltResult & 0x0000FF00) >> 8;
   566     minor = (gestaltResult & 0x000000F0) >> 4;
   567     sprintf(versStr, "%d.%d", major, minor);
   568     Tcl_SetVar2(interp, "tcl_platform", "osVersion", versStr, TCL_GLOBAL_ONLY);
   569 #if GENERATINGPOWERPC
   570     Tcl_SetVar2(interp, "tcl_platform", "machine", "ppc", TCL_GLOBAL_ONLY);
   571 #else
   572     Tcl_SetVar2(interp, "tcl_platform", "machine", "68k", TCL_GLOBAL_ONLY);
   573 #endif
   574 
   575     /*
   576      * Copy USER or LOGIN environment variable into tcl_platform(user)
   577      * These are set by SystemVariables in tclMacEnv.c
   578      */
   579 
   580     Tcl_DStringInit(&ds);
   581     str = TclGetEnv("USER", &ds);
   582     if (str == NULL) {
   583 	str = TclGetEnv("LOGIN", &ds);
   584 	if (str == NULL) {
   585 	    str = "";
   586 	}
   587     }
   588     Tcl_SetVar2(interp, "tcl_platform", "user", str, TCL_GLOBAL_ONLY);
   589     Tcl_DStringFree(&ds);
   590 }
   591 
   592 /*
   593  *----------------------------------------------------------------------
   594  *
   595  * TclpCheckStackSpace --
   596  *
   597  *	On a 68K Mac, we can detect if we are about to blow the stack.
   598  *	Called before an evaluation can happen when nesting depth is
   599  *	checked.
   600  *
   601  * Results:
   602  *	1 if there is enough stack space to continue; 0 if not.
   603  *
   604  * Side effects:
   605  *	None.
   606  *
   607  *----------------------------------------------------------------------
   608  */
   609 
   610 int
   611 TclpCheckStackSpace()
   612 {
   613     return StackSpace() > TCL_MAC_STACK_THRESHOLD;
   614 }
   615 
   616 /*
   617  *----------------------------------------------------------------------
   618  *
   619  * TclpFindVariable --
   620  *
   621  *	Locate the entry in environ for a given name.  On Unix and Macthis 
   622  *	routine is case sensitive, on Windows this matches mixed case.
   623  *
   624  * Results:
   625  *	The return value is the index in environ of an entry with the
   626  *	name "name", or -1 if there is no such entry.   The integer at
   627  *	*lengthPtr is filled in with the length of name (if a matching
   628  *	entry is found) or the length of the environ array (if no matching
   629  *	entry is found).
   630  *
   631  * Side effects:
   632  *	None.
   633  *
   634  *----------------------------------------------------------------------
   635  */
   636 
   637 int
   638 TclpFindVariable(name, lengthPtr)
   639     CONST char *name;		/* Name of desired environment variable
   640 				 * (native). */
   641     int *lengthPtr;		/* Used to return length of name (for
   642 				 * successful searches) or number of non-NULL
   643 				 * entries in environ (for unsuccessful
   644 				 * searches). */
   645 {
   646     int i, result = -1;
   647     register CONST char *env, *p1, *p2;
   648     Tcl_DString envString;
   649 
   650     Tcl_DStringInit(&envString);
   651     for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) {
   652 	p1 = Tcl_ExternalToUtfDString(NULL, env, -1, &envString);
   653 	p2 = name;
   654 
   655 	for (; *p2 == *p1; p1++, p2++) {
   656 	    /* NULL loop body. */
   657 	}
   658 	if ((*p1 == '=') && (*p2 == '\0')) {
   659 	    *lengthPtr = p2 - name;
   660 	    result = i;
   661 	    goto done;
   662 	}
   663 	
   664 	Tcl_DStringFree(&envString);
   665     }
   666     
   667     *lengthPtr = i;
   668 
   669     done:
   670     Tcl_DStringFree(&envString);
   671     return result;
   672 }
   673 
   674 /*
   675  *----------------------------------------------------------------------
   676  *
   677  * Tcl_Init --
   678  *
   679  *	This procedure is typically invoked by Tcl_AppInit procedures
   680  *	to perform additional initialization for a Tcl interpreter,
   681  *	such as sourcing the "init.tcl" script.
   682  *
   683  * Results:
   684  *	Returns a standard Tcl completion code and sets the interp's result
   685  *	if there is an error.
   686  *
   687  * Side effects:
   688  *	Depends on what's in the init.tcl script.
   689  *
   690  *----------------------------------------------------------------------
   691  */
   692 
   693 int
   694 Tcl_Init(
   695     Tcl_Interp *interp)		/* Interpreter to initialize. */
   696 {
   697     Tcl_Obj *pathPtr;
   698 
   699     if (tclPreInitScript != NULL) {
   700     if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
   701         return (TCL_ERROR);
   702     };
   703     }
   704 
   705     /*
   706      * For Macintosh applications the Init function may be contained in
   707      * the application resources.  If it exists we use it - otherwise we
   708      * look in the tcl_library directory.  Ditto for the history command.
   709      */
   710 
   711     pathPtr = TclGetLibraryPath();
   712     if (pathPtr == NULL) {
   713 	pathPtr = Tcl_NewObj();
   714     }
   715     Tcl_IncrRefCount(pathPtr);
   716     Tcl_SetVar2Ex(interp, "auto_path", NULL, pathPtr, TCL_GLOBAL_ONLY);
   717     Tcl_DecrRefCount(pathPtr);
   718     return Tcl_Eval(interp, initCmd);
   719 }
   720 
   721 /*
   722  *----------------------------------------------------------------------
   723  *
   724  * Tcl_SourceRCFile --
   725  *
   726  *	This procedure is typically invoked by Tcl_Main or Tk_Main
   727  *	procedure to source an application specific rc file into the
   728  *	interpreter at startup time.  This will either source a file
   729  *	in the "tcl_rcFileName" variable or a TEXT resource in the
   730  *	"tcl_rcRsrcName" variable.
   731  *
   732  * Results:
   733  *	None.
   734  *
   735  * Side effects:
   736  *	Depends on what's in the rc script.
   737  *
   738  *----------------------------------------------------------------------
   739  */
   740 
   741 void
   742 Tcl_SourceRCFile(
   743     Tcl_Interp *interp)		/* Interpreter to source rc file into. */
   744 {
   745     Tcl_DString temp;
   746     CONST char *fileName;
   747     Tcl_Channel errChannel;
   748     Handle h;
   749 
   750     fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
   751 
   752     if (fileName != NULL) {
   753         Tcl_Channel c;
   754 	CONST char *fullName;
   755 
   756         Tcl_DStringInit(&temp);
   757 	fullName = Tcl_TranslateFileName(interp, fileName, &temp);
   758 	if (fullName == NULL) {
   759 	    /*
   760 	     * Couldn't translate the file name (e.g. it referred to a
   761 	     * bogus user or there was no HOME environment variable).
   762 	     * Just do nothing.
   763 	     */
   764 	} else {
   765 
   766 	    /*
   767 	     * Test for the existence of the rc file before trying to read it.
   768 	     */
   769 
   770             c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
   771             if (c != (Tcl_Channel) NULL) {
   772                 Tcl_Close(NULL, c);
   773 		if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
   774 		    errChannel = Tcl_GetStdChannel(TCL_STDERR);
   775 		    if (errChannel) {
   776 			Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
   777 			Tcl_WriteChars(errChannel, "\n", 1);
   778 		    }
   779 		}
   780 	    }
   781 	}
   782         Tcl_DStringFree(&temp);
   783     }
   784 
   785     fileName = Tcl_GetVar(interp, "tcl_rcRsrcName", TCL_GLOBAL_ONLY);
   786 
   787     if (fileName != NULL) {
   788 	Str255 rezName;
   789 	Tcl_DString ds;
   790 	Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
   791 	strcpy((char *) rezName + 1, Tcl_DStringValue(&ds));
   792 	rezName[0] = (unsigned) Tcl_DStringLength(&ds);
   793 	h = GetNamedResource('TEXT', rezName);
   794 	Tcl_DStringFree(&ds);
   795 	if (h != NULL) {
   796 	    if (Tcl_MacEvalResource(interp, fileName, 0, NULL) != TCL_OK) {
   797 		errChannel = Tcl_GetStdChannel(TCL_STDERR);
   798 		if (errChannel) {
   799 		    Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
   800 		    Tcl_WriteChars(errChannel, "\n", 1);
   801 		}
   802 	    }
   803 	    Tcl_ResetResult(interp);
   804 	    ReleaseResource(h);
   805 	}
   806     }
   807 }