home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / SPIM Folder / Sources / macspim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-03  |  15.6 KB  |  729 lines  |  [TEXT/KAHL]

  1. /* SPIM S20 MIPS simulator.
  2.    Copyright (C) 1990 by James Larus (larus@cs.wisc.edu).
  3.  
  4.    Macintosh Version by Philip Delaquess (delaques@gcg.com)
  5.    Copyright (C) 1993 by Saunders College Publishing and Morgan Kaufman Publishers.
  6.  
  7.    SPIM is free software; you can redistribute it and/or modify it
  8.    under the terms of the GNU General Public License as published by the
  9.    Free Software Foundation; either version 1, or (at your option) any
  10.    later version.
  11.  
  12.    SPIM is distributed in the hope that it will be useful, but WITHOUT
  13.    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14.    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15.    for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with GNU CC; see the file COPYING.  If not, write to James R.
  19.    Larus, Computer Sciences Department, University of Wisconsin--Madison,
  20.    1210 West Dayton Street, Madison, WI 53706, USA or to the Free
  21.    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22. */
  23.  
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include <setjmp.h>
  27.  
  28. #include "mactext.h"
  29.  
  30. #include "spim.h"
  31. #include "inst.h"
  32. #include "mem.h"
  33. #include "reg.h"
  34.  
  35. char mess_buff[256];
  36. int source_file;
  37.  
  38. static Boolean running = TRUE, RunningCPU = FALSE;
  39.  
  40. DialogPtr RunningDlg; /* this little f--ker is global */
  41. static DialogPtr RunDlg, StepDlg, BreakpointsDlg, PrintDlg, SetDlg;
  42. static Rect DragBoundary;
  43.  
  44. static SPIMTextWindow TextWindow, DataWindow, ConsoleWindow, SessionWindow;
  45.  
  46. static jmp_buf JumpBuff;
  47.  
  48. static short StartupVolume; /* where trap handler must reside */
  49.  
  50. static CursHandle WristWatch;
  51.  
  52. /* This handles fatal errors from all over. */
  53.  
  54. void MacFatalError(char *message)
  55. {
  56.     char *s;
  57.     DialogPtr dialog;
  58.     short item;
  59.  
  60.     FreeMacMemory();
  61.     for (s = message; *s; ++s)
  62.         if ( *s < ' ' ) *s = ' ';
  63.     CtoPstr(message);
  64.     ParamText(message, "\p", "\p", "\p");
  65.     dialog = GetNewDialog(136, 0, (WindowPtr) -1);
  66.     InitCursor();
  67.     ModalDialog(0, &item);
  68.     ExitToShell();
  69. } /* MacFatalError */
  70.  
  71. /* This tells the user why SPIM stopped, and asks what to do.
  72.    It returns TRUE if the user want to keep going, or FALSE if she wants to abort.
  73. */
  74.  
  75. static Boolean doHaltDialog(Boolean interrupted)
  76. {
  77.     char pcString[32];
  78.     DialogPtr dialog;
  79.     short item;
  80.  
  81.     sprintf(pcString, "0x%08X", PC);
  82.     CtoPstr(pcString);
  83.     ParamText(interrupted ? "\pInterrupted" : "\pBreakpoint",
  84.                 pcString, "\p", "\p");
  85.     dialog = GetNewDialog(135, 0, (WindowPtr) -1);
  86.     ModalDialog(0, &item);
  87.     DisposDialog(dialog);
  88.     return item == 1 ? TRUE : FALSE;
  89. } /* doHaltDialog */
  90.  
  91. /* This reports normal completion of a program. Is this necessary? */
  92.  
  93. static void reportCompletion()
  94. {
  95. #if 0
  96.     static DialogPtr dialog;
  97.     short item;
  98.  
  99.     if ( !dialog )
  100.         dialog = GetNewDialog(137, 0, (WindowPtr) -1);
  101.     else {
  102.         ShowWindow(dialog);
  103.         SelectWindow(dialog);
  104.     }
  105.     ModalDialog(0, &item);
  106.     HideWindow(dialog);
  107. #endif
  108. } /* reportCompletion */
  109.  
  110. /* This prepares for a long jump, then runs the program for a while. */
  111.  
  112. static void execute_program(mem_addr start, int steps, int display, int cont)
  113. {
  114.     PC = start;
  115.     while ( 1 ) {
  116.         /* are we being sent here by a long jump? */
  117.         if ( setjmp(JumpBuff) ) {
  118.             /* interrupted -- do we continue? */
  119.             HideWindow(RunningDlg);
  120.             if ( !doHaltDialog(TRUE) )
  121.                 break; /* do not continue */
  122.             else {
  123.                 /* convert to a run command even if we were stepping */
  124.                 steps = DEFAULT_RUN_STEPS;
  125.                 display = 0;
  126.                 cont = 0;
  127.             }
  128.         }
  129.         /* start or continue running */
  130.         ShowWindow(RunningDlg);
  131.         SelectWindow(RunningDlg);
  132.         RunningCPU = TRUE;
  133.         if ( !run_program(PC, steps, display, cont) ) {
  134.             /* no breakpoint -- all done */
  135.             RunningCPU = FALSE;
  136.             HideWindow(RunningDlg);
  137.             if ( !display )
  138.                 reportCompletion();
  139.             break;
  140.         }
  141.         /* breakpoint -- do we continue? */
  142.         RunningCPU = FALSE;
  143.         HideWindow(RunningDlg);
  144.         if ( !doHaltDialog(FALSE) )
  145.             break;
  146.         /* step over the breakpoint */
  147.         RunningCPU = TRUE;
  148.         run_program(PC, 1, display, 1);
  149.         RunningCPU = FALSE;
  150.     }
  151. } /* execute_program */
  152.  
  153. /* This sees if the Halt button in the program run dialog got nailed. */
  154.  
  155. int IntCheck()
  156. {
  157.     EventRecord event;
  158.     DialogPtr dlg;
  159.     short item;
  160.  
  161.     if ( GetNextEvent(everyEvent, &event) ) {
  162.         if ( IsDialogEvent(&event) ) {
  163.             if ( DialogSelect(&event, &dlg, &item) && dlg == RunningDlg && item == 2 )
  164.                 return 1;
  165.         }
  166.     }
  167.     return 0;
  168. } /* IntCheck */
  169.  
  170. /* This copes with the detection of an interrupt. */
  171.  
  172. void control_c_seen()
  173. {
  174.     longjmp(JumpBuff, 1);
  175. } /* control_c_seen */
  176.  
  177. /* This gets a dialog's edit text as a C string. */
  178.  
  179. static void getITextAsCStr(DialogPtr dialog, short item, char *text)
  180. {
  181.     short type;
  182.     Handle handle;
  183.     Rect box;
  184.     Str255 result;
  185.  
  186.     GetDItem(dialog, item, &type, &handle, &box);
  187.     GetIText(handle, result);
  188.     PtoCstr(result);
  189.     strcpy(text, (char *) result);
  190. } /* getITextAsCStr */
  191.  
  192. /* This handles the buttons in the Step dialog. */
  193.  
  194. static void doStep(short item)
  195. {
  196.     char nsText[256];
  197.     int address, nSteps;
  198.  
  199.     getITextAsCStr(StepDlg, 2, nsText);
  200.     sscanf(nsText, "%d", &nSteps);
  201.     address = starting_address();
  202.     switch ( item ) {
  203.     case 3 :
  204.         /* step */
  205.         execute_program(address, nSteps, 1, 1);
  206.         FormatRegisters();
  207.         if ( data_modified )
  208.             CountData();
  209.         data_modified = 0;
  210.         RecenterText();
  211.         break;
  212.     case 4 :
  213.         /* run */
  214.         HideWindow(StepDlg);
  215.         execute_program(address, DEFAULT_RUN_STEPS, 0, 0);
  216.         FormatRegisters();
  217.         if ( data_modified )
  218.             CountData();
  219.         data_modified = 0;
  220.         RecenterText();
  221.         break;
  222.     }
  223. } /* doStep */
  224.  
  225. static void doRun()
  226. {
  227.     char aText[256];
  228.     int address;
  229.  
  230.     if ( PC )
  231.         address = PC;
  232.     else
  233.         address = find_symbol_address(DEFAULT_RUN_LOCATION);
  234.     getITextAsCStr(RunDlg, 2, aText);
  235.     sscanf(aText, "%d", &address);
  236.     if ( !address )
  237.         address = starting_address();
  238.     HideWindow(RunDlg);
  239.     execute_program(address, DEFAULT_RUN_STEPS, 0, 0);
  240.     FormatRegisters();
  241.     if ( data_modified )
  242.         CountData();
  243.     data_modified = 0;
  244.     RecenterText();
  245. } /* doRun */
  246.  
  247. /* This performs a set values command. */
  248.  
  249. static void setValues()
  250. {
  251.     char address[256], *p, *q, *eptr, ebuf[256];
  252.     mem_word value, addr;
  253.     int reg_no;
  254.  
  255.     getITextAsCStr(SetDlg, 4, address);
  256.     value = strtoul(address, NULL, 16);
  257.     getITextAsCStr(SetDlg, 2, address);
  258.  
  259.     for (p = address; isspace(*p); ++p)
  260.         ;
  261.     for (q = p; *q; ++q)
  262.         if ( *q >= 'a' && *q <= 'z' )
  263.             *q += 'A' - 'a';
  264.  
  265.     if ( (reg_no = register_name_to_number(p)) < 0 ) {
  266.         if ( strchr("Rr$", *p) )
  267.             reg_no = register_name_to_number(p + 1);
  268.     }
  269.  
  270.     if ( !reg_no )
  271.         error("Cannot modify register zero.\n");
  272.     else if ( reg_no > 0 ) {
  273.         R[reg_no] = value;
  274.         FormatRegisters();
  275.     }
  276.     else if ( !strncmp(p, "STATUS", 6) ) {
  277.         Status_Reg = value;
  278.         FormatRegisters();
  279.     }
  280.     else if ( !strncmp(p, "EPC", 3) ) {
  281.         EPC = value;
  282.         FormatRegisters();
  283.     }
  284.     else if ( !strncmp(p, "PC", 2) ) {
  285.         PC = value;
  286.         FormatRegisters();
  287.     }
  288.     else {
  289.         addr = strtoul(p, &eptr, 16);
  290.         if ( eptr == p ) {
  291.             sprintf(ebuf, "Unknown location: %s\n", p);
  292.             error(ebuf);
  293.         }
  294.         else {
  295.             SET_MEM_WORD(addr, value);
  296.             CountData();
  297.         }
  298.     }
  299. } /* setValues */
  300.  
  301. /* This turns the text of an address spec into an address. */
  302.  
  303. static mem_addr getAddress(char *p)
  304. {
  305.     while(isspace(*p))
  306.         p++;
  307.     if(isdigit(*p))
  308.         return strtoul(p, NULL, 16);
  309.     else
  310.         return find_symbol_address(p);
  311. } /* end getAddress() */
  312.  
  313. /* This performs a print values command. */
  314.  
  315. static void printValues(short item)
  316. {
  317.     mem_addr from, to;
  318.     char address[256];
  319.  
  320.     if ( item == 6 )
  321.         print_symbols();
  322.     else {
  323.         getITextAsCStr(PrintDlg, 2, address);
  324.         from = getAddress(address);
  325.         getITextAsCStr(PrintDlg, 4, address);
  326.         to = getAddress(address);
  327.         do
  328.             print_mem(from);
  329.         while ( (from += BYTES_PER_WORD) <= to );
  330.     }
  331. } /* printValues */
  332.  
  333. /* This handles a button in the breakpoints dialog. */
  334.  
  335. static void doBreakpoint(short item)
  336. {
  337.     char address[256];
  338.  
  339.     getITextAsCStr(BreakpointsDlg, 2, address);
  340.     switch ( item ) {
  341.     case 3 :
  342.         add_breakpoint(getAddress(address));
  343.         break;
  344.     case 4 :
  345.         delete_breakpoint(getAddress(address));
  346.         break;
  347.     case 5 :
  348.         list_breakpoints();
  349.         break;
  350.     }
  351. } /* doBreakpoint */
  352.  
  353. /* This handles a hit on any of my dialog buttons. */
  354.  
  355. static void doDialogEvent(DialogPtr dialog, short item)
  356. {
  357.     if ( dialog == SetDlg )
  358.         setValues();
  359.     else if ( dialog == PrintDlg )
  360.         printValues(item);
  361.     else if ( dialog == BreakpointsDlg )
  362.         doBreakpoint(item);
  363.     else if ( dialog == StepDlg )
  364.         doStep(item);
  365.     else if ( dialog == RunDlg )
  366.         doRun();
  367. } /* doDialogEvent */
  368.  
  369. static void showAboutBox()
  370. {
  371.     DialogPtr dlg;
  372.     short item;
  373.  
  374.     dlg = GetNewDialog(128, 0, (WindowPtr) -1);
  375.     ModalDialog(0, &item);
  376.     DisposDialog(dlg);
  377. } /* showAboutBox */
  378.  
  379. /* This puts up the standard input file dialog. If the user picks a file, we
  380.    hand it off to the parser.
  381. */
  382.  
  383. static void selectLoadFile()
  384. {
  385.     Point upperLeft;
  386.     SFTypeList typeList;
  387.     SFReply reply;
  388.     extern Boolean Assembling;
  389.     extern short MessageCount;
  390.  
  391.     upperLeft.h = upperLeft.v = 100;
  392.     typeList[0] = 'TEXT';
  393.     SFGetFile(upperLeft, "\p", 0, 1, typeList, 0, &reply);
  394.     if ( reply.good ) {
  395.         SetVol(0, reply.vRefNum);
  396.         PtoCstr(reply.fName);
  397.         MessageCount = 0;
  398.         Assembling = TRUE;
  399.         SetCursor(*WristWatch);
  400.         read_assembly_file((char *) (reply.fName));
  401.         Assembling = FALSE;
  402.         CountText();
  403.         CountData();
  404.         InitCursor();
  405.         write_output(message_out, "Loaded ");
  406.         write_output(message_out, (char *) reply.fName);
  407.         write_output(message_out, ".\n");
  408.     }
  409. } /* selectLoadFile */
  410.  
  411. static void doMenuEvent(long resultCode)
  412. {
  413.     short menuCode, itemCode, currentVolume, type;
  414.     Handle hand;
  415.     Rect box;
  416.     mem_addr address;
  417.     Str255 addrStr;
  418.  
  419.     menuCode = HiWord(resultCode);
  420.     itemCode = LoWord(resultCode);
  421.     switch ( menuCode ) {
  422.     case 128 :
  423.         /* apple menu */
  424.         if ( itemCode == 1 )
  425.             showAboutBox();
  426.         else if ( itemCode == 2 )
  427.             SelectTextWindow(&Help);
  428.         else {
  429.             Str255 theItem;
  430.             GetItem(GetMHandle(menuCode), itemCode, theItem);
  431.             OpenDeskAcc(theItem);
  432.         }
  433.         break;
  434.     case 129 :
  435.         /* file menu */
  436.         switch ( itemCode ) {
  437.         case 1 :
  438.             selectLoadFile();
  439.             break;
  440.         case 4 :
  441.             running = FALSE;
  442.             break;
  443.         }
  444.         break;
  445.     case 130 :
  446.         /* edit menu */
  447.         break;
  448.     case 131 :
  449.         /* window menu */
  450.         switch ( itemCode ) {
  451.         case 1 :
  452.             SelectTextWindow(&Registers);
  453.             break;
  454.         case 2 :
  455.             SelectTextWindow(&Text);
  456.             break;
  457.         case 3 :
  458.             SelectTextWindow(&Data);
  459.             break;
  460.         case 4 :
  461.             SelectTextWindow(&Session);
  462.             break;
  463.         case 5 :
  464.             SelectTextWindow(&Console);
  465.             break;
  466.         case 7 :
  467.             /* tile vertically */
  468.             TileTextWindows(TRUE);
  469.             break;
  470.         case 8 :
  471.             /* tile horizontally */
  472.             TileTextWindows(FALSE);
  473.             break;
  474.         case 9 :
  475.             /* close all */
  476.             HideWindow(Registers.window);
  477.             HideWindow(Text.window);
  478.             HideWindow(Data.window);
  479.             HideWindow(Session.window);
  480.             HideWindow(Console.window);
  481.             break;
  482.         }
  483.         break;
  484.     case 132 :
  485.         /* options menu */
  486.         switch ( itemCode ) {
  487.         case 1 :
  488.             bare_machine = 1 - bare_machine;
  489.             CheckItem(GetMHandle(menuCode), itemCode, bare_machine ? TRUE : FALSE);
  490.             break;
  491.         case 2 :
  492.             quiet = 1 - quiet;
  493.             CheckItem(GetMHandle(menuCode), itemCode, quiet ? TRUE : FALSE);
  494.             break;
  495.         }
  496.         break;
  497.     case 133 :
  498.         /* execute menu */
  499.         switch ( itemCode ) {
  500.         case 1 :
  501.             if ( PC )
  502.                 address = PC;
  503.             else {
  504.                 address = find_symbol_address(DEFAULT_RUN_LOCATION);
  505.                 if ( !address )
  506.                     address = TEXT_BOT;
  507.             }
  508.             sprintf((char *) addrStr, "0x%X", address);
  509.             CtoPstr(addrStr);
  510.             GetDItem(RunDlg, 2, &type, &hand, &box);
  511.             SetIText(hand, addrStr);
  512.             SelIText(RunDlg, 2, 0, 32767);
  513.             ShowWindow(RunDlg);
  514.             SelectWindow(RunDlg);
  515.             break;
  516.         case 2 :
  517.             SelIText(StepDlg, 2, 0, 32767);
  518.             ShowWindow(StepDlg);
  519.             SelectWindow(StepDlg);
  520.             break;
  521.         case 4 :
  522.             SelIText(BreakpointsDlg, 2, 0, 32767);
  523.             ShowWindow(BreakpointsDlg);
  524.             SelectWindow(BreakpointsDlg);
  525.             break;
  526.         }
  527.         break;
  528.     case 134 :
  529.         /* data menu */
  530.         switch ( itemCode ) {
  531.         case 1 :
  532.             SelIText(PrintDlg, 2, 0, 32767);
  533.             ShowWindow(PrintDlg);
  534.             SelectWindow(PrintDlg);
  535.             break;
  536.         case 2 :
  537.             SelIText(SetDlg, 2, 0, 32767);
  538.             ShowWindow(SetDlg);
  539.             SelectWindow(SetDlg);
  540.             break;
  541.         }
  542.         break;
  543.     case 200 :
  544.         /* clear submenu */
  545.         switch ( itemCode ) {
  546.         case 1 :
  547.             /* clear registers */
  548.             initialize_registers();
  549.             write_output(message_out, "Cleared registers.\n");
  550.             FormatRegisters();
  551.             break;
  552.         case 2 :
  553.             /* clear console */
  554.             ClearConsole();
  555.             write_output(message_out, "Cleared console.\n");
  556.             break;
  557.         case 3 :
  558.             /* clear all */
  559.             ResetMacMemory();
  560.             ClearConsole();
  561.             GetVol(0, ¤tVolume);
  562.             SetVol(0, StartupVolume);
  563.             text_seg = 0;
  564.             data_seg = 0;
  565.             stack_seg = 0;
  566.             k_text_seg = 0;
  567.             k_data_seg = 0;
  568.             FGR = 0;
  569.             ReinitInst();
  570.             initialize_world(!bare_machine);
  571.             SetVol(0, currentVolume);
  572.             write_output(message_out, "Cleared registers, memory and console.\n");
  573.             CountText();
  574.             CountData();
  575.             break;
  576.         }
  577.         break;
  578.     }
  579.     HiliteMenu(0);
  580. } /* doMenuEvent */
  581.  
  582. /* This handles mouse-down events. */
  583.  
  584. static void doMouseDown(EventRecord *event)
  585. {
  586.     WindowPtr whichWindow;
  587.     short code;
  588.  
  589.     switch ( code = FindWindow(event->where, &whichWindow) ) {
  590.     case inDesk :
  591.         break;
  592.     case inMenuBar :
  593.         doMenuEvent(MenuSelect(event->where));
  594.         break;
  595.     case inSysWindow :
  596.         SystemClick(event, whichWindow);
  597.         break;
  598.     case inContent :
  599.         if ( whichWindow == FrontWindow() )
  600.             ClickTextWindow(whichWindow, event);
  601.         else
  602.             SelectWindow(whichWindow);
  603.         break;
  604.     case inDrag :
  605.         DragWindow(whichWindow, event->where, &DragBoundary);
  606.         break;
  607.     case inGrow :
  608.         SizeTextWindow(whichWindow, event->where);
  609.         break;
  610.     case inGoAway :
  611.         if ( TrackGoAway(whichWindow, event->where) )
  612.             HideWindow(whichWindow);
  613.         break;
  614.     case inZoomIn :
  615.     case inZoomOut :
  616.         if ( TrackBox(whichWindow, event->where, code) ) {
  617.             ZoomWindow(whichWindow, code, TRUE);
  618.             RecalculateTextWindow(whichWindow);
  619.         }
  620.         break;
  621.     }
  622. } /* doMouseDown */
  623.  
  624. main()
  625. {
  626.     Handle mBar;
  627.     MenuHandle menu;
  628.     EventRecord event;
  629.     Boolean gotEvent, isDlgEvent;
  630.  
  631.     /* init mac toolbox */
  632.     MaxApplZone();
  633.     InitGraf(&thePort);
  634.     InitFonts();
  635.     InitWindows();
  636.     InitMenus();
  637.     TEInit();
  638.     InitDialogs(0);
  639.  
  640.     WristWatch = GetCursor(watchCursor);
  641.     SetCursor(*WristWatch);
  642.  
  643.     /* init this app */
  644.     mBar = GetNewMBar(128);
  645.     SetMenuBar(mBar);
  646.     DrawMenuBar();
  647.     menu = GetMHandle(128);
  648.     AddResMenu(menu, 'DRVR');
  649.     menu = GetMenu(200);
  650.     InsertMenu(menu, -1);
  651.  
  652.     RunDlg = GetNewDialog(129, 0, (WindowPtr) -1);
  653.     StepDlg = GetNewDialog(130, 0, (WindowPtr) -1);
  654.     BreakpointsDlg = GetNewDialog(131, 0, (WindowPtr) -1);
  655.     PrintDlg = GetNewDialog(132, 0, (WindowPtr) -1);
  656.     SetDlg = GetNewDialog(133, 0, (WindowPtr) -1);
  657.     RunningDlg = GetNewDialog(134, 0, (WindowPtr) -1);
  658.  
  659.     GetVol(0, &StartupVolume);
  660.  
  661.     DragBoundary = screenBits.bounds;
  662.     InsetRect(&DragBoundary, 4, 4);
  663.     DragBoundary.top += 20;
  664.  
  665.     InitTextWindows();
  666.     message_out = (int) &Session;
  667.     console_out = (int) &Console;
  668.  
  669.     CreateMacMemory();
  670.     initialize_world(1);
  671.  
  672.     FormatRegisters();
  673.     CountText();
  674.     CountData();
  675.  
  676.     /* main loop */
  677.     FlushEvents(everyEvent, 0);
  678.     InitCursor();
  679.     showAboutBox();
  680.     SelectTextWindow(&Console);
  681.     SelectTextWindow(&Session);
  682.     TileTextWindows(TRUE);
  683.     while ( running ) {
  684.         gotEvent = GetNextEvent(everyEvent, &event);
  685.         isDlgEvent = IsDialogEvent(&event);
  686.         if ( isDlgEvent ) {
  687.             DialogPtr whichDlg;
  688.             short whichItem;
  689.  
  690.             if ( event.what == keyDown && event.modifiers & cmdKey )
  691.                 doMenuEvent(MenuKey(event.message & charCodeMask));
  692.             else if ( DialogSelect(&event, &whichDlg, &whichItem) )
  693.                 doDialogEvent(whichDlg, whichItem);
  694.                 
  695.         }
  696.         else if ( gotEvent ) {
  697.             switch ( event.what ) {
  698.             case mouseDown :
  699.                 doMouseDown(&event);
  700.                 break;
  701.             case keyDown :
  702.                 if ( event.modifiers & cmdKey )
  703.                     doMenuEvent(MenuKey(event.message & charCodeMask));
  704.                 break;
  705.             case activateEvt :
  706.                 ActivateTextWindow((WindowPtr) event.message,
  707.                                     event.modifiers & activeFlag ? TRUE : FALSE);
  708.                 break;
  709.             case updateEvt :
  710.                 UpdateTextWindow((WindowPtr) event.message);
  711.                 break;
  712.             }
  713.         }
  714.     }
  715. } /* main */
  716.  
  717. void error(char *text)
  718. {
  719.     write_output(message_out, text);
  720. }
  721.  
  722. int run_error(char *text)
  723. {
  724.     write_output(message_out, text);
  725.     if ( RunningCPU )
  726.         longjmp(JumpBuff, 1);
  727.     return 0;
  728. }
  729.