home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / new / util / cdity / colorsaver / src / simplerexx.c < prev    next >
C/C++ Source or Header  |  1994-11-28  |  11KB  |  437 lines

  1. /*
  2.  * Simple ARexx interface by Michael Sinz
  3.  *
  4.  * This is a very "Simple" interface to the world of ARexx...
  5.  * For more complex interfaces into ARexx, it is best that you
  6.  * understand the functions that are provided by ARexx.
  7.  * In many cases they are more powerful than what is presented
  8.  * here.
  9.  *
  10.  * This code is fully re-entrant and self-contained other than
  11.  * the use of SysBase/AbsExecBase and the ARexx RVI support
  12.  * library which is also self-contained...
  13.  */
  14.  
  15. #include    <exec/types.h>
  16. #include    <exec/nodes.h>
  17. #include    <exec/lists.h>
  18. #include    <exec/ports.h>
  19. #include    <exec/memory.h>
  20.  
  21. #include    <proto/exec.h>
  22.  
  23. #include    <rexx/storage.h>
  24. #include    <rexx/rxslib.h>
  25.  
  26. #include    <string.h>
  27. #include    <ctype.h>
  28.  
  29. #ifdef _DCC
  30. #include       <clib/alib_protos.h>
  31. #include       <clib/alib_stdio_protos.h>
  32. #include       <clib/rexxsyslib_protos.h>
  33.  
  34. long CheckRexxMsg(struct RexxMsg *);
  35. long GetRexxVar(struct RexxMsg *,char *,char **);
  36. long SetRexxVar(struct RexxMsg *,char *,char *,long);
  37.  
  38. #endif
  39.  
  40. #ifdef LATTICE
  41. /*
  42.  * The prototypes for the few ARexx functions we will call...
  43.  */
  44. struct RexxMsg *CreateRexxMsg(struct MsgPort *,char *,char *);
  45. void *CreateArgstring(char *,long);
  46. void DeleteRexxMsg(struct RexxMsg *);
  47. void DeleteArgstring(char *);
  48. BOOL IsRexxMsg(struct Message *);
  49.  
  50. /*
  51.  * Pragmas for the above functions...  (To make this all self-contained...)
  52.  * If you use RexxGlue.o, this is not needed...
  53.  *
  54.  * These are for Lattice C 5.x  (Note the use of RexxContext->RexxSysBase)
  55.  */
  56. #pragma libcall RexxContext->RexxSysBase CreateRexxMsg 90 09803
  57. #pragma libcall RexxContext->RexxSysBase CreateArgstring 7E 0802
  58. #pragma libcall RexxContext->RexxSysBase DeleteRexxMsg 96 801
  59. #pragma libcall RexxContext->RexxSysBase DeleteArgstring 84 801
  60. #pragma libcall RexxContext->RexxSysBase IsRexxMsg A8 801
  61.  
  62.  
  63.  
  64. /*
  65.  * Prototypes for the RVI ARexx calls...  (link with RexxVars.o)
  66.  */
  67. __stdargs long CheckRexxMsg(struct RexxMsg *);
  68. __stdargs long GetRexxVar(struct RexxMsg *,char *,char **);
  69. __stdargs long SetRexxVar(struct RexxMsg *,char *,char *,long);
  70.  
  71. #endif
  72.  
  73. /*
  74.  * Now, we have made the pragmas needed, let's get to work...
  75.  */
  76.  
  77. /*
  78.  * A structure for the ARexx handler context
  79.  * This is *VERY* *PRIVATE* and should not be touched...
  80.  */
  81. struct    ARexxContext
  82. {
  83. struct    MsgPort    *ARexxPort;    /* The port messages come in at... */
  84. struct    Library    *RexxSysBase;    /* We will hide the library pointer here... */
  85.     long    Outstanding;    /* The count of outstanding ARexx messages... */
  86.     char    PortName[24];    /* The port name goes here... */
  87.     char    ErrorName[28];    /* The name of the <base>.LASTERROR... */
  88.     char    Extension[8];    /* Default file name extension... */
  89. };
  90.  
  91. #define    AREXXCONTEXT    struct ARexxContext *
  92.  
  93. #include    "SimpleRexx.h"
  94.  
  95. /*
  96.  * This function returns the port name of your ARexx port.
  97.  * It will return NULL if there is no ARexx port...
  98.  *
  99.  * This string is *READ ONLY*  You *MUST NOT* modify it...
  100.  */
  101. char *ARexxName(AREXXCONTEXT RexxContext)
  102. {
  103. register    char    *tmp=NULL;
  104.  
  105.     if (RexxContext) tmp=RexxContext->PortName;
  106.     return(tmp);
  107. }
  108.  
  109. /*
  110.  * This function returns the signal mask that the Rexx port is
  111.  * using.  It returns NULL if there is no signal...
  112.  *
  113.  * Use this signal bit in your Wait() loop...
  114.  */
  115. ULONG ARexxSignal(AREXXCONTEXT RexxContext)
  116. {
  117. register    ULONG    tmp=NULL;
  118.  
  119.     if (RexxContext) tmp=1L << (RexxContext->ARexxPort->mp_SigBit);
  120.     return(tmp);
  121. }
  122.  
  123. /*
  124.  * This function returns a structure that contains the commands sent from
  125.  * ARexx...  You will need to parse it and return the structure back
  126.  * so that the memory can be freed...
  127.  *
  128.  * This returns NULL if there was no message...
  129.  */
  130. struct RexxMsg *GetARexxMsg(AREXXCONTEXT RexxContext)
  131. {
  132. register    struct    RexxMsg    *tmp=NULL;
  133. register        long    flag;
  134.  
  135.     if (RexxContext)
  136.         if (tmp=(struct RexxMsg *)GetMsg(RexxContext->ARexxPort))
  137.     {
  138.         if (tmp->rm_Node.mn_Node.ln_Type==NT_REPLYMSG)
  139.         {
  140.             /*
  141.              * If we had sent a command, it would come this way...
  142.              *
  143.              * Since we don't in this simple example, we just throw
  144.              * away anything that looks "strange"
  145.              */
  146.             flag=FALSE;
  147.             if (tmp->rm_Result1) flag=TRUE;
  148.  
  149.             /*
  150.              * Free the arguments and the message...
  151.              */
  152.             DeleteArgstring(tmp->rm_Args[0]);
  153.             DeleteRexxMsg(tmp);
  154.             RexxContext->Outstanding-=1;
  155.  
  156.             /*
  157.              * Return the error if there was one...
  158.              */
  159.             tmp= (struct RexxMsg *)(flag ? REXX_RETURN_ERROR : NULL);
  160.         }
  161.     }
  162.     return(tmp);
  163. }
  164.  
  165. /*
  166.  * Use this to return a ARexx message...
  167.  *
  168.  * If you wish to return something, it must be in the RString.
  169.  * If you wish to return an Error, it must be in the Error.
  170.  * If there is an error, the RString is ignored.
  171.  */
  172. void ReplyARexxMsg(AREXXCONTEXT RexxContext,struct RexxMsg *rmsg,
  173.             char *RString,LONG Error)
  174. {
  175.     if (RexxContext) if (rmsg) if (rmsg!=REXX_RETURN_ERROR)
  176.     {
  177.         rmsg->rm_Result2=0;
  178.         if (!(rmsg->rm_Result1=Error))
  179.         {
  180.             /*
  181.              * if you did not have an error we return the string
  182.              */
  183.             if (rmsg->rm_Action & (1L << RXFB_RESULT)) if (RString)
  184.             {
  185.                 rmsg->rm_Result2=(LONG)CreateArgstring(RString,
  186.                             (LONG)strlen(RString));
  187.             }
  188.         }
  189.  
  190.         /*
  191.          * Reply the message to ARexx...
  192.          */
  193.         ReplyMsg((struct Message *)rmsg);
  194.     }
  195. }
  196.  
  197. /*
  198.  * This function will set an error string for the ARexx
  199.  * application in the variable defined as <appname>.LASTERROR
  200.  *
  201.  * Note that this can only happen if there is an ARexx message...
  202.  *
  203.  * This returns TRUE if it worked, FALSE if it did not...
  204.  */
  205. short SetARexxLastError(AREXXCONTEXT RexxContext,struct RexxMsg *rmsg,
  206.             char *ErrorString)
  207. {
  208. register    short    OkFlag=FALSE;
  209.  
  210.     if (RexxContext) if (rmsg) if (CheckRexxMsg(rmsg))
  211.     {
  212.         /*
  213.          * Note that SetRexxVar() has more than just a TRUE/FALSE
  214.          * return code, but for this "basic" case, we just care if
  215.          * it works or not.
  216.          */
  217.         if (!SetRexxVar(rmsg,RexxContext->ErrorName,ErrorString,
  218.                         (long)strlen(ErrorString)))
  219.         {
  220.             OkFlag=TRUE;
  221.         }
  222.     }
  223.     return(OkFlag);
  224. }
  225.  
  226. /*
  227.  * This function will send a string to ARexx...
  228.  *
  229.  * The default host port will be that of your task...
  230.  *
  231.  * If you set StringFile to TRUE, it will set that bit for the message...
  232.  *
  233.  * Returns TRUE if it send the message, FALSE if it did not...
  234.  */
  235. short SendARexxMsg(AREXXCONTEXT RexxContext,char *RString,
  236.             short StringFile)
  237. {
  238. register    struct    MsgPort    *RexxPort;
  239. register    struct    RexxMsg    *rmsg;
  240. register        short    flag=FALSE;
  241.  
  242.     if (RexxContext) if (RString)
  243.     {
  244.         if (rmsg=CreateRexxMsg(RexxContext->ARexxPort,
  245.                     RexxContext->Extension,
  246.                     RexxContext->PortName))
  247.         {
  248.             rmsg->rm_Action=RXCOMM | (StringFile ?
  249.                             (1L << RXFB_STRING):0);
  250.             if (rmsg->rm_Args[0]=CreateArgstring(RString,
  251.                             (LONG)strlen(RString)))
  252.             {
  253.                 /*
  254.                  * We need to find the RexxPort and this needs
  255.                  * to be done in a Forbid()
  256.                  */
  257.                 Forbid();
  258.                 if (RexxPort=FindPort(RXSDIR))
  259.                 {
  260.                     /*
  261.                      * We found the port, so put the
  262.                      * message to ARexx...
  263.                      */
  264.                     PutMsg(RexxPort,(struct Message *)rmsg);
  265.                     RexxContext->Outstanding+=1;
  266.                     flag=TRUE;
  267.                 }
  268.                 else
  269.                 {
  270.                     /*
  271.                      * No port, so clean up...
  272.                      */
  273.                     DeleteArgstring(rmsg->rm_Args[0]);
  274.                     DeleteRexxMsg(rmsg);
  275.                 }
  276.                 Permit();
  277.             }
  278.             else DeleteRexxMsg(rmsg);
  279.         }
  280.     }
  281.     return(flag);
  282. }
  283.  
  284. /*
  285.  * This function closes down the ARexx context that was opened
  286.  * with InitARexx...
  287.  */
  288. void FreeARexx(AREXXCONTEXT RexxContext)
  289. {
  290. register    struct    RexxMsg    *rmsg;
  291.  
  292.     if (RexxContext)
  293.     {
  294.         /*
  295.          * Clear port name so it can't be found...
  296.          */
  297.         RexxContext->PortName[0]='\0';
  298.  
  299.         /*
  300.          * Clean out any outstanding messages we had sent out...
  301.          */
  302.         while (RexxContext->Outstanding)
  303.         {
  304.             WaitPort(RexxContext->ARexxPort);
  305.             while (rmsg=GetARexxMsg(RexxContext))
  306.             {
  307.                 if (rmsg!=REXX_RETURN_ERROR)
  308.                 {
  309.                     /*
  310.                      * Any messages that come now are blown
  311.                      * away...
  312.                      */
  313.                     SetARexxLastError(RexxContext,rmsg,
  314.                                 "99: Port Closed!");
  315.                     ReplyARexxMsg(RexxContext,rmsg,
  316.                             NULL,100);
  317.                 }
  318.             }
  319.         }
  320.  
  321.         /*
  322.          * Clean up the port and delete it...
  323.          */
  324.         if (RexxContext->ARexxPort)
  325.         {
  326.             while (rmsg=GetARexxMsg(RexxContext))
  327.             {
  328.                 /*
  329.                  * Any messages that still are coming in are
  330.                  * "dead"  We just set the LASTERROR and
  331.                  * reply an error of 100...
  332.                  */
  333.                 SetARexxLastError(RexxContext,rmsg,
  334.                             "99: Port Closed!"