home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / Apps / DevTools / COWS / Code / COWSIPCLibrary.m < prev    next >
Encoding:
Text File  |  1994-03-25  |  14.5 KB  |  713 lines

  1. /*
  2.     Copyright (C) 1994 Sean Luke
  3.  
  4.     COWSIPCLibrary.m
  5.     Version 10
  6.     Sean Luke
  7.     
  8. */
  9.  
  10.  
  11.  
  12.  
  13. #import "COWSIPCLibrary.h"
  14. #import <stdio.h>
  15.  
  16. @implementation COWSIPCLibrary
  17.  
  18.  
  19. - init
  20.     {
  21.     char nm[COWSLARGESTPATHLENGTH];    
  22.     id returnval=[super init];
  23.     sprintf (nm,"%s(COWS)",[NXApp appName]);
  24.     connection = [NXConnection registerRoot: self withName:nm];
  25.     [connection runFromAppKit];
  26.     arguments=[[COWSArgumentList alloc] init];
  27.     arguments_state=COWSIPCLIBRARY_ARGSTATE_READY;
  28.     result=[[COWSStringNode alloc] init];
  29.     return returnval;
  30.     }
  31.     
  32.     
  33. - free
  34.     {
  35.     if (connection!=NULL) [connection free];
  36.     [arguments free];
  37.     [result free];
  38.     [NXConnection removeObject:self];
  39.     return [super free];
  40.     }
  41.  
  42.  
  43. - loadLibrary:sender
  44.     {
  45.     id returnval=[super loadLibrary:sender];
  46.     
  47.     if (![sender conformsTo:@protocol(LibraryControl)])
  48.         {
  49.         printf ("StandardLibrary error:  Interpreter cannot accept Library Control protocol!\n");
  50.         return NULL;
  51.         }
  52.     [sender addLibraryFunction:"send-out"
  53.             selector:@selector(ipc_sendout:)
  54.             target:self];
  55.     [sender addLibraryFunction:"send-out-remote"
  56.             selector:@selector(ipc_sendout_machine:)
  57.             target:self];
  58.     [sender addLibraryFunction:"send"
  59.             selector:@selector(ipc_send:)
  60.             target:self];
  61.     [sender addLibraryFunction:"send-remote"
  62.             selector:@selector(ipc_send_machine:)
  63.             target:self];
  64.     [sender addLibraryFunction:"launch"
  65.             selector:@selector(ipc_launch:)
  66.             target:self];
  67.     [sender addLibraryFunction:"launched?"
  68.             selector:@selector(ipc_launched:)
  69.             target:self];
  70.     interpreter=sender;    
  71.     return returnval;
  72.     }
  73.  
  74.  
  75. - ipc_send:arg_list
  76.     {
  77.     char nm[COWSLARGESTPATHLENGTH];    
  78.     id return_val=[[COWSStringNode alloc] init];
  79.     id current;
  80.     id name=[[COWSStringNode alloc] init];
  81.     id function=[[COWSStringNode alloc] init];
  82.     id server;
  83.     
  84.     
  85.     if ([arg_list top]==NULL)                 // no args
  86.         {
  87.         [return_val setString:"send error:  nothing to connect to"];
  88.         [return_val setError:YES];
  89.         [name free];
  90.         [function free];
  91.         return return_val;
  92.         }
  93.     else
  94.         {
  95.         current=[arg_list pop];
  96.         [name setString:[current string]];
  97.         [current free];
  98.         }
  99.         
  100.     if ([arg_list top]==NULL)                 // only one arg
  101.         {
  102.         [return_val setString:"send error:  no function to call"];
  103.         [return_val setError:YES];
  104.         [name free];
  105.         [function free];
  106.         return return_val;
  107.         }
  108.     else
  109.         {
  110.         current=[arg_list pop];
  111.         [function setString:[current string]];
  112.         [current free];
  113.         }
  114.     sprintf (nm,"%s(COWS)",[name string]);
  115.     server = [NXConnection connectToName:nm];
  116.     if (server==nil)
  117.         {
  118.         [return_val setString:"send error:  cannot establish connection"];
  119.         [return_val setError:YES];
  120.         [name free];
  121.         [function free];
  122.         return return_val;
  123.         }
  124.  
  125.     if (![server conformsTo:@protocol(InterpreterIPC)])
  126.         {
  127.         [return_val setString:"send error:  remote object is not an interpreter"];
  128.         [return_val setError:YES];
  129.         [name free];
  130.         [function free];
  131.         return return_val;
  132.         }
  133.  
  134.     if (![server isForeground])
  135.         {
  136.         [return_val setString:
  137.             "send error:  remote interpreter is in background mode"];
  138.         [return_val setError:YES];    
  139.         [name free];
  140.         [function free];
  141.         return return_val;
  142.         }
  143.  
  144.     while ([arg_list top]!=NULL)
  145.         {
  146.         id current=[arg_list pop];
  147.         [server addArgument:(const char*)[current string]];
  148.         [current free];
  149.         }
  150.  
  151.     [server sendFunction:(const char*) [function string]:return_val];
  152.  
  153.     [function free];
  154.     [name free];
  155.         
  156.     return return_val;
  157.     }
  158.  
  159.  
  160.  
  161.  
  162. - ipc_send_machine:arg_list
  163.     {
  164.     char nm[COWSLARGESTPATHLENGTH];    
  165.     id return_val=[[COWSStringNode alloc] init];
  166.     id current;
  167.     id name=[[COWSStringNode alloc] init];
  168.     id function=[[COWSStringNode alloc] init];
  169.     id machine=[[COWSStringNode alloc] init];
  170.     id server;
  171.     
  172.     
  173.     if ([arg_list top]==NULL)                 // no args
  174.         {
  175.         [return_val setString:"send-remote error:  no machine to connect to"];
  176.         [return_val setError:YES];
  177.         [name free];
  178.         [machine free];
  179.         [function free];
  180.         return return_val;
  181.         }
  182.     else
  183.         {
  184.         current=[arg_list pop];
  185.         [machine setString:[current string]];
  186.         [current free];
  187.         }
  188.         
  189.     if ([arg_list top]==NULL)                 // no args
  190.         {
  191.         [return_val setString:"send-remote error:  nothing to connect to"];
  192.         [return_val setError:YES];
  193.         [name free];
  194.         [machine free];
  195.         [function free];
  196.         return return_val;
  197.         }
  198.     else
  199.         {
  200.         current=[arg_list pop];
  201.         [name setString:[current string]];
  202.         [current free];
  203.         }
  204.         
  205.     if ([arg_list top]==NULL)                 // only one arg
  206.         {
  207.         [return_val setString:"send-remote error:  no function to call"];
  208.         [return_val setError:YES];
  209.         [name free];
  210.         [machine free];
  211.         [function free];
  212.         return return_val;
  213.         }
  214.     else
  215.         {
  216.         current=[arg_list pop];
  217.         [function setString:[current string]];
  218.         [current free];
  219.         }
  220.  
  221.     sprintf (nm,"%s(COWS)",[name string]);
  222.     server = [NXConnection connectToName:nm onHost:[machine string]];
  223.     if (server==nil)
  224.         {
  225.         [return_val setString:"send-remote error:  cannot establish connection"];
  226.         [return_val setError:YES];
  227.         [name free];
  228.         [machine free];
  229.         [function free];
  230.         return return_val;
  231.         }
  232.  
  233.     if (![server conformsTo:@protocol(InterpreterIPC)])
  234.         {
  235.         [return_val setString:"send-remote error:  remote object is not an interpreter"];
  236.         [return_val setError:YES];
  237.         [name free];
  238.         [machine free];
  239.         [function free];
  240.         return return_val;
  241.         }
  242.  
  243.     if (![server isForeground])
  244.         {
  245.         [return_val setString:
  246.             "send-remote error:  remote interpreter is in background mode"];
  247.         [return_val setError:YES];    
  248.         [name free];
  249.         [machine free];
  250.         [function free];
  251.         return return_val;
  252.         }
  253.  
  254.     while ([arg_list top]!=NULL)
  255.         {
  256.         id current=[arg_list pop];
  257.         [server addArgument:(const char*)[current string]];
  258.         [current free];
  259.         }
  260.  
  261.     [server sendFunction:(const char*) [function string]:return_val];
  262.  
  263.     [name free];
  264.     [machine free];
  265.     [function free];
  266.         
  267.     return return_val;
  268.     }    
  269.     
  270.  
  271.  
  272.  
  273. - ipc_sendout:arg_list                    // calls a remote function in another
  274.                                         // interpreter and ignores answer.
  275.  
  276.     {
  277.     char nm[COWSLARGESTPATHLENGTH];    
  278.     id return_val=[[COWSStringNode alloc] init];
  279.     id current;
  280.     id name=[[COWSStringNode alloc] init];
  281.     id function=[[COWSStringNode alloc] init];
  282.     id server;
  283.     
  284.     
  285.     if ([arg_list top]==NULL)                 // no args
  286.         {
  287.         [return_val setString:"send-out error:  nothing to connect to"];
  288.         [return_val setError:YES];
  289.         [name free];
  290.         [function free];
  291.         return return_val;
  292.         }
  293.     else
  294.         {
  295.         current=[arg_list pop];
  296.         [name setString:[current string]];
  297.         [current free];
  298.         }
  299.         
  300.     if ([arg_list top]==NULL)                 // only one arg
  301.         {
  302.         [return_val setString:"send-out error:  no function to call"];
  303.         [return_val setError:YES];
  304.         [name free];
  305.         [function free];
  306.         return return_val;
  307.         }
  308.     else
  309.         {
  310.         current=[arg_list pop];
  311.         [function setString:[current string]];
  312.         [current free];
  313.         }
  314.     sprintf (nm,"%s(COWS)",[name string]);
  315.     server = [NXConnection connectToName:nm];
  316.     if (server==nil)
  317.         {
  318.         [return_val setString:"send-out error:  cannot establish connection"];
  319.         [return_val setError:YES];
  320.         [name free];
  321.         [function free];
  322.         return return_val;
  323.         }
  324.  
  325.     if (![server conformsTo:@protocol(InterpreterIPC)])
  326.         {
  327.         [return_val setString:"send-out error:  remote object is not an interpreter"];
  328.         [return_val setError:YES];
  329.         [name free];
  330.         [function free];
  331.         return return_val;
  332.         }
  333.  
  334.     while ([arg_list top]!=NULL)
  335.         {
  336.         id current=[arg_list pop];
  337.         [server addArgument:(const char*)[current string]];
  338.         [current free];
  339.         }
  340.  
  341.     [server sendOutFunction:(const char*) [function string]];
  342.     [function free];
  343.     [name free];
  344.         
  345.     return return_val;
  346.     }
  347.     
  348.     
  349. - ipc_sendout_machine:arg_list
  350.     {
  351.     char nm[COWSLARGESTPATHLENGTH];    
  352.     id return_val=[[COWSStringNode alloc] init];
  353.     id current;
  354.     id name=[[COWSStringNode alloc] init];
  355.     id function=[[COWSStringNode alloc] init];
  356.     id machine=[[COWSStringNode alloc] init];
  357.     id server;
  358.     
  359.     
  360.     if ([arg_list top]==NULL)                 // no args
  361.         {
  362.         [return_val setString:"send-out-remote error:  no machine to connect to"];
  363.         [return_val setError:YES];
  364.         [name free];
  365.         [machine free];
  366.         [function free];
  367.         return return_val;
  368.         }
  369.     else
  370.         {
  371.         current=[arg_list pop];
  372.         [machine setString:[current string]];
  373.         [current free];
  374.         }
  375.         
  376.     if ([arg_list top]==NULL)                 // no args
  377.         {
  378.         [return_val setString:"send-out-remote error:  nothing to connect to"];
  379.         [return_val setError:YES];
  380.         [name free];
  381.         [machine free];
  382.         [function free];
  383.         return return_val;
  384.         }
  385.     else
  386.         {
  387.         current=[arg_list pop];
  388.         [name setString:[current string]];
  389.         [current free];
  390.         }
  391.         
  392.     if ([arg_list top]==NULL)                 // only one arg
  393.         {
  394.         [return_val setString:"send-out-remote error:  no function to call"];
  395.         [return_val setError:YES];
  396.         [name free];
  397.         [machine free];
  398.         [function free];
  399.         return return_val;
  400.         }
  401.     else
  402.         {
  403.         current=[arg_list pop];
  404.         [function setString:[current string]];
  405.         [current free];
  406.         }
  407.  
  408.     sprintf (nm,"%s(COWS)",[name string]);
  409.     server = [NXConnection connectToName:nm onHost:[machine string]];
  410.     if (server==nil)
  411.         {
  412.         [return_val setString:"send-out-remote error:  cannot establish connection"];
  413.         [return_val setError:YES];
  414.         [name free];
  415.         [machine free];
  416.         [function free];
  417.         return return_val;
  418.         }
  419.  
  420.     if (![server conformsTo:@protocol(InterpreterIPC)])
  421.         {
  422.         [return_val setString:"send-out-remote error:  remote object is not an interpreter"];
  423.         [return_val setError:YES];
  424.         [name free];
  425.         [machine free];
  426.         [function free];
  427.         return return_val;
  428.         }
  429.  
  430.     while ([arg_list top]!=NULL)
  431.         {
  432.         id current=[arg_list pop];
  433.         [server addArgument:(const char*)[current string]];
  434.         [current free];
  435.         }
  436.  
  437.     [server sendOutFunction:(const char*) [function string]];
  438.     [name free];
  439.     [machine free];
  440.     [function free];
  441.         
  442.     return return_val;
  443.     }
  444.     
  445.     
  446.     
  447.     
  448.     
  449. // IPC MESSAGES
  450.  
  451.  
  452. - finishedInterpreting:(const char*)returnValue:(int)thisMessage:sender
  453.     // this message is sent to the delegate, if it can receive it, after
  454.     // the interpreter has finished interpreting a function request.
  455.     // it is defined here for IPC purposes (an interpreter can be its
  456.     // own delegate in an IPC process.
  457.     {
  458.     [result setString:returnValue];
  459.     [result setError:NO];
  460.     return self;
  461.     }
  462.  
  463. - errorInterpreting:(int) thisError:(const char*)thisFunction:
  464.     (int)thisPosition:(const char*)thisString:sender
  465.     // this message is sent to the delegate, if it can receive it, after
  466.     // the interpreter has encountered an error while interpreting.
  467.     {
  468.     [result setString:thisString];
  469.     [result setError:YES];
  470.     return self;
  471.     }
  472.  
  473.  
  474.  
  475.  
  476. - addArgument:(const char*)this_argument
  477.     {
  478.     id new_string;
  479.     printf ("Adding Argument: %s\n",this_argument);
  480.     if (arguments_state==COWSIPCLIBRARY_ARGSTATE_WORKING)
  481.         {
  482.         printf ("COWS IPC Error:  trying to begin new function before old one has finished\n");
  483.         return NULL;
  484.         }
  485.     
  486.     new_string=[[COWSStringNode alloc] init];
  487.     [new_string setString:this_argument];
  488.     [arguments push:new_string];
  489.     printf ("Added Argument:  %s\n",[new_string string]);
  490.     return NULL;
  491.     }
  492.  
  493.  
  494.  
  495. - (oneway void) sendOutFunction:(const char*) this_name
  496.     {
  497.     id arg_list=[[COWSArgumentList alloc] init];
  498.  
  499.     if (arguments_state==COWSIPCLIBRARY_ARGSTATE_WORKING)
  500.         {
  501.         printf ("COWS IPC Error:  calling new function before old one has finished\n");
  502.         }
  503.     else
  504.         {
  505.         arguments_state=COWSIPCLIBRARY_ARGSTATE_WORKING;
  506.         
  507.         // reverse the argument list    
  508.                 
  509.         while([arguments top]!=NULL)
  510.             {
  511.             [arg_list push:[arguments pop]];
  512.             }
  513.         
  514.         if (![interpreter locked]&&![interpreter working])
  515.             // i.e., interpreter is able to respond to messages
  516.             {
  517.             // note no delegate is assigned.
  518.             [interpreter setDelegate:NULL];
  519.             [interpreter interpretFunction:this_name arguments:arg_list];
  520.             }
  521.         
  522.         [arguments clear];
  523.         arguments_state=COWSIPCLIBRARY_ARGSTATE_READY;
  524.         }
  525.     [arg_list free];
  526.     }
  527.  
  528.  
  529.  
  530.  
  531.  
  532. - sendFunction:(const char*) this_name:reply
  533.     {
  534.     id arg_list=[[COWSArgumentList alloc] init];
  535.     
  536.     if (arguments_state==COWSIPCLIBRARY_ARGSTATE_WORKING)
  537.         {
  538.         char junk[COWSLARGESTPATHLENGTH+40];
  539.         sprintf (junk,"remote send error (%s):  calling new function before old one has finished.", [NXApp appName]);        
  540.         [reply setString:junk];
  541.         [reply setError:YES];    
  542.         }
  543.     else
  544.         {
  545.         arguments_state=COWSIPCLIBRARY_ARGSTATE_WORKING;
  546.         
  547.         // clean out response
  548.         
  549.         [result setString:""];
  550.         [result setError:NO];
  551.         
  552.         // reverse the argument list    
  553.                 
  554.         while([arguments top]!=NULL)
  555.             {
  556.             [arg_list push:[arguments pop]];
  557.             }
  558.         
  559.         if (![interpreter locked]&&![interpreter working])
  560.             {
  561.             [interpreter setDelegate:self];
  562.             [interpreter interpretFunction:this_name arguments:arg_list];
  563.             [reply setString:(const char*)[result string]];
  564.             [reply setError:[result error]];
  565.             }
  566.         else
  567.             {
  568.             char junk[COWSLARGESTPATHLENGTH+40];
  569.             sprintf (junk,"remote send error (%s):  interpreter is unavailable.", [NXApp appName]);
  570.             [reply setString: junk];
  571.             [reply setError:YES];    
  572.             }
  573.         arguments_state=COWSIPCLIBRARY_ARGSTATE_READY;
  574.         }
  575.     [arg_list free];
  576.     return NULL;
  577.     }
  578.  
  579.  
  580. - (BOOL) isForeground
  581.     {
  582.     if (interpreter==NULL) 
  583.         {
  584.         printf ("Yikes!  No Interpreter\n");
  585.         return NO;
  586.         }
  587.     return [interpreter foreground];
  588.     }
  589.  
  590. - pauseCancelled:sender
  591.     {
  592.     return NULL;
  593.     }
  594.  
  595. - pauseInterpreter:remote_process
  596.     {
  597.     [interpreter pauseInterpreting:remote_process];
  598.     return NULL;
  599.     }
  600.     
  601.     
  602.     
  603. - ipc_launch:arg_list
  604.     {
  605.     id return_val=[[COWSStringNode alloc] init];
  606.     id current;
  607.     id name=[[COWSStringNode alloc] init];
  608.     id machine=[[COWSStringNode alloc] init];
  609.     port_t response;
  610.     
  611.     if ([arg_list top]==NULL)                 // no args
  612.         {
  613.         [return_val setString:"launch error:  nothing to launch"];
  614.         [return_val setError:YES];
  615.         [name free];
  616.         [machine free];
  617.         return return_val;
  618.         }
  619.     else
  620.         {
  621.         current=[arg_list pop];
  622.         [name setString:[current string]];
  623.         [current free];
  624.         }
  625.         
  626.     if ([arg_list top]==NULL)                 // only one arg
  627.         {
  628.         char host[MAXHOSTNAMELEN];
  629.         gethostname(host,MAXHOSTNAMELEN);
  630.         [machine setString:(const char*) host];
  631.         }
  632.     else
  633.         {
  634.         current=[arg_list pop];
  635.         [machine setString:[current string]];
  636.         [current free];
  637.         }
  638.  
  639.     response=NXPortFromName([name string],[machine string]);
  640.  
  641.     if (response==PORT_NULL)
  642.         {
  643.         [return_val setString:"f"];
  644.         [name free];
  645.         [machine free];
  646.         return return_val;
  647.         }
  648.  
  649.     [return_val setString:"t"];
  650.     [name free];
  651.     [machine free];
  652.     
  653.     return return_val;
  654.     }
  655.  
  656.  
  657.  
  658. - ipc_launched:arg_list
  659.     {
  660.     id return_val=[[COWSStringNode alloc] init];
  661.     id current;
  662.     id name=[[COWSStringNode alloc] init];
  663.     id machine=[[COWSStringNode alloc] init];
  664.     port_t response;
  665.     
  666.     if ([arg_list top]==NULL)                 // no args
  667.         {
  668.         [return_val setString:"launched? error:  nothing to check for"];
  669.         [return_val setError:YES];
  670.         [name free];
  671.         [machine free];
  672.         return return_val;
  673.         }
  674.     else
  675.         {
  676.         current=[arg_list pop];
  677.         [name setString:[current string]];
  678.         [current free];
  679.         }
  680.         
  681.     if ([arg_list top]==NULL)                 // only one arg
  682.         {
  683.         char host[MAXHOSTNAMELEN];
  684.         gethostname(host,MAXHOSTNAMELEN);
  685.         [machine setString:(const char*) host];
  686.         }
  687.     else
  688.         {
  689.         current=[arg_list pop];
  690.         [machine setString:[current string]];
  691.         [current free];
  692.         }
  693.  
  694.     response=NXPortNameLookup([name string],[machine string]);
  695.  
  696.     if (response==PORT_NULL)
  697.         {
  698.         [return_val setString:"f"];
  699.         [name free];
  700.         [machine free];
  701.         return return_val;
  702.         }
  703.  
  704.     [return_val setString:"t"];
  705.         
  706.     [name free];
  707.     [machine free];
  708.     return return_val;
  709.     }
  710.  
  711.  
  712. @end
  713.