home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnusmalltalk / mstlib.c < prev    next >
C/C++ Source or Header  |  1992-03-01  |  24KB  |  926 lines

  1. /***********************************************************************
  2.  *
  3.  *    Main (library) Module
  4.  *
  5.  ***********************************************************************/
  6.  
  7. /***********************************************************************
  8.  *
  9.  * Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  10.  * Written by Steve Byrne.
  11.  *
  12.  * This file is part of GNU Smalltalk.
  13.  *
  14.  * GNU Smalltalk is free software; you can redistribute it and/or modify it
  15.  * under the terms of the GNU General Public License as published by the Free
  16.  * Software Foundation; either version 1, or (at your option) any later 
  17.  * version.
  18.  * 
  19.  * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  20.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  21.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  22.  * more details.
  23.  * 
  24.  * You should have received a copy of the GNU General Public License along with
  25.  * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  26.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  27.  *
  28.  ***********************************************************************/
  29.  
  30.  
  31. /*
  32.  *    Change Log
  33.  * ============================================================================
  34.  * Author      Date       Change 
  35.  * sbb          1 Jan 92      Converted to be callable as a library.
  36.  *
  37.  * sbb         14 Sep 91      Added edit version support.
  38.  *
  39.  * sbb         12 Sep 91      Fixed -I argument parsing code to properly gobble up
  40.  *              the file name.
  41.  *
  42.  * sbb         19 Jul 91      Started adding conditional support for the DLD
  43.  *              package.
  44.  *
  45.  * sbb         24 Mar 91      Added loading of changes.st
  46.  *
  47.  * sbb         24 Nov 90      Fixed to set quietExecution using || instead of | (HP
  48.  *              doesn't like it otherwise).
  49.  *
  50.  * sbb         17 Nov 90      Added UnixStream and IOCtl to kernel files.
  51.  *
  52.  * sbb          6 Nov 90      Added the per-user pre-image file...this may turn
  53.  *              into a kind of site defaults thing, but this is what
  54.  *              I've wanted for a while.
  55.  *
  56.  * sbb          2 Oct 90      Fixed okToLoadBinary so that it returns false if
  57.  *              there is a Smalltalk file found locally, but there is
  58.  *              no image file locally (the stix problem).
  59.  *
  60.  * sbyrne    22 May 90      Improved on Doug's mapping with macro to improve
  61.  *              readability.
  62.  *
  63.  * sbyrne    22 May 90      Short name stuff added, thanks to Doug McCallum.
  64.  *
  65.  * sbyrne    25 Mar 90      ProcessorScheduler is too long of a name for the
  66.  *              Atari; there are uniqueness problems.  Shortened to
  67.  *              ProcScheduler.   Also, fixed quietExecution; wasn't
  68.  *              set when reading from the terminal; should have been
  69.  *              set to false (since the loading of the quiet things
  70.  *              is over).
  71.  *
  72.  * sbyrne    15 Oct 89      Added support for creating an "installed" version of
  73.  *              Smalltalk.  There is now an include file that the
  74.  *              installer can customize for his site that provides
  75.  *              default locations to be checked for the kernel .st
  76.  *              files and the binary image file, but these can be
  77.  *              overidden in two ways: a) by a file of the same
  78.  *              name in the user's current directory, or b)
  79.  *              environment variables SMALLTALK_KERNEL and
  80.  *              SMALLTALK_IMAGE.
  81.  *
  82.  * sbyrne     4 Jul 89      Added support for user init files (in ~/.stinit),
  83.  *              which are invoked on every startup.  Also, added
  84.  *              support for initBlocks, which are blocks that are
  85.  *              stored in the system and invoked on each startup
  86.  *              (these could be used, for example, as an interim
  87.  *              measure for declaring C callouts until the callout
  88.  *              descriptor is converted to a Smalltalk object).
  89.  *
  90.  * sbyrne    10 Mar 89      Added support for automatically loading image file if
  91.  *              it's newer than and of the system source files.
  92.  *
  93.  * sbyrne    27 Dec 88      Created.
  94.  *
  95.  */
  96.  
  97.  
  98. #include "mst.h"
  99. #include "mst.tab.h"
  100. #include "mstinterp.h"
  101. #include "mstcomp.h"
  102. #include "mstsave.h"
  103. #include "mstsym.h"        /* for symbol table profiling */
  104. #include "mstoop.h"        /* indirectly defines oopAt for sym tab prof */
  105. #include "mstpaths.h"
  106. #include "mstlib.h"
  107. #include <stdio.h>
  108. #include <sys/types.h>
  109. #include <sys/stat.h>
  110. #include <sys/file.h>
  111. #if defined(USG)
  112. #include <unistd.h>
  113. #endif
  114.  
  115. #ifndef MAXPATHLEN
  116. #define MAXPATHLEN        1024 /* max length of a file and path */
  117. #endif
  118.  
  119. #ifdef SHORTNAMES
  120. #define MAP_FILE(long, short)    short
  121. #else
  122. #define MAP_FILE(long, short)    long
  123. #endif
  124.  
  125.  
  126. #ifndef atarist
  127. #define INIT_FILE_NAME        ".stinit"
  128. #define PRE_IMAGE_FILE_NAME    ".stpre"
  129. #else
  130. #define INIT_FILE_NAME        ".tinit"
  131. #define PRE_IMAGE_FILE_NAME    ".stpre" /* hope this is ok */
  132. #endif
  133.  
  134.  
  135. extern int        yydebug, lexDebug, numFreeOOPs;
  136. extern YYSTYPE        yylval;
  137. extern char        *getenv();
  138.  
  139. #ifdef symbol_table_profiling
  140. extern int        adds, reused, reprobes, hitsOn[];
  141. #endif /* symbol_table_profiling */
  142.  
  143. /* When true, this flag suppresses the printing of execution-related
  144.  * messages, such as the number of byte codes executed by the
  145.  * last expression, etc.
  146.  */
  147. Boolean            quietExecution;
  148.  
  149. char            *kernelFileDefaultPath, *imageFileDefaultPath;
  150.  
  151. /* This string contains the printed representation of the Smalltalk version
  152.  * number
  153.  */
  154. char            versionString[50];
  155.  
  156.  
  157. /* This is used by the callin functions to auto-initialize Smalltalk.
  158.  * When it's not true, initialization needs to be performed.  It's set
  159.  * to true by initSmalltalk().
  160.  */
  161. Boolean            smalltalkInitialized = false;
  162.  
  163.  
  164. /***********************************************************************
  165.  *
  166.  *    Private declarations
  167.  *
  168.  ***********************************************************************/
  169.  
  170. static Boolean         processFile(), okToLoadBinary(), findKernelFile();
  171. static void        loadStandardFiles(), loadUserInitFile(), initPaths(),
  172.             parseArgs(), loadUserPreImageFile(),
  173.             makeVersionString();
  174. static unsigned long    getFileModifyTime();
  175.  
  176.  
  177. /* Set by cmd line flag.  If true, Smalltalk is more verbose about what it's
  178.  * doing.
  179.  */
  180. static Boolean        verbose = false;
  181.  
  182. /* If true, even both kernel and user method definitions are shown as
  183.  * they are compiled.
  184.  */
  185. static Boolean        traceKernelDeclarations;
  186.  
  187. /* If true, execution tracing is performed when loading kernel method
  188.  * definitions
  189.  */
  190. static Boolean        traceKernelExecution;
  191.  
  192. /* If true, skip date checking of kernel files vs. binary image; pretend
  193.  * that binary image does not exist
  194.  */
  195. static Boolean        ignoreImage;
  196.  
  197.  
  198. /* If non-nil, this is the name of the binary image to load, and overrides
  199.  * the checking of the dates of the kernel source files against the image
  200.  * file date.
  201.  */
  202. static char        *binaryImageName = nil;
  203.  
  204.  
  205. /* Set by command line flag.  When this is true, the interpreter 
  206.  * does not print out things like "execution begins" or information
  207.  * about the number of byte codes executed.
  208.  */
  209. static Boolean        runQuietly = false;
  210.  
  211.  
  212. /* The complete list of "kernel" class and method definitions.  Each of
  213.  * these files is loaded, in the order given below.  Their last modification
  214.  * dates are compared against that of the image file; if any are newer,
  215.  * the image file is ignored, these files are loaded, and a new image file
  216.  * is created.
  217.  */
  218. static char        *standardFiles[] = {
  219.   "builtins.st", 
  220.   "Object.st",
  221.   "Message.st",
  222.   "Magnitude.st",
  223.   "Character.st",
  224.   "Date.st",
  225.   "Time.st",
  226.   "Number.st",
  227.   "Float.st",
  228.   "Integer.st",
  229.   "LookupKey.st",
  230.   "Association.st",
  231.   "Link.st",
  232.   "Process.st",
  233.   "Collection.st",
  234.   MAP_FILE("SequenceableCollection.st", "SeqColl.st"),
  235.   "LinkedList.st",
  236.   "Semaphore.st",
  237.   MAP_FILE("ArrayedCollection.st", "ArrColl.st"),
  238.   "Array.st",
  239.   "String.st",
  240.   "Symbol.st",
  241.   "ByteArray.st",
  242.   MAP_FILE("CompiledMethod.st", "CompileMth.st"),
  243.   "Interval.st",
  244.   MAP_FILE("OrderedCollection.st", "OrdColl.st"),
  245.   MAP_FILE("SortedCollection.st", "SortedColl.st"),
  246.   "Bag.st",
  247.   MAP_FILE("MappedCollection.st", "MappedColl.st"),
  248.   "Set.st",
  249.   "Dictionary.st",
  250.   MAP_FILE("IdentityDictionary.st", "IdentDict.st"),
  251.   MAP_FILE("SystemDictionary.st", "SysDict.st"),
  252.   "Stream.st",
  253.   MAP_FILE("PositionableStream.st", "PosStream.st"),
  254.   "ReadStream.st",
  255.   "WriteStream.st",
  256.   MAP_FILE("ReadWriteStream.st", "RWStream.st"),
  257.   "FileStream.st",
  258.   "TokenStream.st",
  259.   "Random.st",
  260.   MAP_FILE("UndefinedObject.st", "UndefObj.st"),
  261.   "Boolean.st",
  262.   "False.st",
  263.   "True.st",
  264. #if !defined(USG) && !defined(atarist)
  265.   "ProcessorScheduler.st",
  266. #else
  267.   "ProcSched.st",
  268. #endif
  269.   "Delay.st",
  270.   "SharedQueue.st",
  271.   "Behavior.st",
  272.   MAP_FILE("ClassDescription.st", "ClassDescr.st"),
  273.   "Class.st",
  274.   "Metaclass.st",
  275.   MAP_FILE("MethodContext.st", "MthContext.st"),
  276.   MAP_FILE("BlockContext.st", "BlkContext.st"),
  277.   "Memory.st",
  278.   "WordMemory.st",
  279.   "ByteMemory.st",
  280.   "MethodInfo.st",
  281.   "FileSegment.st",
  282.   "SymLink.st",
  283.   "initialize.st",
  284.   "CFuncs.st",
  285.   "CType.st",
  286.   "CObject.st",
  287.   "CStruct.st",
  288.   "Autoload.st",
  289.   "Fraction.st",
  290.   "UnixStream.st",
  291.   "IOCtl.st",
  292.   "changes.st", 
  293.   "Browser.st",
  294. #ifdef DLD
  295.   "DLD.st",
  296. #endif
  297.   nil
  298. };
  299.  
  300. static char    *smalltalkArgVec[] = { "mst", nil };
  301. static char    **smalltalkArgv = smalltalkArgVec ;
  302. static int    smalltalkArgc = 0;
  303.  
  304. smalltalkArgs(argc, argv)
  305. int    argc;
  306. char    **argv;
  307. {
  308.   smalltalkArgc = argc;
  309.   smalltalkArgv = argv;
  310. }
  311.  
  312. initSmalltalk()
  313. {
  314.   Boolean    loadBinary, traceUserDeclarations, traceUserExecution;
  315.   char        *imageName;
  316. #ifdef DLD
  317.   extern char    *dldArgv0;
  318. #endif
  319.  
  320. #ifdef USE_MONCONTROL
  321.   moncontrol(0);        /* don't monitor the initial stuff */
  322. #endif /* USE_MONCONTROL */
  323.  
  324. #ifdef DLD
  325.   dldArgv0 = smalltalkArgv[0];
  326. #endif
  327.  
  328.   yydebug = 0;
  329.   traceKernelDeclarations = declareTracing = false;
  330.   traceKernelExecution = executionTracing = false;
  331.   regressionTesting = false;
  332.   ignoreImage = false;
  333.   verbose = false;
  334.  
  335.   /*
  336.    * Even though we're nowhere near through initialization, we set this
  337.    * to make sure we don't invoke a callin function which would recursively
  338.    * invoke us.
  339.    */
  340.   smalltalkInitialized = true;
  341.  
  342.   initSignals();
  343.   initMem();
  344.   initCFuncs();
  345.   initOOPRegistry();
  346.   initPaths();
  347.   makeVersionString();
  348. #ifdef USE_READLINE
  349.   initializeReadline();
  350. #endif /* USE_READLINE */
  351.   initChangesStream();
  352. #if defined(USG)
  353.   tzset();
  354. #endif
  355.  
  356.   parseArgs(smalltalkArgc, smalltalkArgv);
  357.  
  358.   imageName = defaultImageName;
  359.  
  360.   if (binaryImageName) {
  361.     loadBinary = true;
  362.     imageName = binaryImageName;
  363.   } else if (ignoreImage) {
  364.     loadBinary = false;
  365.   } else {
  366.     loadBinary = okToLoadBinary(defaultImageName);
  367.   }
  368.  
  369.   if (loadBinary && loadFromFile(imageName)) {
  370.     initDefaultCompilationEnvironment();
  371.     initSTDIOObjects();
  372.     initInterpreter();
  373.     gcOn();
  374.   } else {
  375.     resetChangesFile();
  376.     initOOPTable();
  377.     initDictionary();
  378.     initSymbols();
  379.     initInterpreter();
  380.  
  381.     installInitialMethods();
  382.  
  383.     traceUserDeclarations = declareTracing;
  384.     traceUserExecution = executionTracing;
  385.     if (!traceKernelDeclarations) {
  386.       declareTracing = false;
  387.     }
  388.     if (!traceKernelExecution) {
  389.       executionTracing = false;
  390.     }
  391.  
  392.     gcOn();
  393.     loadStandardFiles();
  394.  
  395.     declareTracing = traceUserDeclarations;
  396.     executionTracing = traceUserExecution;
  397.  
  398.     loadUserPreImageFile();
  399. /* ***    gcOn(); *** */
  400.     saveToFile(defaultImageName);
  401.   }
  402.  
  403. #ifdef preserved /* Sun Mar 26 23:36:15 1989 */
  404. /**/#ifdef profiling
  405. /**/  monitor(0);
  406. /**/
  407. /**/  printf("results %d/%d\n", hits, misses);
  408. /**/  { int i;
  409. /**/    for (i = 0; i < 10240; i++) {
  410. /**/      if (hitsOn[i]) {
  411. /**/    printf("hitsOn[%d] = %4d\t%d\t%4x\t%8o", i, hitsOn[i],
  412. /**/           i, i, i);
  413. /**/    printObject(oopAt(i));
  414. /**/    printf("\n");
  415. /**/      }
  416. /**/    }
  417. /**/  }
  418. /**/#endif /* profiling */
  419. #endif /* preserved Sun Mar 26 23:36:15 1989 */
  420.  
  421. #ifdef USE_MONCONTROL
  422.   moncontrol(1);
  423. #endif /* USE_MONCONTROL */
  424.  
  425.   invokeInitBlocks();
  426.   loadUserInitFile();
  427.  
  428. #ifdef symbol_table_profiling
  429.   printf("%d adds, %d reused %d reprobes\n", adds, reused, reprobes);
  430.  
  431.   { int i;
  432.     for (i = 0; i < OOP_TABLE_SIZE; i++) {
  433.       if (hitsOn[i]) {
  434.     printf("hitsOn[%d] = %4d\t%d\t%4x\t%8o", i, hitsOn[i],
  435.            i, i, i);
  436.     printObject(oopAt(i));
  437.     printf("\n");
  438.       }
  439.     }
  440.   }
  441. #endif /* symbol_table_profiling */
  442.  
  443.  
  444. }
  445.  
  446. topLevelLoop()
  447. {
  448.   int        filesProcessed;
  449.  
  450.   if (regressionTesting) {
  451.     printf("Smalltalk Ready\n\n");
  452.   } else {
  453.     printf("Smalltalk %s Ready\n\n", versionString);
  454.   }
  455.  
  456.   quietExecution = runQuietly || emacsProcess;
  457.  
  458. #ifndef LEXDEBUG
  459.   for (filesProcessed = 0; *++smalltalkArgv; ) {
  460.     if (smalltalkArgv[0][0] != '-') {
  461.       processFile(smalltalkArgv[0], quietExecution);
  462.       filesProcessed++;
  463.     } else if (smalltalkArgv[0][1] == '-' || smalltalkArgv[0][1] == '\0') {
  464.       /* either - by itself or -- indicates standard input */
  465.       initLexer(false);
  466. #ifdef USE_READLINE
  467.       pushReadlineString();
  468. #else
  469.       pushUNIXFile(stdin, "stdin");
  470. #endif /* USE_READLINE */
  471.       yyparse();
  472.       popStream(true);
  473.     }
  474.   }
  475.  
  476.   if (filesProcessed == 0) {    /* didn't do any from cmd line, so read stdin*/
  477.     initLexer(false);
  478. #ifdef USE_READLINE
  479.     pushReadlineString();
  480. #else
  481.     pushUNIXFile(stdin, "stdin");
  482. #endif /* USE_READLINE */
  483.     yyparse();
  484.   }
  485.  
  486. #ifdef USE_MONCONTROL
  487.    moncontrol(0);
  488. #endif /* USE_MONCONTROL */
  489.  
  490.  
  491.  
  492. #else /* debugging the lexer */
  493.  
  494.  
  495.  
  496. #ifdef USE_READLINE
  497.     pushReadlineString();
  498. #else
  499.     pushUNIXFile(stdin, "stdin");
  500. #endif /* USE_READLINE */
  501.  
  502. /********* THIS IS NOT UP TO DATE ... BEWARE ************/
  503.  
  504.   lexDebug = 1;
  505.   while(!feof(infile)) {
  506.     switch (yylex()) {
  507.     case DOT:
  508.       printf("DOT\n");
  509.       break;
  510.     case BANG:
  511.       printf("BANG\n");
  512.       break;
  513.     case COLON:
  514.       printf("COLON\n");
  515.       break;
  516.     case VERTICAL_BAR:
  517.       printf("VERTICAL_BAR\n");
  518.       break;
  519.     case UPARROW:
  520.       printf("UPARROW\n");
  521.       break;
  522.     case ASSIGN:
  523.       printf("ASSIGN\n");
  524.       break;
  525.     case SHARP:
  526.       printf("SHARP\n");
  527.       break;
  528.     case SEMICOLON:
  529.       printf("SEMICOLON\n");
  530.       break;
  531.     case OPEN_PAREN:
  532.       printf("OPEN_PAREN\n");
  533.       break;
  534.     case CLOSE_PAREN:
  535.       printf("CLOSE_PAREN\n");
  536.       break;
  537.     case OPEN_BRACKET:
  538.       printf("OPEN_BRACKET\n");
  539.       break;
  540.     case CLOSE_BRACKET:
  541.       printf("CLOSE_BRACKET\n");
  542.       break;
  543.     case IDENTIFIER:
  544.       printf("IDENTIFIER: %s\n", yylval.sval);
  545.       break;
  546.     case INTEGER_LITERAL:
  547.       printf("INTEGER_LITERAL: %d\n", yylval.ival);
  548.       break;
  549.     case FLOATING_LITERAL:
  550.       printf("FLOATING_LITERAL: %g\n", yylval.fval);
  551.       break;
  552.     case CHAR_LITERAL:
  553.       printf("CHAR_LITERAL: %c\n", yylval.cval);
  554.       break;
  555.     case STRING_LITERAL:
  556.       printf("STRING_LITERAL: %s\n", yylval.sval);
  557.       break;
  558.     case BINOP:
  559.       printf("BINOP: %d\n", yylval.op);
  560.       break;
  561.     }
  562.   }
  563. #endif /* LEXDEBUG */
  564.  
  565. }
  566.  
  567.  
  568. /*
  569.  *    static void initPaths()
  570.  *
  571.  * Description
  572.  *
  573.  *    Sets up the paths for the kernel source directory and for where the
  574.  *    saved Smalltalk binary image lives.  Uses environment variables
  575.  *    SMALLTALK_KERNEL and SMALLTALK_IMAGE if they are set, otherwise uses
  576.  *    the paths assigned in mstpaths.h.
  577.  *
  578.  */
  579. static void initPaths()
  580. {
  581.   if ((kernelFileDefaultPath = (char *)getenv("SMALLTALK_KERNEL")) == nil) {
  582.     kernelFileDefaultPath = KERNEL_PATH;
  583.   }
  584.  
  585.   if ((imageFileDefaultPath = (char *)getenv("SMALLTALK_IMAGE")) == nil) {
  586.     imageFileDefaultPath = IMAGE_PATH;
  587.   }
  588. }
  589.  
  590. static Boolean okToLoadBinary(imageFileName)
  591. char    *imageFileName;
  592. {
  593.   unsigned long    imageFileTime;
  594.   char        **fileNames, fullFileName[MAXPATHLEN],
  595.           fullImageName[MAXPATHLEN], *home,
  596.           preImageFileName[MAXPATHLEN];
  597.   Boolean    localImage;    /* actually, nonDefaultImage is more right */
  598.  
  599.   localImage = findImageFile(imageFileName, fullImageName);
  600.   imageFileTime = getFileModifyTime(fullImageName);
  601.  
  602.   if (imageFileTime == 0) { /* not found */
  603.     return (false);
  604.   }
  605.  
  606.   for (fileNames = standardFiles; *fileNames; fileNames++) {
  607.     if (findKernelFile(*fileNames, fullFileName) && !localImage) {
  608.       /* file lives locally but the image doesn't -- bad semantics */
  609.       return (false);
  610.     }
  611.     if (imageFileTime < getFileModifyTime(fullFileName)) {
  612.       return (false);
  613.     }
  614.   }
  615.  
  616.   if ((home = (char *)getenv("HOME")) != nil) {
  617.     sprintf(preImageFileName, "%s/%s", home, PRE_IMAGE_FILE_NAME);
  618.     if (imageFileTime < getFileModifyTime(preImageFileName)) {
  619.       return (false);
  620.     }
  621.   }
  622.  
  623.   return (true);
  624. }
  625.  
  626. static unsigned long getFileModifyTime(fileName)
  627. char    *fileName;
  628. {
  629.   struct stat    st;
  630.  
  631.   if (stat(fileName, &st) < 0) {
  632.     return ((unsigned long)0);
  633.   } else {
  634.     return (st.st_mtime);
  635.   }
  636. }
  637.  
  638. /*
  639.  *    static void loadStandardFiles()
  640.  *
  641.  * Description
  642.  *
  643.  *    Loads the kernel Smalltalk files.  It uses a vector of file names, and
  644.  *    loads each file individually.  To provide for greater flexibility, if a
  645.  *    one of the files exists in the current directory, that is used in
  646.  *    preference to one in the default location.  The default location can be
  647.  *    overridden at runtime by setting the SMALLTALK_KERNEL environment
  648.  *    variable. 
  649.  *
  650.  */
  651. static void loadStandardFiles()
  652. {
  653.   char        **fileNames, fullFileName[MAXPATHLEN];
  654.   
  655.   for (fileNames = standardFiles; *fileNames; fileNames++) {
  656.     findKernelFile(*fileNames, fullFileName);
  657.     if (!processFile(fullFileName, true)) {
  658.       fprintf(stderr,
  659.           "Can't find system file '%s', proceeding without it.\n",
  660.           fullFileName);
  661.     }
  662.   }
  663. }
  664.  
  665.  
  666. /*
  667.  *    static Boolean findKernelFile(fileName, fullFileName)
  668.  *
  669.  * Description
  670.  *
  671.  *    Attempts to find a viable kernel Smalltalk file (.st file).  First
  672.  *    tries the current directory to allow for overriding installed kernel
  673.  *    files.  If that isn't found, the full path name of the installed kernel
  674.  *    file is stored in fullFileName.  Note that the directory part of the
  675.  *    kernel file name in this second case can be overridden by defining the
  676.  *    SMALLTALK_KERNEL environment variable to be the directory that should
  677.  *    serve as the kernel directory instead of the installed one.
  678.  *
  679.  * Inputs
  680.  *
  681.  *    fileName: 
  682.  *        A simple file name, sans directory.
  683.  *    fullFileName: 
  684.  *        The file name to use for the particular kernel file is returned
  685.  *        in this variable (which must be a string large enough for any
  686.  *        file name).  If there is a file in the current directory with
  687.  *        name "fileName", that is returned; otherwise the kernel path is
  688.  *        prepended to fileName (separated by a slash, of course) and
  689.  *        that is stored in the string pointed to by "fullFileName".
  690.  *
  691.  * Outputs
  692.  *
  693.  *    Returns true if the kernel file is found in the local directory, and
  694.  *    false if the file was found using the default path.
  695.  */
  696. static Boolean findKernelFile(fileName, fullFileName)
  697. char *fileName, *fullFileName;
  698. {
  699.   if (access(fileName, R_OK) == 0) {
  700.     strcpy(fullFileName, fileName);
  701.     return (true);
  702.   } else {
  703.     sprintf(fullFileName, "%s/%s", kernelFileDefaultPath, fileName);
  704.     return (false);
  705.   }
  706. }
  707.  
  708.  
  709. static void loadUserPreImageFile()
  710. {
  711.   char        fileName[MAXPATHLEN], *home;
  712.  
  713.   if ((home = (char *)getenv("HOME")) != nil) {
  714.     sprintf(fileName, "%s/%s", home, PRE_IMAGE_FILE_NAME);
  715.     processFile(fileName, quietExecution);
  716.   }
  717. }
  718.  
  719. static void loadUserInitFile()
  720. {
  721.   char        fileName[MAXPATHLEN], *home;
  722.  
  723.   if ((home = (char *)getenv("HOME")) != nil) {
  724.     sprintf(fileName, "%s/%s", home, INIT_FILE_NAME);
  725.     processFile(fileName, quietExecution);
  726.   }
  727. }
  728.  
  729. static Boolean processFile(fileName, quiet)
  730. char    *fileName;
  731. Boolean    quiet;
  732. {
  733.   FILE        *file;
  734.  
  735.   file = fopen(fileName, "r");
  736.   if (file == NULL) {
  737.     return (false);
  738.   }
  739.  
  740.   if (verbose) {
  741.     printf("Processing %s\n", fileName);
  742.   }
  743.  
  744.   quietExecution = quiet;
  745.   initLexer(false);
  746.   pushUNIXFile(file, fileName);
  747.   yyparse();
  748.   popStream(true);
  749.  
  750.   return (true);
  751. }
  752.  
  753. /*
  754.  *    Boolean findImageFile(fileName, fullFileName)
  755.  *
  756.  * Description
  757.  *
  758.  *    Attempts to find a viable Smalltalk image file.  First
  759.  *    tries the current directory to allow for overriding installed image
  760.  *    files.  If that isn't found, the full path name of the installed image
  761.  *    file is stored in fullFileName.  Note that the directory part of the
  762.  *    image file name in this second case can be overridden by defining the
  763.  *    SMALLTALK_IMAGE environment variable to be the directory that should
  764.  *    serve as the image directory instead of the installed one.
  765.  *
  766.  * Inputs
  767.  *
  768.  *    fileName: 
  769.  *        A simple file name, sans directory.
  770.  *    fullFileName: 
  771.  *        The file name to use for the particular image file is returned
  772.  *        in this variable (which must be a string large enough for any
  773.  *        file name).  If there is a file in the current directory with
  774.  *        name "fileName", that is returned; otherwise the kernel path is
  775.  *        prepended to fileName (separated by a slash, of course) and
  776.  *        that is stored in the string pointed to by "fullFileName".
  777.  *
  778.  * Outputs
  779.  *
  780.  *    Returns true if the image file was without the default path, and
  781.  *    false if the image file is found using the default path.
  782.  */
  783. Boolean findImageFile(fileName, fullFileName)
  784. char *fileName, *fullFileName;
  785. {
  786.   if (access(fileName, R_OK) == 0) {
  787.     strcpy(fullFileName, fileName);
  788.     return (true);
  789.   } else {
  790.     sprintf(fullFileName, "%s/%s", imageFileDefaultPath, fileName);
  791.     return (false);
  792.   }
  793. }
  794.  
  795.  
  796. /*
  797.  *    static void parseArgs(argc, argv)
  798.  *
  799.  * Description
  800.  *
  801.  *    This routine scans the command line arguments, accumulating information
  802.  *    and setting flags.  This will probably be replaced by getopt in a
  803.  *    future version of Smalltalk.
  804.  *
  805.  * Inputs
  806.  *
  807.  *    argc  : The number of arguments present
  808.  *    argv  : Vector of strings that are the arguments.
  809.  *
  810.  */
  811. static void parseArgs(argc, argv)
  812. int    argc;
  813. char    **argv;
  814. {
  815.   char        **hp, **av;
  816.   char        *flags;
  817.  
  818.   static char    *helpText[] = {
  819. "GNU Smalltalk usage:",
  820. "",
  821. "    mst [ flag ... ] [ file ...]",
  822. "",
  823. "Flags can appear either as -xyz or as -x -y -z.  The currently",
  824. "defined set of flags is:",
  825. "  -c\tDump core on fatal signal",
  826. "  -d\tTrace compilation of user specified files",
  827. "  -D\tTrace compilation of kernel and user files",
  828. "  -e\tTrace execution of files specified on command line",
  829. "  -E\tTrace execution of kernel and user files",
  830. "  -H -h -?  Print this message and exit",
  831. "  -i\tIgnore the image file; rebuild it from scratch",
  832. "  -I file\tUse 'file' as the image file, instead of 'mst.im'",
  833. "  -p\tRun Smalltalk as a 'process', i.e. from within GNU Emacs",
  834. "  -q\tRun Smalltalk without printing execution information",
  835. "  -r\tRun in regression test mode (printed messages are made constant)",
  836. "  -v\tPrint the Smalltalk version number",
  837. "  -V\tEnable verbose mode",
  838. "  -y\tTurn on debugging in the parser",
  839. "  - --\tRead input from standard input explicitly",
  840. "",
  841. "Files are loaded one after the other.  After the last one is loaded,",
  842. "Smalltalk will exit.  If no files are specified, Smalltalk reads from",
  843. "the terminal, with prompts.",
  844. NULL
  845. };
  846.  
  847.  
  848.   for ( ; *++argv; ) {
  849.     if (argv[0][0] == '-') {
  850.       for (flags = &argv[0][1]; *flags; flags++) {
  851.     switch (*flags) {
  852.     case 'c':
  853.       makeCoreFile = true;
  854.       break;
  855.     case 'D':
  856.       traceKernelDeclarations = true; /* fall thru */
  857.     case 'd':
  858.       declareTracing = true;
  859.       break;
  860.     case 'E':
  861.       traceKernelExecution = true; /* fall thru */
  862.     case 'e':
  863.       executionTracing = true;
  864.       break;
  865.     case 'h': case 'H': case '?':
  866.     default:
  867.       for (hp = helpText; *hp != NULL; hp++) {
  868.         printf("%s\n", *hp);
  869.       }
  870.           exit(0);
  871.     case 'I':
  872.       binaryImageName = argv[1];
  873.       for (av = argv+1; *av; av++) {    /* remove this argument */
  874.         *av = *(av+1);    /* ###fix me!!! */
  875.       }
  876.       break;
  877.     case 'i':
  878.       ignoreImage = true;
  879.       break;
  880.     case 'p':
  881.       emacsProcess = true;
  882.       break;
  883.     case 'q':
  884.       runQuietly = true;
  885.       break;
  886.     case 'r':
  887.       regressionTesting = true;
  888.       break;
  889.     case 'V':
  890.       verbose = true;
  891.       break;
  892.     case 'v':
  893.       printf("GNU Smalltalk version %s\n", versionString);
  894.       printf("Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.\n");
  895.       printf("Written by Steve Byrne.\n");
  896.       printf("Using kernel path: %s\n", kernelFileDefaultPath);
  897.       printf("Using image path : %s\n", imageFileDefaultPath);
  898.       break;
  899.     case 'y':
  900.       yydebug = 1;
  901.       break;
  902.     case '-':        /* this means standard input, so it's ok */
  903.       break;
  904.     }
  905.       }
  906.     }
  907.   }
  908.  
  909.   if (regressionTesting) {
  910.     traceKernelDeclarations = declareTracing = false;
  911.     traceKernelExecution = executionTracing = false;
  912.     verbose = false;
  913.   }
  914. }
  915.  
  916. static void makeVersionString()
  917. {
  918.   if (sysVersEdit != 0) {
  919.     sprintf(versionString, "%d.%d.%d", sysVersMajor, sysVersMinor,
  920.         sysVersEdit);
  921.   } else {
  922.     sprintf(versionString, "%d.%d", sysVersMajor, sysVersMinor);
  923.   }
  924. }
  925.  
  926.