home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / scheme / schematk / src_1152.lha / Main.subproj / SchemeProtocol.m < prev   
Encoding:
Text File  |  1992-07-10  |  19.3 KB  |  579 lines

  1. /* Copyright รก 1991 Gustavus Adolphus College.  All rights reserved.
  2.  *
  3.  * Schematik was developed by Gustavus Adolphus College (GAC) with
  4.  * support from NeXT Computer, Inc.  Permission to copy this software,
  5.  * to redistribute it, and to use it for any purpose is granted,
  6.  * subject to the following restrictions and understandings.
  7.  *
  8.  * 1. Any copy made of this software must include this copyright
  9.  * notice in full.
  10.  *
  11.  * 2. Users of this software agree to make their best efforts (a) to
  12.  * return to the GAC Mathematics and Computer Science Department any
  13.  * improvements or extensions that they make, so that these may be
  14.  * included in future releases; and (b) to inform GAC of noteworthy
  15.  * uses of this software.
  16.  *
  17.  * 3. All materials developed as a consequence of the use of this
  18.  * software shall duly acknowledge such use, in accordance with the
  19.  * usual standards of acknowledging credit in academic research.
  20.  *
  21.  * 4. GAC makes no express or implied warranty or representation of
  22.  * any kind with respect to this software, including any warranty
  23.  * that the operation of this software will be error-free.  ANY
  24.  * IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
  25.  * PURPOSE IS HEREBY DISCLAIMED.  GAC is under no obligation to
  26.  * provide any services, by way of maintenance, update, or otherwise.
  27.  *
  28.  * 5. In conjunction with products arising from the use of this
  29.  * material, there shall be no use of the name of Gustavus Adolphus
  30.  * College nor of any adaptation thereof in any advertising,
  31.  * promotional, or sales literature without prior written consent
  32.  * from GAC in each case.
  33.  */
  34.  
  35. #import "SchemeProtocol.h"
  36. #import "../defines.h"
  37. #import Main_h
  38. #import PrefAgent_h
  39. #import DocText_h
  40. #import InteractionWin_h
  41. #import <appkit/Matrix.h>
  42. #import <appkit/Panel.h>
  43. #import <appkit/Text.h>
  44. #import <sys/signal.h>
  45. #import <sys/socket.h>
  46. #import <defaults.h>
  47. #import <fcntl.h>
  48. #import <libc.h>
  49. #import <mach.h>
  50. #import <NXCType.h> 
  51. #import <string.h>
  52. extern void NXBeep(void);
  53.  
  54. #define BUFFERSIZE        4096
  55. #define COMMENTCHAR        ';'
  56. #define COMMENTSTRING        ";"
  57. #define ERRORAFFIRMATIVE    "y"
  58. #define ERRORNEGATIVE        "n"
  59. #define MAXPARAMS        64
  60. #define PROMPTMESSAGESPLITCHAR    ' '
  61. #define QUERYAFFIRMATIVE    "y"
  62. #define QUERYNEGATIVE        "n"
  63. #define SCHEMEENVIRON1    "USE_SCHEMATIK_STYLE_INTERRUPTS="
  64. #define SCHEMEENVIRON2    "USE_SCHEMATIK_STYLE_ERRORS="
  65. #define SCHEMEENVIRON3    "USE_SCHEMATIK_STYLE_GRAPHICS="
  66. #define SMF1A        "(message \"%s\" \""
  67. #define SMF1B        "\")"
  68. #define SMF2A        "(xscheme-write-message-1 xscheme-prompt (format \";Value "
  69. #define SMF2B        ": %s\" xscheme-prompt))"
  70. #define YORN        " (y or n)? "
  71.  
  72. #define USLEEP(x) {int _usleep_mask=sigsetmask(~0);\
  73.                    usleep((x));\
  74.                    sigsetmask(_usleep_mask);}
  75.  
  76. static void fdHandler(int, id);
  77. static void outputHandler(DPSTimedEntry, double, id);
  78. static void childHandler(DPSTimedEntry, double, id);
  79.  
  80. int fromScheme,toScheme,schemePid,graphicsFD;
  81. int inState=1,j=0,k=0;
  82. BOOL inInputState=NO,gc=NO,sigintOK=YES;
  83. char buffer1[BUFFERSIZE],buffer3[BUFFERSIZE];
  84. DPSTimedEntry TE,childCheck;
  85. NXZone *outputZone=NULL;
  86. char *outputBuffer=NULL;
  87. unsigned outputBufferSize=0;
  88. char *bogusEscPHack=NULL;
  89.  
  90. @implementation SchemeProtocol
  91.  
  92. - init
  93. {
  94.     int sv[2],sw[2],numFDs,fd,pidChild;
  95.  
  96. DEBUG_FUNC1(DEBUGLEVEL);
  97.     if ((socketpair(AF_UNIX,SOCK_STREAM,0,sv)<0)||(socketpair(AF_UNIX,SOCK_STREAM,0,sw)<0))
  98.       {
  99.         NXRunAlertPanel(ERRORTITLE,SOCKETERRORMESSAGE,NULL,NULL,NULL);
  100.         return nil;
  101.       }
  102.     switch (pidChild = vfork())
  103.       {
  104.         case -1: NXRunAlertPanel(ERRORTITLE,FORKERRORMESSAGE,NULL,NULL,NULL);
  105.                  return nil;
  106.         case 0 : {
  107.                    char *argv[MAXPARAMS],**envp;
  108.                    char *parms=NXCopyStringBuffer([[PrefAgent new] parameters]);
  109.                    int i;
  110.  
  111.                    argv[0]=[[PrefAgent new] executable];
  112.                    argv[1]=strtok(parms, WHITESPACECHARS);
  113.                    for(i=2; i<MAXPARAMS; i++)
  114.              argv[i]=strtok(NULL, WHITESPACECHARS);
  115.            argv[MAXPARAMS-1]=NULL;
  116.                    for(i=0; environ[i]; i++);
  117.                    envp=(char **)malloc((i+3)*sizeof(char *));
  118.                    for(i=0; environ[i]; i++) envp[i]=environ[i];
  119.                    envp[i++]=SCHEMEENVIRON1;
  120.                    envp[i++]=SCHEMEENVIRON2;
  121.                    envp[i++]=SCHEMEENVIRON3;
  122.            envp[i]=NULL;
  123.                    dup2(sv[1],0);
  124.                    dup2(sv[1],1);
  125.                    dup2(sv[1],2);
  126.                    dup2(sw[1],3);
  127.                    numFDs = getdtablesize();
  128.                    for(fd=4; fd<numFDs; fd++)
  129.                      close(fd);
  130.                    execve(argv[0],argv,envp);
  131.                    perror(EXECERRORMESSAGE);
  132.                    _exit(1);
  133.          }
  134.         default: schemePid = pidChild;
  135.                  fromScheme = toScheme = sv[0];
  136.          graphicsFD = sw[0];
  137.                  fcntl(toScheme, F_SETFL, fcntl(toScheme, F_GETFL, 0)|FNDELAY);
  138.                  fcntl(graphicsFD, F_SETFL, fcntl(graphicsFD, F_GETFL, 0)|FNDELAY);
  139.                  DPSAddFD(fromScheme, (DPSFDProc)fdHandler, (id)self, NX_BASETHRESHOLD+1);
  140.                  TE = (DPSTimedEntry)0;
  141.          interactionWin = [NXApp interactionWindow];
  142.                  outputZone = NXCreateZone(vm_page_size, vm_page_size, YES);
  143.                  outputBuffer = (char *)NXZoneMalloc(outputZone, 1020);
  144.                  childCheck = DPSAddTimedEntry(10.0, (DPSTimedEntryProc)childHandler, self, NX_MODALRESPTHRESHOLD+1);
  145.                  return self;
  146.       }
  147. }
  148.  
  149. - free
  150. {
  151.     inState=1;
  152.     j=k=0;
  153.     inInputState=NO;
  154.     gc=NO;
  155.     sigintOK=YES;
  156.     if (bogusEscPHack!=NULL) free(bogusEscPHack);
  157.     bogusEscPHack=NULL;
  158.     buffer1[0] = buffer3[0] = 0;
  159.     NXDestroyZone(outputZone);
  160.     outputZone = NULL;
  161.     outputBuffer = NULL;
  162.     outputBufferSize = 0;
  163.     return [super free];
  164. }
  165.  
  166. @end
  167.  
  168. @implementation SchemeProtocol (SchemeProcess)
  169.  
  170. - (int)schemePid    { return schemePid;}
  171.  
  172. - outputHandler
  173. {
  174. DEBUG_FUNC1(DEBUGLEVEL);
  175.     if (outputBufferSize)
  176.       {
  177.         int num = write(toScheme, outputBuffer, outputBufferSize);
  178.         if (num>0)
  179.           {
  180.             outputBufferSize-=num;
  181.             memmove(outputBuffer, (outputBuffer+num), outputBufferSize);
  182.           }
  183.       }
  184.     if (!TE&&(outputBufferSize>0))
  185.       TE = DPSAddTimedEntry(0.01, (DPSTimedEntryProc)outputHandler, self, NX_MODALRESPTHRESHOLD);
  186.     else if (TE&&!outputBufferSize)
  187.       {
  188.     DPSRemoveTimedEntry(TE);
  189.     TE = (DPSTimedEntry)0;
  190.       }
  191.     return self;
  192. }
  193.  
  194. - send:(STR)aString
  195. {
  196. DEBUG_FUNC1(DEBUGLEVEL);
  197.     outputBuffer = (char *)NXZoneRealloc(outputZone, outputBuffer, outputBufferSize+strlen(aString)+1);
  198.     strcpy((outputBuffer+outputBufferSize), aString);
  199.     outputBufferSize+=strlen(aString);
  200.     [self outputHandler];
  201.     return self;
  202. }
  203.  
  204. - sendNul
  205. {
  206. DEBUG_FUNC1(DEBUGLEVEL);
  207.     outputBuffer = (char *)NXZoneRealloc(outputZone, outputBuffer, outputBufferSize+1);
  208.     outputBuffer[outputBufferSize++] = '\0';
  209.     [self outputHandler];
  210.     return self;
  211. }
  212.  
  213. - sendSignal:(int)aSignal
  214. {
  215. DEBUG_FUNC1(DEBUGLEVEL);
  216.     switch (aSignal)
  217.       {
  218.         case SIGNALBREAKPOINT: kill(schemePid,aSignal); return self;
  219.         case SIGNALABORTTOP  : if (!sigintOK) return self;
  220.         case SIGNALABORTPREV :
  221.         case SIGNALABORTSAME : kill(schemePid,aSignal);
  222.       }
  223.     USLEEP(10000);
  224.     return [self sendNul];
  225. }
  226.  
  227. - sendGraphicsWindow:(int)windowNum
  228. {
  229.     char buffer[2044];
  230.  
  231.     sprintf(buffer,"%i\n%s\n%s\n",windowNum, (NXGetDefaultValue([NXApp appName],"NXHost")?:"\0"), (NXGetDefaultValue([NXApp appName],"NXPSName")?:"\0"));
  232.     write(graphicsFD, buffer, strlen(buffer));
  233.     return self;
  234. }
  235.  
  236. #include <syslog.h>
  237.  
  238. void kill_alarm(int sig)
  239. {
  240.     kill(schemePid, SIGKILL);
  241.     syslog(LOG_WARNING|LOG_LOCAL1, "Scheme termination timeout (5 sec).  Killing with SIGKILL.");
  242. }
  243.  
  244. void kill_scheme()
  245. {
  246.     void (*oldsigh)(int);
  247.     union wait status;
  248.     int ret,oldsigb;
  249.  
  250.     kill(schemePid, SIGHUP);
  251.     oldsigb=sigblock(0);
  252. //    if (sigmask(SIGALRM)&oldsigb)
  253. //      oldsigb=oldsigb&(~sigmask(SIGALRM));
  254.     sigblock(oldsigb);
  255.     oldsigh = signal(SIGALRM, kill_alarm);
  256.     ualarm(5000000, 0);
  257.     ret = wait4(schemePid, &status, 0, NULL);
  258.     if (WIFSTOPPED(status)||(ret<0))
  259.       kill_alarm(0);
  260.     ualarm(0, 0);
  261.     signal(SIGALRM, oldsigh);
  262. }
  263.  
  264. - terminate:sender withPrejudice:(BOOL)aBoolean
  265. {
  266. DEBUG_FUNC1(DEBUGLEVEL);
  267.     if (!schemePid)
  268.       return self;
  269.     DPSRemoveTimedEntry(childCheck);
  270.     if (TE) DPSRemoveTimedEntry(TE);
  271.     kill_scheme();
  272.     DPSRemoveFD(fromScheme);
  273.     close(fromScheme);
  274.     close(toScheme);
  275.     close(graphicsFD);
  276.     schemePid=0;
  277.     if (!aBoolean)
  278.       NXRunAlertPanel(ERRORTITLE,TERMINATIONERRORMESSAGE,NULL,NULL,NULL);
  279.     return self;
  280. }
  281.  
  282. - fdHandler:(int)anFD
  283. {
  284.     char aChar,tempBuffer[BUFFERSIZE];
  285.     int ret,i;
  286.  
  287. DEBUG_FUNC1(DEBUGLEVEL);
  288.     if ((ret=read(anFD, tempBuffer, BUFFERSIZE))<=0)
  289.       return [self terminate:self withPrejudice:NO];
  290.     for(i=0; i<ret; i++)
  291.       {
  292.         aChar = tempBuffer[i];
  293.         switch (inState)
  294.           {
  295.             case 1 : switch (aChar)                            /* Initial state */
  296.                        {
  297.                          case 27 : buffer1[j] = '\0'; [self sendOutput:buffer1]; j=0; inState = 2; break;
  298.                          case 7  : NXBeep(); break;
  299.                          default : buffer1[j++] = aChar;
  300.                        }
  301.                      break;
  302.             case 2 : switch (aChar)                            /* ESC sequence state */
  303.                        {
  304.                          case 'c' :
  305.                          case 'o' :
  306.                          case 'z' :
  307.                          case 'R' : inState = 1; break;                    /* nop, no string */
  308.                          case 'w' :
  309.                          case 'D' : k = 0; buffer3[0] = '\0'; inState = 3; break;    /* nop, with string */
  310.                          case 'b' : [self showRunState:GARBCOLLECT]; gc = YES; inState = 1;  break;
  311.                          case 'e' : [self showRunState:PREVIOUS]; gc = NO; inState = 1;  break;
  312.                          case 'f' : [self showRunState:EVALUATING]; inInputState = NO; inState = 1;  break;
  313.                          case 's' : [self showRunState:INPUTSTATE]; inInputState = YES; [self sendGraphics:"f0"]; inState = 1;  break;
  314.                          case 'g' : sigintOK = YES; inState = 1;  break;
  315.                          case 'i' :
  316.                          case 'm' : k = 0; buffer3[0] = '\0'; inState = 4; break;    /* normal message */
  317.                          case 'p' : k = 0; buffer3[0] = '\0'; inState = 5; break;    /* prompt message */
  318.                          case 'v' : k = 0; buffer3[0] = '\0'; inState = 6; break;    /* normal value */
  319.                          case 'n' : k = 0; buffer3[0] = '\0'; inState = 7; break;    /* yes/no query */
  320.                          case 'B' : k = 0; buffer3[0] = '\0'; inState = 8; break;    /* error message */
  321.                          case 'E' : k = 0; buffer3[0] = '\0'; inState = 9; break;    /* special message */
  322.                          case 'P' : k = 0; buffer3[0] = '\0'; inState = 10; break;    /* special value */
  323.                          case 'G' : k = 0; buffer3[0] = '\0'; inState = 11; break;    /* graphics */
  324.                          default  : NXRunAlertPanel(PROTOCOLERROR, NONPROTOCOLERROR, NULL, NULL, NULL, aChar); inState = 1; 
  325.                        }
  326.                      break;
  327.             case 3 : if (aChar==27)                        // nop string
  328.                        {
  329.                          buffer3[k] = '\0';
  330.                          inState = 1;  break;
  331.                        }
  332.                      buffer3[k++] = aChar; break;
  333.             case 4 : if (aChar==27)                        // normal message
  334.                        {
  335.                          buffer3[k] = '\0';
  336.              [self sendMessage:buffer3];
  337.                          inState = 1;  break;
  338.                        }
  339.                      buffer3[k++] = aChar;  break;
  340.             case 5 : if (aChar==27)                        // prompt message
  341.                        {
  342.                          buffer3[k] = '\0';
  343.              [self sendPrompt:buffer3];
  344.                          inState = 1;  break;
  345.                        }
  346.                      buffer3[k++] = aChar; break;
  347.             case 6 : if (aChar==27)                        // value
  348.                        {
  349.                          buffer3[k] = '\0';
  350.              [self sendValue:buffer3];
  351.                          inState = 1;  break;
  352.                        }
  353.                      buffer3[k++] = aChar; break;
  354.             case 7 : if (aChar==27)                        // yes/no query
  355.                {
  356.              buffer3[k] = '\0';
  357.              if ((strlen(buffer3)>=strlen(YORN))&&
  358.                   !NXOrderStrings((unsigned char *)(buffer3+strlen(buffer3)-strlen(YORN)),(unsigned char *)YORN,NO,-1,NULL))
  359.                strcpy(buffer3+strlen(buffer3)-strlen(YORN), "?");
  360.              [self sendQuery:buffer3];
  361.              inState = 1;  break;
  362.                }
  363.                      buffer3[k++] = aChar; break;
  364.             case 8 : if (aChar==27)                        // error
  365.                        {
  366.                          buffer3[k] = '\0';
  367.              [self sendError:buffer3];
  368.                          inState = 1;  break;
  369.                        }
  370.                      buffer3[k++] = aChar; break;
  371.             case 9 : if (aChar==27)                        // special message
  372.                        {
  373.                          buffer3[k] = '\0';
  374.              if ((strlen(buffer3)>=strlen(SMF1A)+strlen(SMF1B))&&
  375.                   !NXOrderStrings((unsigned char *)buffer3,(unsigned char *)SMF1A,NO,strlen(SMF1A),NULL)&&
  376.                   !NXOrderStrings((unsigned char *)(buffer3+strlen(buffer3)-strlen(SMF1B)),(unsigned char *)SMF1B,NO,-1,NULL))
  377.                            {
  378.                  buffer3[k-strlen(SMF1B)] = '\0';
  379.                  [self sendMessage:(buffer3+strlen(SMF1A))];
  380.                            }
  381.              else if ((bogusEscPHack!=NULL)&&
  382.                   (strlen(buffer3)>=strlen(SMF2A)+strlen(SMF2B))&&
  383.                   !NXOrderStrings((unsigned char *)buffer3,(unsigned char *)SMF2A,NO,strlen(SMF2A),NULL)&&
  384.                   !NXOrderStrings((unsigned char *)(buffer3+strlen(buffer3)-strlen(SMF2B)),(unsigned char *)SMF2B,NO,-1,NULL))
  385.                            {
  386. //                 if (![[PrefAgent new] includeHashValues])
  387.                                [self sendValue:bogusEscPHack];
  388. //                 else
  389. //                   {
  390. //                     buffer3[k-strlen(SMF2B)] = '\0';
  391. //                     [self sendSpecialValue:bogusEscPHack withHashCode:(buffer3+strlen(SMF2A))];
  392. //                   }
  393.                  free(bogusEscPHack);
  394.                  bogusEscPHack=NULL;
  395.                }
  396.                          inState = 1;  break;
  397.                        }
  398.                      buffer3[k++] = aChar; break;
  399.             case 10 : if (aChar==27)                        // special value
  400.                        {
  401.                          buffer3[k] = '\0';
  402.              bogusEscPHack = NXCopyStringBuffer(buffer3);
  403.                          inState = 1;  break;
  404.                        }
  405.                      buffer3[k++] = aChar;  break;
  406.  
  407.             case 11: if (aChar==27)                        // graphics
  408.                        {
  409.                          buffer3[k] = '\0';
  410.              [self sendGraphics:buffer3];
  411.                          inState = 1;  break;
  412.                        }
  413.                      buffer3[k++] = aChar; break;
  414.           }
  415.       }
  416.     if (inState==1)
  417.       {
  418.         buffer1[j] = '\0'; [self sendOutput:buffer1]; j = 0;
  419.       }
  420.     return self;
  421. }
  422.  
  423. @end
  424.  
  425. @implementation SchemeProtocol (InteractionWindow)
  426.  
  427. - sendMessage:(STR)aString
  428. {
  429.     id text = [interactionWin textView];
  430. DEBUG_FUNC1(DEBUGLEVEL);
  431.     [text appendNewlineIfNeeded];
  432.     return [text appendText:aString commented:YES withNewline:YES];
  433. }
  434.  
  435. - sendQuery:(STR)aString
  436. {
  437. DEBUG_FUNC1(DEBUGLEVEL);
  438.     if (NXRunAlertPanel(QUERYTITLE, aString, QUERYDEFAULT, QUERYALTERNATE, NULL)>0)
  439.       [self send:QUERYAFFIRMATIVE];
  440.     else
  441.       [self send:QUERYNEGATIVE];
  442.     return self;
  443. }
  444.  
  445. - sendValue:(STR)aString
  446. {
  447.     id text = [interactionWin textView];
  448. DEBUG_FUNC1(DEBUGLEVEL);
  449.     [text appendNewlineIfNeeded];
  450.     if (!*aString)
  451.       return [text appendText:NOVALUESTRING commented:YES withNewline:YES];
  452.     [text appendText:VALUESTRING commented:YES withNewline:NO];
  453.     return [text appendText:aString commented:NO withNewline:YES];
  454. }
  455.  
  456. - sendSpecialValue:(STR)aString withHashCode:(STR)hashString
  457. {
  458.     id text = [interactionWin textView];
  459. DEBUG_FUNC1(DEBUGLEVEL);
  460.     [text appendNewlineIfNeeded];
  461.     [text appendText:"Value " commented:YES withNewline:NO];
  462.     [text appendText:hashString commented:NO withNewline:NO];
  463.     [text appendText:": " commented:NO withNewline:NO];
  464.     return [text appendText:aString commented:NO withNewline:YES];
  465. }
  466.  
  467. - sendGraphics:(STR)aString        // sent to NXApp (Main)
  468. {
  469.     char function;
  470.     unsigned int windownum,width,height,mode;
  471.  
  472.     switch (aString[0])
  473.       {
  474.         case 'c' : sscanf(aString, "%c%d", &function, &windownum);
  475.                [NXApp closeGraphicsWindow:windownum];
  476.                break;
  477.     case 'f' : sscanf(aString, "%c%d%d", &function, &windownum, &mode);
  478.            [NXApp setGraphicsWindowFlush:windownum mode:mode];
  479.            break;
  480.     case 'o' : sscanf(aString, "%c%d%u%u", &function, &windownum, &width, &height);
  481.            [NXApp openGraphicsWindow:windownum width:width height:height];
  482.            break;
  483.     case 'p' : sscanf(aString, "%c%d", &function, &windownum);
  484.            [NXApp printGraphicsWindow:windownum];
  485.            break;
  486.     default  : NXRunAlertPanel(PROTOCOLERROR, GRAPHICSPROTOCOLERROR, NULL, NULL, NULL, aString[0]);
  487.       }
  488.     return self;
  489. }
  490.  
  491. - sendOutput:(STR)aString
  492. {
  493.     id text = [interactionWin textView];
  494. DEBUG_FUNC1(DEBUGLEVEL);
  495.     if (*aString)
  496.       return [text appendText:aString commented:[[PrefAgent new] commentOutput] withNewline:NO];
  497.     return self;
  498. }
  499.  
  500. - sendPrompt:(STR)aString
  501. {
  502.     id text = [interactionWin textView];
  503. DEBUG_FUNC1(DEBUGLEVEL);
  504.     [interactionWin setLevel:atoi(aString)];
  505.     [interactionWin setPrompt:strchr(aString, PROMPTMESSAGESPLITCHAR)];
  506.     return [text appendText:"" commented:NO withNewline:YES];
  507. }
  508.  
  509. - sendError:(STR)aString
  510. {
  511. DEBUG_FUNC1(DEBUGLEVEL);
  512.     if (NXRunAlertPanel(ERRORTITLE,ERRORMESSAGE,ERRORDEFAULT,ERRORALTERNATE,NULL,aString)>0)
  513.       switch ([[PrefAgent new] errorAbort])
  514.         {
  515.       case 0: [self sendSignal:SIGNALABORTTOP]; break;
  516.       case 1: [self sendSignal:SIGNALABORTSAME]; break;
  517.     }
  518.     else
  519.       [self sendNul];
  520.     [self showRunState:PREVIOUS];
  521.     if ([[NXApp prefAgent] insertErrors])
  522.       {
  523.         [self sendMessage:aString];
  524.     [interactionWin makeKeyAndOrderFront:self];
  525.       }
  526.     return self;
  527. }
  528.  
  529.  
  530. - showRunState:(int)aState
  531. {
  532.     static int prevState;
  533.  
  534. DEBUG_FUNC1(DEBUGLEVEL);
  535.     switch (aState)
  536.       {
  537.         case INPUTSTATE : [interactionWin setTitle:INTERWINDOWTITLE];
  538.                       prevState=INPUTSTATE; break;
  539.     case EVALUATING : [interactionWin setTitle:EVALMESSAGE];
  540.                       prevState=EVALUATING; break;
  541.     case GARBCOLLECT: [interactionWin setTitle:GCMESSAGE]; break;
  542.     case PREVIOUS   : ((prevState==INPUTSTATE)?[interactionWin setTitle:INTERWINDOWTITLE]:[interactionWin setTitle:EVALMESSAGE]);
  543.       }
  544.     return self;
  545. }
  546.  
  547. @end
  548.  
  549. static void fdHandler(int anFD, id self)
  550. {
  551.     [self fdHandler:anFD];
  552. }
  553.  
  554. static void outputHandler(DPSTimedEntry te, double time, id self)
  555. {
  556.     [self outputHandler];
  557. }
  558.  
  559. static void childHandler(DPSTimedEntry te, double time, id self)
  560. {
  561.     extern char *sys_siglist[];
  562.     union wait status;
  563.     int ret = wait4(schemePid, &status, WNOHANG|WUNTRACED, NULL);
  564.  
  565.     if (ret>0)
  566.       {
  567.         if (WIFSTOPPED(status))
  568.       NXRunAlertPanel(SCHEMEPROCMESSAGE,PROCESSSTOPPED,NULL,NULL,NULL,status.w_stopsig,sys_siglist[status.w_stopsig]);
  569.     else if (WIFSIGNALED(status))
  570.       {
  571.         if (NXRunAlertPanel(SCHEMEPROCMESSAGE,PROCESSSIGTERM,
  572.                           RESTARTDEFAULT,RESTARTALTERNATE,NULL,status.w_termsig,sys_siglist[status.w_termsig]))
  573.           [NXApp restartSubprocess];
  574.       }
  575.     else
  576.       NXRunAlertPanel(SCHEMEPROCMESSAGE,PROCESSEXITTERM,NULL,NULL,NULL,status.w_retcode);
  577.       }
  578. }
  579.