home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / runtime / imain.r < prev    next >
Text File  |  1996-03-22  |  18KB  |  747 lines

  1. #if !COMPILER
  2. /*
  3.  * File: imain.r
  4.  * Interpreter main program, argument handling, and such.
  5.  * Contents: main, icon_call, icon_setup, resolve, xmfree
  6.  */
  7.  
  8. #include "::h:version.h"
  9. #include "::h:header.h"
  10. #include "::h:opdefs.h"
  11.  
  12. /*
  13.  * Prototypes.
  14.  */
  15. hidden    novalue    env_err    Params((char *msg,char *name,char *val));
  16. novalue    icon_setup    Params((int argc, char **argv, int *ip));
  17.  
  18. #ifdef MacGraph
  19. void MacMain (int argc,char **argv);
  20. void ToolBoxInit (void);
  21. void MenuBarInit (void);
  22. void MouseInfoInit (void);
  23. int GetArgs (char **argv);
  24. #endif                    /* MacGraph */
  25.  
  26. /*
  27.  * The following code is operating-system dependent [@imain.01].  Declarations
  28.  *   that are system-dependent.
  29.  */
  30.  
  31. #if PORT
  32.    /* probably needs something more */
  33. Deliberate Syntax Error
  34. #endif                    /* PORT */
  35.  
  36. #if MACINTOSH
  37. #if MPW
  38. int NoOptions = 0;
  39. #endif                    /* MPW */
  40. #endif                    /* MACINTOSH */
  41.  
  42. #if AMIGA || ARM || ATARI_ST || MSDOS || MVS || VM || OS2 || UNIX\
  43.    || VMS
  44.    /* nothing needed */
  45. #endif                    /* AMIGA || ARM || ATARI_ST ... */
  46.  
  47. /*
  48.  * End of operating-system specific code.
  49.  */
  50.  
  51. extern set_up;
  52.  
  53. /*
  54.  * A number of important variables follow.
  55.  */
  56.  
  57. #ifndef MultiThread
  58. int n_globals = 0;            /* number of globals */
  59. int n_statics = 0;            /* number of statics */
  60. #endif                    /* MultiThread */
  61.  
  62. extern int_setup;
  63.  
  64.  
  65. /*
  66.  * Initial icode sequence. This is used to invoke the main procedure with one
  67.  *  argument.  If main returns, the Op_Quit is executed.
  68.  */
  69. word istart[4];
  70. int mterm = Op_Quit;
  71.  
  72.  
  73.  
  74. #ifdef MSWindows
  75. int CmdParamToArgv(char *s, char ***avp)
  76.    {
  77.    char *t, *t2;
  78.    int rv=0;
  79.    t = salloc(s);
  80.    t2 = t;
  81.    while (*t2) {
  82.       while (*t2 && isspace(*t2)) t2++;
  83.       if (!*t2) break;
  84.       rv++;
  85.       while (*t2 && !isspace(*t2)) t2++;
  86.       }
  87.    rv++; /* make room for "iconx" at front */
  88.    *avp = (char **)alloc((rv + 1) * sizeof(char *));
  89.    rv = 0;
  90.    (*avp)[rv++] = salloc("iconx.exe");
  91.    t2 = t;
  92.    while (*t2) {
  93.       while (*t2 && isspace(*t2)) t2++;
  94.       if (!*t2) break;
  95.       (*avp)[rv++] = t2;
  96.       while (*t2 && !isspace(*t2)) t2++;
  97.       if (*t2) *t2++ = '\0';
  98.       }
  99.    (*avp)[rv] = NULL;
  100.    return rv;  
  101.    }
  102.  
  103. novalue MSStartup(HINSTANCE hInstance, HINSTANCE hPrevInstance)
  104.    {
  105.    WNDCLASS wc;
  106.    if (!hPrevInstance) {
  107. #if NT
  108.       wc.style = CS_HREDRAW | CS_VREDRAW;
  109. #else                    /* NT */
  110.       wc.style = 0;
  111. #endif                    /* NT */
  112.       wc.lpfnWndProc = WndProc;
  113.       wc.cbClsExtra = 0;
  114.       wc.cbWndExtra = 0;
  115.       wc.hInstance  = hInstance;
  116.       wc.hIcon      = NULL;
  117.       wc.hCursor    = LoadCursor(NULL, IDC_ARROW);
  118.       wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  119.       wc.lpszMenuName = NULL;
  120.       wc.lpszClassName = "iconx";
  121.       RegisterClass(&wc);
  122.       }
  123.    }
  124.  
  125. void iconx(int argc, char **argv);
  126.  
  127. jmp_buf mark_sj;
  128.  
  129. int_PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  130.                    LPSTR lpszCmdLine, int nCmdShow)
  131.    {
  132.    int argc;
  133.    char **argv;
  134.  
  135.    mswinInstance = hInstance;
  136.    ncmdShow = nCmdShow;
  137.    argc = CmdParamToArgv(lpszCmdLine, &argv);
  138.    MSStartup(hInstance, hPrevInstance);
  139.    if (setjmp(mark_sj) == 0)
  140.       iconx(argc,argv);
  141.    wfreersc();
  142.    return 0;
  143. }
  144. #define main iconx
  145. #endif                    /* MSWindows */
  146.  
  147. #if OS2
  148. int stubexe;
  149. novalue os2main(int stubflag, int argc, char**argv); /* Prototype OS2main */
  150. novalue os2main(stubflag, argc, argv)
  151. int stubflag;
  152. #else                    /* OS2 */
  153. #ifdef MacGraph
  154. MouseInfoType gMouseInfo;
  155. PaletteHandle gPal;
  156. long gNumColors;
  157. Boolean gDone;
  158. char *cmlArgs;
  159. StringHandle textHandle;
  160.  
  161. novalue MacMain (argc, argv)
  162. #else                    /* MacGraph */
  163. novalue main(argc, argv)
  164. #endif                    /* MacGraph */
  165. #endif                    /* OS2 */
  166. int argc;
  167. char **argv;
  168.    {
  169.    int i, slen;
  170.  
  171. #if AMIGA
  172. #if AZTEC_C
  173.    struct Process *FindTask();
  174.    struct Process *Process = FindTask(0L);
  175.    ULONG stacksize = *((ULONG *)Process->pr_ReturnAddr);
  176.  
  177.    if (stacksize < ICONXMINSTACK) {
  178.       fprintf(stderr,"Iconx needs \"stack %d\" to run\n",ICONXMINSTACK);
  179.       exit(-1);
  180.       }
  181. #endif                    /* AZTEC_C */
  182. #endif                    /* AMIGA */
  183.  
  184. #ifdef SuppressAlignmentMsg
  185.    {
  186.       /*
  187.        * suppress "Unaligned access" messages on Dec Alpha.
  188.        */
  189.       int buf[] = {SSIN_UACPROC, UAC_NOPRINT};
  190.       setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0);
  191.    }
  192. #endif                /* SuppressAlignmentMsg */
  193.  
  194. #if SASC
  195.    quiet(1);                    /* suppress C library diagnostics */
  196. #endif                    /* SASC */
  197.  
  198. #ifdef MultiThread
  199.    /*
  200.     * Look for MultiThread programming environment in which to execute
  201.     * this program, specified by MTENV environment variable.
  202.     */
  203.    {
  204.    char *p;
  205.    char **new_argv;
  206.    int i, j = 1, k = 1;
  207.    if ((p = getenv("MTENV")) != NULL) {
  208.       for(i=0;p[i];i++)
  209.      if (p[i] == ' ')
  210.         j++;
  211.       new_argv = (char **)malloc((argc + j) * sizeof(char *));
  212.       new_argv[0] = argv[0];
  213.       for (i=0; p[i]; ) {
  214.      new_argv[k++] = p+i;
  215.      while (p[i] && (p[i] != ' '))
  216.         i++;
  217.      if (p[i] == ' ')
  218.         p[i++] = '\0';
  219.      }
  220.       for(i=1;i<argc;i++)
  221.      new_argv[k++] = argv[i];
  222.       argc += j;
  223.       argv = new_argv;
  224.       }
  225.    }
  226. #endif                    /* MultiThread */
  227.  
  228.    ipc.opnd = NULL;
  229.  
  230.    /*
  231.     * Setup Icon interface.  It's done this way to avoid duplication
  232.     *  of code, since the same thing has to be done if calling Icon
  233.     *  is enabled.  See istart.c.
  234.     */
  235.  
  236. #ifdef CRAY
  237.    argv[0] = "iconx";
  238. #endif                    /* CRAY */
  239.  
  240. #if OS2
  241.    if (stubflag) {  /* Invoked as a direct executable */
  242.       stubexe = 1;
  243.       icon_init(argv[0],&argc, argv);
  244.       argc += 2;
  245.       argv -= 2;
  246.       }
  247.    else {
  248.       stubexe = 0;
  249.       icon_setup(argc, argv, &i);
  250.       if (i < 0) {
  251.      argc++;
  252.      argv--;
  253.      i++;
  254.      }
  255.       while (i--) {                /* skip option arguments */
  256.      argc--;
  257.      argv++;
  258.      }
  259.  
  260.       if (argc <= 1)
  261.      error(NULL, "An icode file was not specified.\nExecution cannot proceed.");
  262.       /*
  263.        * Call icon_init with the name of the icode file to execute.        [[I?]]
  264.        */
  265.  
  266.       icon_init(argv[1], &argc, argv);
  267.       }
  268. #else                    /* PresentationManager */
  269.    icon_setup(argc, argv, &i);
  270.  
  271.    if (i < 0) {
  272.       argc++;
  273.       argv--;
  274.       i++;
  275.       }
  276.  
  277.    while (i--) {            /* skip option arguments */
  278.       argc--;
  279.       argv++;
  280.       }
  281.  
  282.    if (argc <= 1) 
  283.       error(NULL, "no icode file specified");
  284.    /*
  285.     * Call icon_init with the name of the icode file to execute.    [[I?]]
  286.     */
  287.    icon_init(argv[1], &argc, argv);
  288. #endif                    /* OS2 */
  289.  
  290.    /*
  291.     *  Point sp at word after b_coexpr block for &main, point ipc at initial
  292.     *    icode segment, and clear the gfp.
  293.     */
  294.  
  295.    stackend = stack + mstksize/WordSize;
  296.    sp = stack + Wsizeof(struct b_coexpr);
  297.  
  298.    ipc.opnd = istart;
  299.    *ipc.op++ = Op_Noop;  /* aligns Invoke's operand */    /*    [[I?]] */
  300.    *ipc.op++ = Op_Invoke;                /*    [[I?]] */
  301.  
  302. #if AMIGA
  303.    istart[0] = Op_Invoke;
  304.    istart[1] = 1;
  305.    istart[2] = Op_Quit;
  306. #else                    /* AMIGA */
  307.    *ipc.opnd++ = 1;
  308.    *ipc.op = Op_Quit;
  309.    ipc.opnd = istart;
  310. #endif                    /* AMIGA */
  311.  
  312.    gfp = 0;
  313.  
  314.    /*
  315.     * Set up expression frame marker to contain execution of the
  316.     *  main procedure.  If failure occurs in this context, control
  317.     *  is transferred to mterm, the address of an Op_Quit.
  318.     */
  319.    efp = (struct ef_marker *)(sp);
  320.    efp->ef_failure.op = &mterm;
  321.    efp->ef_gfp = 0;
  322.    efp->ef_efp = 0;
  323.    efp->ef_ilevel = 1;
  324.    sp += Wsizeof(*efp) - 1;
  325.  
  326.    pfp = 0;
  327.    ilevel = 0;
  328.  
  329. /*
  330.  * We have already loaded the
  331.  * icode and initialized things, so it's time to just push main(),
  332.  * build an Icon list for the rest of the arguments, and called
  333.  * interp on a "invoke 1" bytecode.
  334.  */
  335.    /*
  336.     * The first global variable holds the value of "main".  If it
  337.     *  is not of type procedure, this is noted as run-time error 117.
  338.     *  Otherwise, this value is pushed on the stack.
  339.     */
  340.    if (globals[0].dword != D_Proc)
  341.       fatalerr(117, NULL);
  342.    PushDesc(globals[0]);
  343.    PushNull;
  344.    argp = (dptr)(sp - 1);
  345.  
  346.    /*
  347.     * If main() has a parameter, it is to be invoked with one argument, a list
  348.     *  of the command line arguments.  The command line arguments are pushed
  349.     *  on the stack as a series of descriptors and Ollist is called to create
  350.     *  the list.  The null descriptor first pushed serves as Arg0 for
  351.     *  Ollist and receives the result of the computation.
  352.     */
  353.  
  354.    if (((struct b_proc *)BlkLoc(globals[0]))->nparam > 0) {
  355.       for (i = 2; i < argc; i++) {
  356.          char *tmp;
  357.          slen = strlen(argv[i]);
  358.          PushVal(slen);
  359.          Protect(tmp=alcstr(argv[i],(word)slen), fatalerr(0,NULL));
  360.          PushAVal(tmp);
  361.          }
  362.  
  363.       Ollist(argc - 2, argp);
  364.       }
  365.  
  366.  
  367.    sp = (word *)argp + 1;
  368.    argp = 0;
  369.  
  370.    set_up = 1;            /* post fact that iconx is initialized */
  371.  
  372.    /*
  373.     * Start things rolling by calling interp.  This call to interp
  374.     *  returns only if an Op_Quit is executed.    If this happens,
  375.     *  c_exit() is called to wrap things up.
  376.     */
  377.  
  378. #ifdef CoProcesses
  379.    codisp();    /* start up co-expr dispatcher, which will call interp */
  380. #else                    /* CoProcesses */
  381.    interp(0,(dptr)NULL);                        /*      [[I?]] */
  382. #endif                    /* CoProcesses */
  383.  
  384.    c_exit(NormalExit);
  385. }
  386.  
  387. /*
  388.  * icon_setup - handle interpreter command line options.
  389.  */
  390. novalue icon_setup(argc,argv,ip)
  391. int argc;
  392. char **argv;
  393. int *ip;
  394.    {
  395.  
  396. #ifdef TallyOpt
  397.    extern int tallyopt;
  398. #endif                    /* TallyOpt */
  399.  
  400.    *ip = 0;            /* number of arguments processed */
  401.  
  402. #ifdef ExecImages
  403.    if (dumped) {
  404.       /*
  405.        * This is a restart of a dumped interpreter.  Normally, argv[0] is
  406.        *  iconx, argv[1] is the icode file, and argv[2:(argc-1)] are the
  407.        *  arguments to pass as a list to main().  For a dumped interpreter
  408.        *  however, argv[0] is the executable binary, and the first argument
  409.        *  for main() is argv[1].  The simplest way to handle this is to
  410.        *  back up argv to point at argv[-1] and increment argc, giving the
  411.        *  illusion of an additional argument at the head of the list.  Note
  412.        *  that this argument is never referenced.
  413.        */
  414.       argv--;
  415.       argc++;
  416.       (*ip)--;
  417.       }
  418. #endif                    /* ExecImages */
  419.  
  420. #ifdef MaxLevel
  421.    maxilevel = 0;
  422.    maxplevel = 0;
  423.    maxsp = 0;
  424. #endif                    /* MaxLevel */
  425.  
  426. #if MACINTOSH
  427. #if MPW
  428.    InitCursorCtl(NULL);
  429.    /*
  430.     * To support the icode and iconx interpreter bundled together in
  431.     * the same file, we might have to use this code file as the icode
  432.     * file, too.  We do this if the command name is not 'iconx'.
  433.     */
  434.    {
  435.    char *p,*q,c,fn[6];
  436.  
  437.    /*
  438.     * Isolate the filename from the path.
  439.     */
  440.    q = strrchr(*argv,':');
  441.    if (q == NULL)
  442.        q = *argv;
  443.    else
  444.        ++q;
  445.    /*
  446.     * See if it's the real iconx -- case independent compare.
  447.     */
  448.    p = fn;
  449.    if (strlen(q) == 5)
  450.       while (c = *q++) *p++ = tolower(c);
  451.    *p = '\0';
  452.    if (strcmp(fn,"iconx") != 0) {
  453.      /*
  454.       * This technique of shifting arguments relies on the fact that
  455.       * argv[0] is never referenced, since this will make it invalid.
  456.       */
  457.       --argv;
  458.       ++argc;
  459.       --(*ip);
  460.       /*
  461.        * We don't want to look for any command line options in this
  462.        * case.  They could interfere with options for the icon
  463.        * program.
  464.        */
  465.       NoOptions = 1;
  466.       }
  467.    }
  468. #endif                    /* MPW */
  469. #endif                                  /* MACINTOSH */
  470.  
  471. /*
  472.  * Handle command line options.
  473. */
  474. #if MACINTOSH && MPW
  475.    if (!NoOptions)
  476. #endif                    /* MACINTOSH && MPW */
  477.    while ( argv[1] != 0 && *argv[1] == '-' ) {
  478.       switch ( *(argv[1]+1) ) {
  479.  
  480. #ifdef TallyOpt
  481.     /*
  482.      * Set tallying flag if -T option given
  483.      */
  484.     case 'T':
  485.         tallyopt = 1;
  486.         break;
  487. #endif                    /* TallyOpt */
  488.  
  489.       /*
  490.        * Set stderr to new file if -e option is given.
  491.        */
  492.      case 'e': {
  493.         char *p;
  494.         if ( *(argv[1]+2) != '\0' )
  495.            p = argv[1]+2;
  496.         else {
  497.            argv++;
  498.            argc--;
  499.                (*ip)++;
  500.            p = argv[1];
  501.            if ( !p )
  502.           error(NULL, "no file name given for redirection of &errout");
  503.            }
  504.             if (!redirerr(p))
  505.                syserr("Unable to redirect &errout\n");
  506.         break;
  507.         }
  508.         }
  509.     argc--;
  510.         (*ip)++;
  511.     argv++;
  512.       }
  513.    }
  514.  
  515. /*
  516.  * resolve - perform various fix-ups on the data read from the icode
  517.  *  file.
  518.  */
  519. #ifdef MultiThread            /* MultiThread */
  520. novalue resolve(pstate)
  521. struct progstate *pstate;
  522. #else                    /* MultiThread */
  523. novalue resolve()
  524. #endif                    /* MultiThread */
  525.  
  526.    {
  527.    register word i, j;
  528.    register struct b_proc *pp;
  529.    register dptr dp;
  530.    extern Omkrec();
  531.    extern int ftsize;
  532.  
  533. #ifdef MultiThread
  534.    register struct progstate *savedstate;
  535. #endif                    /* MultiThread */
  536.  
  537.  
  538. #ifdef MultiThread
  539.    savedstate = curpstate;
  540.    if (pstate) curpstate = pstate;
  541. #endif                    /* MultiThread */
  542.  
  543.    /*
  544.     * Relocate the names of the global variables.
  545.     */
  546.    for (dp = gnames; dp < egnames; dp++)
  547.       StrLoc(*dp) = strcons + (uword)StrLoc(*dp);
  548.  
  549.    /*
  550.     * Scan the global variable array for procedures and fill in appropriate
  551.     *  addresses.
  552.     */
  553.    for (j = 0; j < n_globals; j++) {
  554.  
  555.       if (globals[j].dword != D_Proc)
  556.          continue;
  557.  
  558.       /*
  559.        * The second word of the descriptor for procedure variables tells
  560.        *  where the procedure is.  Negative values are used for built-in
  561.        *  procedures and positive values are used for Icon procedures.
  562.        */
  563.       i = IntVal(globals[j]);
  564.  
  565.       if (i < 0) {
  566.          /*
  567.           * globals[j] points to a built-in function; call (bi_)strprc
  568.       *  to look it up by name in the interpreter's table of built-in
  569.       *  functions.
  570.           */
  571.      if((BlkLoc(globals[j])= (union block *)bi_strprc(gnames+j,0)) == NULL)
  572.             globals[j] = nulldesc;        /* undefined, set to &null */
  573.          }
  574.       else {
  575.  
  576.          /*
  577.           * globals[j] points to an Icon procedure or a record; i is an offset
  578.           *  to location of the procedure block in the code section.  Point
  579.           *  pp at the block and replace BlkLoc(globals[j]).
  580.           */
  581.          pp = (struct b_proc *)(code + i);
  582.          BlkLoc(globals[j]) = (union block *)pp;
  583.  
  584.          /*
  585.           * Relocate the address of the name of the procedure.
  586.           */
  587.          StrLoc(pp->pname) = strcons + (uword)StrLoc(pp->pname);
  588.  
  589. #ifdef MultiThread
  590.          pp->program = curpstate;
  591. #endif                    /* MultiThread */
  592.  
  593.          if (pp->ndynam == -2) {
  594.             /*
  595.              * This procedure is a record constructor.    Make its entry point
  596.              *    be the entry point of Omkrec().
  597.              */
  598.             pp->entryp.ccode = Omkrec;
  599.  
  600.         /*
  601.          * Initialize field names
  602.          */
  603.             for (i = 0; i < pp->nfields; i++)
  604.                StrLoc(pp->lnames[i]) = strcons + (uword)StrLoc(pp->lnames[i]);
  605.  
  606.         }
  607.          else {
  608.             /*
  609.              * This is an Icon procedure.  Relocate the entry point and
  610.              *    the names of the parameters, locals, and static variables.
  611.              */
  612.             pp->entryp.icode = code + pp->entryp.ioff;
  613.             for (i = 0; i < abs((int)pp->nparam)+pp->ndynam+pp->nstatic; i++)
  614.                StrLoc(pp->lnames[i]) = strcons + (uword)StrLoc(pp->lnames[i]);
  615.             }
  616.          }
  617.       }
  618.  
  619.    /*
  620.     * Relocate the names of the fields.
  621.     */
  622.  
  623.    for (dp = fnames; dp < efnames; dp++)
  624.       StrLoc(*dp) = strcons + (uword)StrLoc(*dp);
  625.  
  626. #ifdef MultiThread
  627.    curpstate = savedstate;
  628. #endif                        /* MultiThread */
  629.    }
  630.  
  631.  
  632. /*
  633.  * Free malloc-ed memory; the main regions then co-expressions.  Note:
  634.  *  this is only correct if all allocation is done by routines that are
  635.  *  compatible with free() -- which may not be the case if Allocreg()
  636.  *  in rmemfix.c is defined to be other than malloc().
  637.  */
  638.  
  639. novalue xmfree()
  640.    {
  641.    register struct b_coexpr **ep, *xep;
  642.    register struct astkblk *abp, *xabp;
  643.  
  644.    if (mainhead != (struct b_coexpr *)NULL)
  645.       free((pointer)mainhead->es_actstk);    /* activation block for &main */
  646.    free((pointer)code);            /* icode */
  647.    code = NULL;
  648.    free((pointer)stack);        /* interpreter stack */
  649.    stack = NULL;
  650.    free((pointer)strbase);        /* allocated string region */
  651.    strbase = NULL;
  652.    free((pointer)blkbase);        /* allocated block region */
  653.    blkbase = NULL;
  654.    free((pointer)quallist);        /* qualifier list */
  655.    quallist = NULL;
  656.  
  657.    /*
  658.     * The co-expression blocks are linked together through their
  659.     *  nextstk fields, with stklist pointing to the head of the list.
  660.     *  The list is traversed and each stack is freeing.
  661.     */
  662.    ep = &stklist;
  663.    while (*ep != NULL) {
  664.       xep = *ep;
  665.       *ep = (*ep)->nextstk;
  666.        /*
  667.         * Free the astkblks.  There should always be one and it seems that
  668.         *  it's not possible to have more than one, but nonetheless, the
  669.         *  code provides for more than one.
  670.         */
  671.       for (abp = xep->es_actstk; abp; ) {
  672.             xabp = abp;
  673.             abp = abp->astk_nxt;
  674.             free((pointer)xabp);
  675.             }
  676.  
  677. #ifdef CoProcesses
  678.          coswitch(BlkLoc(k_current)->coexpr.cstate, xep->cstate, -1);
  679.                 /* terminate coproc for coexpression first */
  680. #endif                    /* CoProcesses */
  681.  
  682.       free((pointer)xep);
  683.       stklist = NULL;
  684.       }
  685.  
  686.    }
  687. #endif                    /* !COMPILER */
  688.  
  689.  
  690. #ifdef MacGraph
  691. void MouseInfoInit (void)
  692. {
  693.    gMouseInfo.wasDown = false;
  694. }
  695.  
  696. void ToolBoxInit (void)
  697. {
  698.    InitGraf (&qd.thePort);
  699.    InitFonts ();
  700.    InitWindows ();
  701.    InitMenus ();
  702.    TEInit ();
  703.    InitDialogs (nil);
  704.    InitCursor ();
  705. }
  706.  
  707. void MenuBarInit (void)
  708. {
  709.    Handle         menuBar;
  710.    MenuHandle     menu;
  711.    OSErr          myErr;
  712.    long           feature;
  713.    
  714.    menuBar = GetNewMBar (kMenuBar);
  715.    SetMenuBar (menuBar);
  716.    
  717.    menu = GetMHandle (kAppleMenu);
  718.    AddResMenu (menu, 'DRVR');
  719.    
  720.    DrawMenuBar ();
  721. }
  722.  
  723. void EventLoop ( void )
  724. {
  725.    EventRecord event, *eventPtr;
  726.    char theChar;
  727.    
  728.    gDone = false;
  729.    while ( gDone == false )
  730.    {
  731.       if ( WaitNextEvent ( everyEvent, &event, kSleep, nil ) ) 
  732.          DoEvent ( &event );
  733.    }
  734. }
  735.  
  736. void main ()
  737. {
  738.    atexit (EventLoop);
  739.    ToolBoxInit ();
  740.    MenuBarInit ();
  741.    MouseInfoInit ();
  742.    cmlArgs = "";
  743.    
  744.    EventLoop ();
  745. }
  746. #endif                    /* MacGraph */
  747.