home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff299.lzh / Rxil / demo.c < prev    next >
C/C++ Source or Header  |  1989-12-30  |  13KB  |  589 lines

  1. /* demo.c    */
  2.  
  3.  
  4.  
  5. /* A small demo program for the Rxil library.
  6.  *
  7.  * This must be run from the CLI only.  This is due to the diagnostic
  8.  * info that is sent to the CLI.
  9.  *
  10.  * This program implments a fairly full-featured ARexx port.
  11.  * The demo program itself is more along the lines of a "hack" and
  12.  * was not written with robustness in mind (especially the child macro
  13.  * launching stuff).
  14.  * It does show how few the lines of code needed are.
  15.  */
  16.  
  17.  
  18.  
  19. /*        Copyright © 1989 by Donald T. Meyer, Stormgate Software
  20.  *        All Rights Reserved
  21.  *
  22.  *        This source code may be compiled and used in any software
  23.  *        product.
  24.  *        No portion of this source code is to be re-distributed or
  25.  *        sold for profit.
  26.  *
  27.  *        Donald T. Meyer
  28.  *        Stormgate Software
  29.  *        P.O. Box 383
  30.  *        St. Peters, MO  63376
  31.  *
  32.  *        BIX:    donmeyer        (usually daily)
  33.  *        GEnie:    D.MEYER            (weekly)
  34.  *        PLINK:    Stormgate        (weekly)
  35.  */
  36.  
  37.  
  38.  
  39. /*        The Commands this program understands from ARexx:
  40.  *
  41.  *        STATUS <l|b|x|y|z>
  42.  *        A do-nothing command which returns various strings and result
  43.  *        codes.
  44.  *
  45.  *        DUMP [e|c|s]
  46.  *        Display some things about the ARexx environment that this
  47.  *        program has established.
  48.  *
  49.  *        LOCK
  50.  *        Engage this program in an exclusive conversation.
  51.  *        Returns the name of the secret port.
  52.  *
  53.  *        UNLOCK
  54.  *        Releases the lock.
  55.  *
  56.  *        LCMD
  57.  *        Allows the launching of an ARexx program as a "command".
  58.  *
  59.  *        LFUNC
  60.  *        Allows the launching of an ARexx program as a "function".
  61.  *
  62.  *        PTEST
  63.  *        Returns a dummy string.  Works only from a "child" ARexx
  64.  *        program or from an ARexx program which has acquired a lock.
  65.  *
  66.  *        QUIT
  67.  *        Causes the program to terminate.  This is the only way to
  68.  *        exit!
  69.  *
  70.  *
  71.  * These descriptions are terse, I know.  Looking at the code here
  72.  * is the best way to get a feel for just what is happening.
  73.  * To play with this, run it, and then run an ARexx program whose
  74.  * host address is set to "MYREXX_TEST_#1".
  75.  * Then issue some commands!  Note that most things require that the
  76.  * results flag be set via an ARexx "options results" statement.
  77.  */
  78.  
  79.  
  80.  
  81. #include "rxil.h"
  82.  
  83. #include <graphics/gfxbase.h>
  84. #include <libraries/dos.h>
  85.  
  86. #include <stdio.h>
  87. #include <string.h>
  88. #include <stdlib.h>
  89.  
  90. #ifdef LATTICE
  91. #include <proto/intuition.h>
  92. #endif
  93.  
  94.  
  95.  
  96. /*--------------------------------------------------------------------*/
  97.  
  98. void openlibrarys( void );
  99. void closelibrarys( void );
  100. void cleanup( void );
  101. void bailout( char *message, int rc );
  102.  
  103. void eventloop( void );
  104.  
  105.  
  106.  
  107. void cmd_status( struct RexxMsg *rexxmsg );
  108. void cmd_quit( struct RexxMsg *rexxmsg );
  109. void cmd_launch_cmd( struct RexxMsg *rexxmsg );
  110. void cmd_launch_func( struct RexxMsg *rexxmsg );
  111. void cmd_ptest( struct RexxMsg *rexxmsg );
  112. void cmd_dump( struct RexxMsg *rexxmsg );
  113.  
  114.  
  115.  
  116. /*--------------------------------------------------------------------*/
  117.  
  118. struct IntuitionBase *IntuitionBase = NULL;
  119. struct GfxBase *GfxBase = NULL;
  120.  
  121.  
  122. BOOL finished = FALSE;
  123.  
  124.  
  125.  
  126. /************************************
  127.  *                                    *
  128.  *    Defined for Rexx Interface    *
  129.  *                                    *
  130.  ************************************/
  131.  
  132. struct RxilDef *global_rdef = NULL;
  133.  
  134.  
  135. struct RxilFunction rexx_cmd_table[] = {
  136.     { "lock", &RxilCmdLock, 0, 0, FALSE, RXIL_PUBLIC },
  137.     { "unlock", &RxilCmdUnlock, 0, 0, FALSE, RXIL_SECRET },
  138.  
  139.     { "status", &cmd_status, 1, 1, FALSE, RXIL_PUBLIC },
  140.     { "quit", &cmd_quit, 0, 0, FALSE, RXIL_PUBLIC },
  141.     { "dump", &cmd_dump, 0, 1, FALSE, RXIL_PUBLIC },
  142.     { "lcmd", &cmd_launch_cmd, 0, 0, FALSE, RXIL_PUBLIC },
  143.     { "lfunc", &cmd_launch_func, 0, 0, FALSE, RXIL_PUBLIC },
  144.     { "ptest", &cmd_ptest, 0, 0, FALSE, RXIL_SECRET },
  145.  
  146.     /* Mark end-of-table */
  147.     { NULL, NULL, 0, 0, FALSE, 0 }
  148. };
  149.  
  150.  
  151. /********************************************************************/
  152.  
  153.  
  154. struct RxilInvocation *rxi_func;
  155. struct RxilInvocation *rxi_cmd;
  156.     /* For general purpose testing use.  These would not be
  157.      * needed as other than local, temporary variables if we were
  158.      * allocating and de-allocating RxilInvocation structures on
  159.      * the fly (since the Rxil library tracks all RxilInvocation
  160.      * structures allocated).
  161.      */
  162.  
  163.  
  164. struct RxilInvocation *rxi_startup;
  165.     /* This one is for the startup macro.  We want to retain it's pointer
  166.      * even after it is launched so that we can "recognize" it when
  167.      * it terminates and handle it differently.
  168.      */
  169.  
  170.  
  171. /*--------------------------------------------------------------------*/
  172.  
  173.  
  174. void main( int argc, char *argv[] )
  175. {
  176.     openlibrarys();
  177.  
  178.  
  179.     /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
  180.      * This will open the rexx library, and the desired ports.
  181.      * If all we want to do is receive commands, we probably
  182.      * would not open the secret port, although we might. 
  183.      */
  184.     global_rdef = RxilInit( RXIL_PUBLIC | RXIL_SECRET, "MYREXX_TEST" );
  185.     if( global_rdef == NULL )
  186.     {
  187.         bailout( "Unable to init rexx", 0 );
  188.     }
  189.  
  190.  
  191.     /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
  192.      * Init the members in the RxilDef structure which customize
  193.      * the way things work.
  194.      */
  195.  
  196. /*    global_rdef->Flags = RXIL_NO_REQ | RXIL_NO_ABORT; */
  197.         /* Set flags here to control various characteristics of the
  198.          * library routines.
  199.          * The default in this demo is to not set any flags, which
  200.          * typicaly turn _off_ features.
  201.          */
  202.  
  203.     global_rdef->Console = "CON:10/10/400/150/RexxCon";
  204.         /* All commands or functions launched by this program will open
  205.          * a console window of this specification.  Set this to NULL to
  206.          * default to no window.
  207.          */
  208.  
  209.     global_rdef->Extension = "rexx";
  210.         /* this normally would be an application
  211.          * specific macro filename extension.
  212.          */
  213.  
  214.     global_rdef->HostPort = "REXX";
  215.         /* If this is AREXX, launches will default
  216.          * to async (as opposed to synchronous).
  217.          */
  218.  
  219.     global_rdef->CommandTable = &rexx_cmd_table[0];
  220.  
  221.  
  222.  
  223.  
  224.  
  225.     /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
  226.      * Pre-allocate some invocation structures.  These could
  227.      * also be allocated and de-allocated on-the-fly if desired.
  228.      * One possible philosophy would be to allocate one structure
  229.      * for each possible macro command.  This would speed macro
  230.      * invocations by a slight amount.
  231.      */
  232.     rxi_cmd = RxilCreateRxi( NULL, RXCOMM );
  233.     if( rxi_cmd == NULL )
  234.     {
  235.         bailout( "Unable to allocate command_rxi", RETURN_FAIL );
  236.     }
  237.  
  238.     rxi_func = RxilCreateRxi( NULL, RXFUNC );
  239.     if( rxi_func == NULL )
  240.     {
  241.         bailout( "Unable to allocate function_rxi", RETURN_FAIL );
  242.     }
  243.  
  244.  
  245.  
  246.     /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
  247.      * This is an example of running a "startup" macro each time the
  248.      * program is invoked.  The RxilInvocation will be allocated and
  249.      * then freed when it returns.
  250.      */
  251.     rxi_startup = RxilCreateRxi( "startup.rxil", RXCOMM );
  252.     if( rxi_startup == NULL )
  253.     {
  254.         /* Just because the startup macro did not work, you would
  255.          * probably not normally give up.
  256.          */
  257.         printf( "** Unable to allocate startup rxi **\n" );
  258.     }
  259.     else
  260.     {
  261.         /* We want our own console spec, not the default.  In some
  262.          * (most?) real applications a console would probably not be
  263.          * opened.  We do it here for illustration purposes.
  264.          */
  265.         rxi_startup->Console = "CON:0/80/620/100/Demo Startup Macro";
  266.  
  267.         if(  RxilLaunch( rxi_startup ) != 0  )
  268.         {
  269.             /* Informative message only */
  270.             printf( "** Unable to launch the startup macro **\n" );
  271.         }
  272.     }
  273.  
  274.     eventloop();
  275.  
  276.     cleanup();
  277. }
  278.  
  279.  
  280.  
  281. /*-----------------------------------------------------------------*/
  282.  
  283.  
  284. void eventloop( void )
  285. {
  286.     struct RxilInvocation *rxi;
  287.     ULONG flags;
  288.  
  289.  
  290.     while( !finished )
  291.     {
  292.         /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
  293.          * Note that we include the rexx port signal bit(s) in the wait().
  294.          */
  295.         flags = Wait( RXIL_WAITFLAG );
  296.  
  297.  
  298.         /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
  299.          * Now do the ARexx port stuff.
  300.          */
  301.         if(  FlagIsSet( flags, RXIL_WAITFLAG )  )
  302.         {
  303.             RxilCheckPort();
  304.         }
  305.  
  306.  
  307.         /* Some info for debugging purposes... */
  308.  
  309.         printf( "---Event---\n" );
  310.         printf( "rxi_cmd state: %d\n", (int)rxi_cmd->State );
  311.         printf( "rxi_func state: %d\n", (int)rxi_func->State );
  312.  
  313.  
  314.         /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
  315.          * Get any ARexx invocation returns which may be back.
  316.          * This code would not be present on a minimal implementation
  317.          * which does not launch macros, just responds to simple
  318.          * commands.
  319.          */
  320.         while(  ( rxi = RxilGetReturn() ) != NULL  )
  321.         {
  322.             if( rxi->Type == RXCOMM )
  323.             {
  324.                 printf( "Command Invocation completed\n" );
  325.             }
  326.             else
  327.             {
  328.                 printf( "Function Invocation completed\n" );
  329.             }
  330.  
  331.             if( rxi == rxi_startup )
  332.             {
  333.                 /* This is our startup macro terminating.  We handle
  334.                  * this differently since we don't want to display
  335.                  * an error if not found (which the standard routine
  336.                  * RxilHandleReturn would do).  And we also want to
  337.                  * de-allocate the RxilInvocation structure.
  338.                  */
  339.  
  340.                 /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+
  341.                  * Deallocate things, close console windows, etc.
  342.                  * Then free the structure.
  343.                  */
  344.                 if(  ( rxi->RexxMsg->rm_Result1 != RC_WARN ) ||
  345.                     ( rxi->RexxMsg->rm_Result2 != ERR10_001 )  )
  346.                 {
  347.                     /* The error is not just "program not found".
  348.                      * This is a true error, tell the user.
  349.                      */
  350.                     RxilHandleReturn( rxi );
  351.                 }
  352.  
  353.                 RxilCleanupReturn( rxi );
  354.                 RxilDeleteRxi( rxi );
  355.                 rxi_startup = NULL;        /* To be tidy... */
  356.             }
  357.             else
  358.             {
  359.                 /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+
  360.                  * Tell user about error returns, etc.
  361.                  * This can either be replaced by client code to handle
  362.                  * returns in a specific way, or not done at all (not very
  363.                  * friendly) and nothing will break...
  364.                  */
  365.                 RxilHandleReturn( rxi );
  366.  
  367.                 /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+
  368.                  * Deallocate things, close console windows, etc.
  369.                  */
  370.                 RxilCleanupReturn( rxi );
  371.             }
  372.         }
  373.     }
  374. }
  375.  
  376.  
  377.  
  378. void cmd_status( struct RexxMsg *rexxmsg )
  379. {
  380.     printf( "Cmd status\n" );
  381.     printf( "The FromRexx variable is %d\n", RXIL_FROM_REXX );
  382.  
  383.     switch( *RXIL_ARGV(1) )
  384.     {
  385.         case 'L':
  386.         case 'l':
  387.             RxilSetResult( rexxmsg, "Hi there!" );
  388.             break;
  389.  
  390.         case 'B':
  391.         case 'b':
  392.             RxilSetResult( rexxmsg, "I'm NOT Fine!" );
  393.             break;
  394.  
  395.         case 'X':
  396.         case 'x':
  397.             rexxmsg->rm_Result1 = 20;
  398.             break;
  399.  
  400.         case 'Y':
  401.         case 'y':
  402.             rexxmsg->rm_Result1 = 100;
  403.             break;
  404.  
  405.         case 'Z':
  406.         case 'z':
  407.             rexxmsg->rm_Result1 = 200;
  408.             break;
  409.  
  410.         default:
  411.             rexxmsg->rm_Result1 = RXERR_INVALID_ARG;
  412.     }
  413. }
  414.  
  415.  
  416.  
  417. /* This will only succeed if the command comes in at the private port.
  418.  */
  419.  
  420. void cmd_ptest( struct RexxMsg *rexxmsg )
  421. {
  422.     printf( "Cmd privilege test\n" );
  423.  
  424.     RxilSetResult( rexxmsg, "You are privileged indeed!" );
  425. }
  426.  
  427.  
  428.  
  429. /* Cause the demo program to exit. */
  430.  
  431. void cmd_quit( struct RexxMsg *rexxmsg )
  432. {
  433.     printf( "Cmd quit\n" );
  434.  
  435.     finished = TRUE;
  436. }
  437.  
  438.  
  439.  
  440. void cmd_dump( struct RexxMsg *rexxmsg )
  441. {
  442.     ULONG flags = 0;
  443.  
  444.  
  445.     if( RXIL_ARGC > 1 )
  446.     {
  447.         if(  strnicmp( RXIL_ARGV(1), "ENVIRONMENT",
  448.             strlen(RXIL_ARGV(1)) ) == 0  )
  449.         {
  450.             flags = RXIL_DUMP_ENV;
  451.         }
  452.  
  453.         if(  strnicmp( RXIL_ARGV(1), "STATE",
  454.             strlen(RXIL_ARGV(1)) ) == 0  )
  455.         {
  456.             flags = RXIL_DUMP_STATE;
  457.         }
  458.  
  459.         if(  strnicmp( RXIL_ARGV(1), "COMMANDS",
  460.             strlen(RXIL_ARGV(1)) ) == 0  )
  461.         {
  462.             flags = RXIL_DUMP_CMDS;
  463.         }
  464.     }
  465.     else
  466.     {
  467.         flags = RXIL_DUMP_ENV | RXIL_DUMP_CMDS | RXIL_DUMP_STATE;
  468.     }
  469.  
  470.     if( flags == 0 )
  471.     {
  472.         /* The keyword was not valid */
  473.         rexxmsg->rm_Result1 = RXERR_INVALID_ARG;
  474.         return;
  475.     }
  476.  
  477.     RxilDumpRdef( global_rdef, flags );
  478. }
  479.  
  480.  
  481.  
  482. void cmd_launch_cmd( struct RexxMsg *rexxmsg )
  483. {
  484.     static char buf[100];
  485.     LONG rc;
  486.  
  487.  
  488.     printf( "Cmd launch command:" );
  489.     gets( buf );
  490.  
  491.     rxi_cmd->Name = buf;
  492.     rc = RxilLaunch( rxi_cmd );
  493.     printf( "Launch returned %d\n", rc );
  494. }
  495.  
  496.  
  497.  
  498. static char buf[16][100];
  499.  
  500.  
  501. void cmd_launch_func( struct RexxMsg *rexxmsg )
  502. {
  503.     LONG rc;
  504.     int i;
  505.  
  506.  
  507.     printf( "Cmd launch function:" );
  508.     gets( &buf[0][0] );
  509.  
  510.     for( i=1; i<16; i++ )
  511.     {
  512.         printf( "Enter arg %d: ", i );
  513.         gets( &buf[i][0] );
  514.         if( strlen(&buf[i][0]) > 0 )
  515.         {
  516.             rxi_func->FuncArg[i] = &buf[i][0];
  517.         }
  518.         else
  519.         {
  520.             rxi_func->FuncArg[i] = NULL;
  521.             break;
  522.         }
  523.     }
  524.  
  525.     rxi_func->Name = &buf[0][0];
  526.  
  527.     rc = RxilLaunch( rxi_func );
  528.  
  529.     printf( "Launch returned %d\n", rc );
  530. }
  531.  
  532.  
  533.  
  534. /*-----------------------------------------------------------------*/
  535.  
  536.  
  537.  
  538.  
  539. void openlibrarys( void )
  540. {
  541.     /*   Intuition   */
  542.     if(  ! ( IntuitionBase = (struct IntuitionBase *)
  543.         OpenLibrary("intuition.library", 33 ) )  )
  544.     {
  545.         bailout( "Unable to open the Intuition Library", RETURN_FAIL );
  546.     }
  547.  
  548.     /*   Graphics   */
  549.     if(  ! ( GfxBase = (struct GfxBase *)
  550.         OpenLibrary("graphics.library", 33 ) )  )
  551.     {
  552.         bailout("Unable to open the Graphics Library", RETURN_FAIL );
  553.     }
  554. }
  555.  
  556.  
  557.  
  558. void closelibrarys( void )
  559. {
  560.     if( IntuitionBase )   CloseLibrary( (struct Library *)IntuitionBase );
  561.     if( GfxBase )   CloseLibrary( (struct Library *)GfxBase );
  562. }
  563.  
  564.  
  565.  
  566. void cleanup( void )
  567. {
  568.     /* =+=+=+=+=+=+=+=+=+  ARexx Interface Note +=+=+=+=+=+=+=+=+=+=+
  569.      * This will handle ALL the cleanup details.  If we wished to make
  570.      * sure that there were no macro program invocations running before
  571.      * we call this routine (and it waits, which may distress the user)
  572.      * we should test our ability to terminate by calling RxilPending().
  573.      */
  574.     RxilCleanup( global_rdef );
  575.     global_rdef = NULL;
  576.  
  577.     closelibrarys();
  578. }
  579.  
  580.  
  581.  
  582. void bailout( char *message, int rc )
  583. {
  584.     printf( "%s/n", message );
  585.     cleanup();
  586.     exit( rc );
  587. }
  588.  
  589.