home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / rexxlib_393.lzh / RexxLib / RexxLib.doc < prev    next >
Text File  |  1990-10-28  |  19KB  |  401 lines

  1. rexxapp.library doc file
  2.  
  3. 1) What is rexxapp.library
  4. 2) Opening rexxapp.library
  5. 3) The RexxData structure
  6. 4) Initializing the RexxData structure
  7. 5) Setting up the Rexx interface
  8. 6) Receiving Rexx commands
  9. 7) Sending Rexx commands
  10. 8) Closing down the Rexx interface
  11.  
  12.  
  13. ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  14. 1) What is the rexxapp.library
  15.  
  16.   The rexxapp.library is a shared library that can be opened (just like
  17. Intuition) and used by an application to implement an ARexx interface. ARexx
  18. is a script language that can control and facilitate communication between
  19. Rexx capable programs. By providing your application's own set of "Rexx
  20. commands" and attaching a routine to each command, this allows a user to
  21. write a script file to automatically control various aspects of your program.
  22. Also, the user can tie your program to another Rexx capable program, thus
  23. creating an integrated package of the 2 or more products.
  24.   This library allows an application to both accept asynchronous REXX messages
  25. and request REXX service. This means that you can use the lib to accept control
  26. from some other application, or use the lib to control another application.
  27.   The library handles all of the rexx port and message allocation. It handles
  28. setup as well as deciphering whether a Rexx communication resulted in an error
  29. or success. It keeps track (and frees) all Rexx-related allocated resources.
  30. In short, it completely manages almost all of the Rexx communication on your
  31. behalf via just a half-dozen, easy-to-use functions. The only thing that you
  32. have to do is provide the set of commands that you wish your program to "under-
  33. stand", write the functions to implement those commands, and provide an error
  34. message display routine.
  35.  
  36.  
  37. ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  38. 2) Opening rexxapp.library
  39.  
  40.    The rexxapp.library should be copied to the LIBS: drawer of your boot disk.
  41. This lib uses the rexxsys.library which is part of the ARexx product available
  42. from Bill Hawes. This library must be available, and the Rexx interpreter must
  43. be started via RexxMast (also part of the ARexx package). You open the
  44. rexxapp.library via a call to Exec's OpenLibrary(). The current version is 0.0
  45.  
  46.  
  47. «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  48. 3) The RexxData structure
  49.  
  50.    The library operates upon what I've defined as a RexxData structure. Certain
  51. fields of this must be initialized once before you setup your Rexx interface
  52. and start calling library functions. All library functions will be passed a
  53. pointer to (ie the address of) this data structure.
  54.    Here is the structure definition in C. Note that this structure will have
  55. a different number of imbedded CmdEntry structures depending upon how many
  56. "commands" your program understands. For this reason, you will need to modify
  57. the varible NUMCMDS for your application.
  58.  
  59. #define NUMCMDS 1
  60.  
  61. struct RexxData {
  62.    struct MsgPort RexxPort;
  63.    CHAR *Exten;
  64.    APTR Func;
  65.    struct *RxsLib; /* defined in the ARexx rxslib.h file */
  66.    APTR Error;
  67.    APTR Result;
  68.    ULONG RexxMask;
  69.    ULONG UserData; /* to be defined by and used by the application */
  70.    /* The command list goes here. It consists of one CmdEntry structure for
  71.       each "command" that the application supports. Note that the number of
  72.       commands (and therefore the size of the RexxData) will depend upon how
  73.       many "commands" the application supports. This list must end with a
  74.       NULL entry.
  75.    */
  76.    struct CmdEntry AsscList[NUMCMDS];
  77. };
  78.  
  79. struct CmdEntry {
  80.    char *CmdString;
  81.    APTR CmdHandler; /* The return value depends upon what the app's Dispatch
  82.                          function wants to see returned. */
  83. };
  84.  
  85.    Here is the structure in assembly. Fields that will be initialized by the
  86. application have a bracketed comment indicating what value must be placed in
  87. that field. All other fields will be initialized by the lib.
  88.  
  89. RexxData:
  90.       ;---The imbedded port
  91. RexxPort:
  92.       dc.l 0,0
  93.       dc.b 4,0
  94.       dc.l 0
  95.       dc.b 0
  96.       dc.b -1    ;This is negative (bit 7 set) whenever our port isn't set up
  97.       dc.l 0
  98.       dc.l RexxData+24
  99.       dc.l 0
  100.       dc.l RexxData+20
  101.       dc.b 0    ;DO NOT ALTER THESE LAST 2 BYTES OF THE PORT
  102.       dc.b 0
  103.       ;---
  104. Exten    dc.l [the address of the extension string]
  105. Func     dc.l [the address of the dispatch function]
  106. RxsLib   dc.l 0  ;the address of rexxsys.library (DO NOT ALTER)
  107. Error    dc.l [the address of the Error function]
  108. Result   dc.l [the address of the Result function]
  109. RexxMask dc.l 0  ;the mask of the rexxPort's SigBit (to be used by the app to Wait())
  110. UserData dc.l [for the application's use (UserData)]
  111.      ;---The command association list
  112.         [a series of pointers to a null-terminated "command" string followed by
  113.         the address of its handler]
  114.          dc.l [0]   ;The association list must end with a 0 LONG
  115.  
  116.  
  117. «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  118. 4) Initializing the RexxData structure
  119.  
  120.   You must initialize certain fields before calling the lib function,
  121. SetRexxPort(). SetRexxPort() will initialize and setup the other fields
  122. including the imbedded RexxPort. The fields that you must setup are as follows
  123.  
  124. Exten:
  125.   This is a pointer to (ie the address of) a null-terminated string describing
  126.   the desired filename extension for Rexx macros invoked by the application.
  127.   If not 0, any `primitive' not in the association command list will be sent
  128.   out to ARexx for interpretation, thus allowing macro programs to work just
  129.   like primitives. If you do not want this behavior, supply a 0 here, and those
  130.   commands not specified in your association list will be sent back to ARexx
  131.   with an error value of 30. It should be noted that extension should point to
  132.   a nulled string if no particular extention is desired, but you want this
  133.   feature enabled.
  134.  
  135. Func
  136.   This is a pointer to the application's Dispatch function. This function
  137.   will be called by the library ONLY when the application calls ReceiveRexx().
  138.   ReceiveRexx() handles all RexxMsgs received from other applications as well
  139.   as processing returned RexxMsgs that your program sent out. This function is
  140.   called when ReceiveRexx() gets some other program's RexxMsg which has a
  141.   command that your program understands (ie is in your association list).
  142.   This function is called with 3 arguments--- the Rexx message that was
  143.   received, the appropriate command association CmdHandler (ie the handler to
  144.   be called from your Dispatch function), and the Argstring (ARG0) stripped of
  145.   the command.  This function should return a 1 if the message is to be replied
  146.   to by the lib or a 0 if not. If not, the application itself is responsible
  147.   for replying the message later via Exec's ReplyMsg(). Otherwise, the library
  148.   ALWAYS takes care of properly replying all messages. Unless you need to hold
  149.   onto a Rexxmsg and consequently "put the Rexx script to sleep" until you
  150.   reply it later, you'll let the lib take care of replies. Also, your Dispatch
  151.   function should setup the return values with SetupResults() before exiting.
  152.  
  153.   BOOL Func(RexxMsg, CmdHandler, Argstring, RexxData);
  154.    d0          a2        a3        a4          a5
  155.  
  156. Error
  157.   This routine is called by the lib when any RexxMsg that the application
  158.   created and sent out is returned with an error. It is passed an appropriate
  159.   error message, and the error code. Typically, this routine needs to do
  160.   nothing more than print the message for the user. You must supply at least 
  161.   a dummy routine. Do not alter the passed, null-terminated string!
  162.  
  163.   void Error(Code, String, Rexxmsg, RexxData);
  164.               d0     a0      a2        a5
  165.  
  166. Result
  167.   This routine is called by the lib when any RexxMsg that the application
  168.   created and sent out is returned successfully. It is passed any returned
  169.   Result string, and the Result1 code. This routine may do various things with
  170.   the Result1 string or code depending upon which function initially sent the
  171.   message out. Or, if your application has no use for returned strings, it
  172.   could simply be a dummy function. You must supply at least a dummy routine.
  173.   Do not alter the passed, null-terminated string!
  174.  
  175.   void Result(Code, String, Rexxmsg, RexxData);
  176.               d0     a0      a2         a5
  177.  
  178. You must also supply the command association list. This is simply a series of
  179. CmdEntry structures, one for each REXX command that the application defines.
  180. The CmdString must be null-terminated and all letters in LOWER CASE (use no
  181. imbedded spaces)! The CmdHandler must point to the routine to execute for this
  182. command. Note that when the lib checks received RexxMsgs, the msgs rm_Arg
  183. string need only be a prefix of one of your commands in order to match.
  184. (ie if one of your commands is "blort", then receiving "Blo" would match.)
  185.   There must be a 0 LONG at the end of your command association list. In C,
  186. this can be done by having a NULL CmdEntry at the end. See the example.
  187.  
  188.  
  189. ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  190. 5) Setting up the Rexx interface
  191.  
  192.   After obtaining a RexxData structure and initializing the above mentioned
  193. fields, call SetRexxPort(). Your Rexx interface is now setup. Note that
  194. SetRexxPort could fail, so check the return.
  195.  
  196.  ***************************** SetRexxPort() *****************************
  197.  This is the routine that sets up the REXX (communication) port. It should
  198.  be called once before using any other routines.
  199.  
  200.  SYNOPSIS
  201.    waitMask = SetRexxPort(portName,RexxData)
  202.       d0                    a1        a5
  203.  
  204.  INPUT
  205.    portName is the desired null-terminated name of your application RexxPort.
  206.    This will be used with the ADDRESS command in Rexx scripts written to
  207.    control your program. This should be in a buffer that is ONE BYTE LARGER
  208.    THAN THE DECLARED NAME.  When installing your Rexx port, the lib first
  209.    checks to see if there is already some program using this port name.  (There
  210.    can't be two programs with the same port name.)  If so, this function
  211.    appends a "2" onto the port name and tries this name.  (That explains the
  212.    need for your portname buffer to have an extra byte.)  So if your portname
  213.    is "Blort" and you run 2 copies of your program simultaneously, the first
  214.    copy's portname is "Blort", and the 2nd copy's is "Blort2".  A third copy
  215.    would have a portname of "Blort3".  The library can only resolve up to 9
  216.    multiple copies.
  217.  
  218.  RETURN
  219.    SetRexxPort() returns the signal bit mask to wait on for Rexx messages. This
  220.    can be OR'ed with other signals which your program waits for. This value is
  221.    also stored in the RexxData's RexxMask field.
  222.    If something goes wrong, it simply returns a 0 (z-flag set).
  223.  
  224.  
  225. ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  226. 6) Receiving Rexx commands
  227.  
  228.   You should place a call to ReceiveRexx() within your IDCMP loop. If any
  229. Rexx messages have been received, this will cause your Func (dispatch) routine
  230. to be called if this message was sent by some other program (with a command
  231. that your application understands). If the msg is a reply of one that you
  232. sent out, the lib will determine whether there was an error, or if it executed
  233. successfully. If an error, your Error routine is called. If success, your
  234. Result routine is called.
  235.  
  236.  *************************** ReceiveRexx() ********************************
  237.  Dispatches all REXX messages that the app might have received. It also frees
  238.  up any returned RexxMsgs that the app itself sent out. This function is fast
  239.  if no messages are outstanding, so it can be called fairly often from an
  240.  IDCMP loop. This function may call the application's Result and Error vectors
  241.  in the case of a returned message that was sent out by the application. In
  242.  the case of a received Rexxmsg from someone else, it will call the applica-
  243.  tion's Dispatch function after parsing for a match in the association
  244.  list.
  245.  
  246.  SYNOPSIS
  247.    ReceiveRexx(RexxData)
  248.                   a5
  249.  
  250.  RETURNS
  251.    None
  252.  
  253.  
  254.   Note that when some other application sends you a Rexx message, you do not
  255. need to reply the message (unless your dispatch Func returns 0). The lib does
  256. this for you. You will need to set the returned Result1 and Result2 fields.
  257. You do this using SetupResults(). This function allows you to pass returned
  258. Argstrings to the other application.
  259.  
  260.  ***************************** SetupResults() *****************************
  261.  Use this function to pass back return codes or a return string when replying a
  262.  received REXX msg.
  263.  
  264.  SYNOPSIS
  265.    SetupResults(primary, secondary, string, RexxMsg, RexxData)
  266.                   d0         d1       a0      a1       a5
  267.  
  268.  INPUTS
  269.    RexxMsg is the address of the REXX message you are replying.
  270.  
  271.    primary and secondary are the return codes to be stored in the msg's
  272.    rm_Result1 and rm_Result2 fields respectively.
  273.  
  274.    string is a null-term return string. This string is only sent to ARexx if
  275.    the primary return code is 0, and a string was requested (i.e. the Rexxmsg's
  276.    rm_Action field has its RXFB_RESULT bit set). If you have no string to pass
  277.    back, pass a 0.
  278.  
  279.  RETURNS
  280.    None
  281.  
  282.  
  283. ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  284. 7) Sending Rexx commands
  285.  
  286.   There are 3 functions to create and send Rexxmsgs. Two are higher level, and
  287. one is a lowel level routine. All 3 return a pointer to a RexxMsg created to
  288. send your command to Rexx, or 0 if an error. In the case of an error, a pointer
  289. to a null-terminated error message is returned as well. C programmers get this
  290. message from the global RexxErrMsg (in the RexxInterface.asm module), and asm
  291. programmers receive the address of the string in a0.
  292.  
  293.  
  294.  *************************** SendRexxCmd() ****************************
  295.  This is the general ARexx command creation interface, but is not the one that
  296.  you will use most of the time; SyncRexxCmd and AsyncRexxCmd are easier to
  297.  understand and use.
  298.  
  299.  SYNOPSIS
  300.  RexxMsg = sendRexxCmd(rm_Action, InitFunc, string, retFunc, Rexxmsg, RexxData)
  301.    d0                      d0        d1       a0      a1       a2        a5
  302.  
  303.  INPUTS
  304.   rm_Action is the desired ARexx Msg's command invocation field, such as RXCOMM
  305.  
  306.   string is the address of a null-terminated command string to send to Rexx.
  307.   Upon return from this function, you may dispose of the string.
  308.  
  309.   retFunc is either NULL, indicating that the command should execute
  310.   asynchronously, or the address of a function to be called when the
  311.   message we build up and send out here finally returns.  Please note
  312.   that the function supplied here could be called during cleanup after
  313.   a fatal error, so make sure that it is "safe".  This function always is
  314.   passed 3 args, the RexxMsg that is being replied (a0) and the rm_Result1
  315.   and rm_Result2 fields in (d0/d1). Return FALSE to abort, or TRUE to continue.
  316.  
  317.   If retFunc is not 0, then you must also pass the address of the Rexxmsg
  318.   which caused this new (asyncronous) command invocation.
  319.  
  320.   InitFunc is the address of an application routine that will be called with
  321.   the new RexxMsg. This can be used to further initialize the RexxMsg
  322.   (ie set up its rm_Args fields) before the msg is actually sent out. The lib
  323.   reserves the last 2 ARGS fields (ARG[14] and ARG[15]), so you must not
  324.   alter these. If InitFunc is 0, then just the default initialization is done.
  325.   The lib always initializes all fields including the RexxMsg's rm_Action,
  326.   ARG[0] command string, rm_Passport, rm_CommAddr, Stdin, Stdout, and node
  327.   before calling your InitFunc. This function should return 0 if all went ok,
  328.   or a pointer to some error message for abort. Note that you can use the
  329.   RexxMsg's ARG[1] to ARG[13] fields for your own use, but you are responsible
  330.   for freeing any argstrings that you stuff into these fields (do this in your
  331.   Error/Result routines. (You could use these fields for storing things besides
  332.   argstrings.)
  333.  
  334.   errormsg = InitFunc(RexxMsg, RexxData);
  335.      d0                 a2        a5
  336.  
  337.  RETURNS
  338.   If all goes well, it sends the message to Arexx and returns the RexxMsg
  339.   address. In the case of error, it returns 0 (z-flag set). A null-term error
  340.   msg string is also returned. Note that you should check the return code to
  341.   make sure that your message got out!
  342.   If you have too many msgs currently out (>256), this fails.
  343.   Also, if any of the following checks fail, it fails:
  344.  
  345.    - the application has a rexx port open (ie SetRexxPort succeeded)
  346.    - Rexx is out there (ie the user started up the Arexx server)
  347.    - the rexxsys library opened
  348.    - the lib can create a Rexx message
  349.    - the lib can create an argstring (for the command string)
  350.  
  351.  
  352.  ***************************** SyncRexxCmd() ******************************
  353.  This functions as a synchronous Rexx call. As soon as the action invoked here
  354.  returns, we reply to RexxMsg, passing the return codes back. Returns the addr
  355.  of the created RexxMsg if success or 0 if an error in sending out the RexxMsg
  356.  (z-flag set). The pointer to a null-term error string is also returned in a0
  357.  in the case of error. It sends the message with rm_Action = RXCOMM.
  358.  
  359.  SYNOPSIS
  360.    RexxMsg = SyncRexxCmd(string, RexxMsg, RexxData)
  361.      d0                    a0       a2       a5
  362.  
  363.  RETURNS
  364.    See SendRexxCmd()
  365.  
  366.  
  367.  ***************************** ASyncRexxCmd() ******************************
  368.  This function is used to send out an ARexx message and return immediately.
  369.  Its single parameter is the null-term command string to send. Returns the addr
  370.  of the created RexxMsg if success or 0 if an error in sending out the RexxMsg.
  371.  (z-flag set). The pointer to a null-term error string is also returned in the
  372.  case of error. It sends the message with rm_Action = RXCOMM.
  373.  
  374.  SYNOPSIS
  375.    RexxMsg = ASyncRexxCmd(string, RexxData)
  376.      d0                     a0       a5
  377.  
  378.  RETURNS
  379.    See SendRexxCmd()
  380.  
  381.  
  382. ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  383. 8) Closing down the Rexx interface
  384.  
  385.   You should call FreeRexxPort(), and then close the rexxapp.library.
  386.  
  387.  ****************************** FreeRexxPort() ****************************
  388.  This function closes down the Rexx port. It MUST be made a part of your
  389.  cleanup routine after you have called SetRexxPort(). It removes the
  390.  Rexxport, replies to any remaining messages and insures that we get replies to
  391.  all the ones we sent out, closes the Rexx system lib, and frees any other
  392.  resources. Note that if we haven't received all of our own Rexxmsgs back, this
  393.  routine waits until we do.
  394.  
  395.  SYNOPSIS
  396.    FreeRexxPort(RexxData);
  397.                  a5
  398.  
  399.  RETURNS
  400.    None
  401.