home *** CD-ROM | disk | FTP | other *** search
- rexxapp.library doc file
-
- 1) What is rexxapp.library
- 2) Opening rexxapp.library
- 3) The RexxData structure
- 4) Initializing the RexxData structure
- 5) Setting up the Rexx interface
- 6) Receiving Rexx commands
- 7) Sending Rexx commands
- 8) Closing down the Rexx interface
-
-
- ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
- 1) What is the rexxapp.library
-
- The rexxapp.library is a shared library that can be opened (just like
- Intuition) and used by an application to implement an ARexx interface. ARexx
- is a script language that can control and facilitate communication between
- Rexx capable programs. By providing your application's own set of "Rexx
- commands" and attaching a routine to each command, this allows a user to
- write a script file to automatically control various aspects of your program.
- Also, the user can tie your program to another Rexx capable program, thus
- creating an integrated package of the 2 or more products.
- This library allows an application to both accept asynchronous REXX messages
- and request REXX service. This means that you can use the lib to accept control
- from some other application, or use the lib to control another application.
- The library handles all of the rexx port and message allocation. It handles
- setup as well as deciphering whether a Rexx communication resulted in an error
- or success. It keeps track (and frees) all Rexx-related allocated resources.
- In short, it completely manages almost all of the Rexx communication on your
- behalf via just a half-dozen, easy-to-use functions. The only thing that you
- have to do is provide the set of commands that you wish your program to "under-
- stand", write the functions to implement those commands, and provide an error
- message display routine.
-
-
- ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
- 2) Opening rexxapp.library
-
- The rexxapp.library should be copied to the LIBS: drawer of your boot disk.
- This lib uses the rexxsys.library which is part of the ARexx product available
- from Bill Hawes. This library must be available, and the Rexx interpreter must
- be started via RexxMast (also part of the ARexx package). You open the
- rexxapp.library via a call to Exec's OpenLibrary(). The current version is 0.0
-
-
- «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
- 3) The RexxData structure
-
- The library operates upon what I've defined as a RexxData structure. Certain
- fields of this must be initialized once before you setup your Rexx interface
- and start calling library functions. All library functions will be passed a
- pointer to (ie the address of) this data structure.
- Here is the structure definition in C. Note that this structure will have
- a different number of imbedded CmdEntry structures depending upon how many
- "commands" your program understands. For this reason, you will need to modify
- the varible NUMCMDS for your application.
-
- #define NUMCMDS 1
-
- struct RexxData {
- struct MsgPort RexxPort;
- CHAR *Exten;
- APTR Func;
- struct *RxsLib; /* defined in the ARexx rxslib.h file */
- APTR Error;
- APTR Result;
- ULONG RexxMask;
- ULONG UserData; /* to be defined by and used by the application */
- /* The command list goes here. It consists of one CmdEntry structure for
- each "command" that the application supports. Note that the number of
- commands (and therefore the size of the RexxData) will depend upon how
- many "commands" the application supports. This list must end with a
- NULL entry.
- */
- struct CmdEntry AsscList[NUMCMDS];
- };
-
- struct CmdEntry {
- char *CmdString;
- APTR CmdHandler; /* The return value depends upon what the app's Dispatch
- function wants to see returned. */
- };
-
- Here is the structure in assembly. Fields that will be initialized by the
- application have a bracketed comment indicating what value must be placed in
- that field. All other fields will be initialized by the lib.
-
- RexxData:
- ;---The imbedded port
- RexxPort:
- dc.l 0,0
- dc.b 4,0
- dc.l 0
- dc.b 0
- dc.b -1 ;This is negative (bit 7 set) whenever our port isn't set up
- dc.l 0
- dc.l RexxData+24
- dc.l 0
- dc.l RexxData+20
- dc.b 0 ;DO NOT ALTER THESE LAST 2 BYTES OF THE PORT
- dc.b 0
- ;---
- Exten dc.l [the address of the extension string]
- Func dc.l [the address of the dispatch function]
- RxsLib dc.l 0 ;the address of rexxsys.library (DO NOT ALTER)
- Error dc.l [the address of the Error function]
- Result dc.l [the address of the Result function]
- RexxMask dc.l 0 ;the mask of the rexxPort's SigBit (to be used by the app to Wait())
- UserData dc.l [for the application's use (UserData)]
- ;---The command association list
- [a series of pointers to a null-terminated "command" string followed by
- the address of its handler]
- dc.l [0] ;The association list must end with a 0 LONG
-
-
- «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
- 4) Initializing the RexxData structure
-
- You must initialize certain fields before calling the lib function,
- SetRexxPort(). SetRexxPort() will initialize and setup the other fields
- including the imbedded RexxPort. The fields that you must setup are as follows
-
- Exten:
- This is a pointer to (ie the address of) a null-terminated string describing
- the desired filename extension for Rexx macros invoked by the application.
- If not 0, any `primitive' not in the association command list will be sent
- out to ARexx for interpretation, thus allowing macro programs to work just
- like primitives. If you do not want this behavior, supply a 0 here, and those
- commands not specified in your association list will be sent back to ARexx
- with an error value of 30. It should be noted that extension should point to
- a nulled string if no particular extention is desired, but you want this
- feature enabled.
-
- Func
- This is a pointer to the application's Dispatch function. This function
- will be called by the library ONLY when the application calls ReceiveRexx().
- ReceiveRexx() handles all RexxMsgs received from other applications as well
- as processing returned RexxMsgs that your program sent out. This function is
- called when ReceiveRexx() gets some other program's RexxMsg which has a
- command that your program understands (ie is in your association list).
- This function is called with 3 arguments--- the Rexx message that was
- received, the appropriate command association CmdHandler (ie the handler to
- be called from your Dispatch function), and the Argstring (ARG0) stripped of
- the command. This function should return a 1 if the message is to be replied
- to by the lib or a 0 if not. If not, the application itself is responsible
- for replying the message later via Exec's ReplyMsg(). Otherwise, the library
- ALWAYS takes care of properly replying all messages. Unless you need to hold
- onto a Rexxmsg and consequently "put the Rexx script to sleep" until you
- reply it later, you'll let the lib take care of replies. Also, your Dispatch
- function should setup the return values with SetupResults() before exiting.
-
- BOOL Func(RexxMsg, CmdHandler, Argstring, RexxData);
- d0 a2 a3 a4 a5
-
- Error
- This routine is called by the lib when any RexxMsg that the application
- created and sent out is returned with an error. It is passed an appropriate
- error message, and the error code. Typically, this routine needs to do
- nothing more than print the message for the user. You must supply at least
- a dummy routine. Do not alter the passed, null-terminated string!
-
- void Error(Code, String, Rexxmsg, RexxData);
- d0 a0 a2 a5
-
- Result
- This routine is called by the lib when any RexxMsg that the application
- created and sent out is returned successfully. It is passed any returned
- Result string, and the Result1 code. This routine may do various things with
- the Result1 string or code depending upon which function initially sent the
- message out. Or, if your application has no use for returned strings, it
- could simply be a dummy function. You must supply at least a dummy routine.
- Do not alter the passed, null-terminated string!
-
- void Result(Code, String, Rexxmsg, RexxData);
- d0 a0 a2 a5
-
- You must also supply the command association list. This is simply a series of
- CmdEntry structures, one for each REXX command that the application defines.
- The CmdString must be null-terminated and all letters in LOWER CASE (use no
- imbedded spaces)! The CmdHandler must point to the routine to execute for this
- command. Note that when the lib checks received RexxMsgs, the msgs rm_Arg
- string need only be a prefix of one of your commands in order to match.
- (ie if one of your commands is "blort", then receiving "Blo" would match.)
- There must be a 0 LONG at the end of your command association list. In C,
- this can be done by having a NULL CmdEntry at the end. See the example.
-
-
- ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
- 5) Setting up the Rexx interface
-
- After obtaining a RexxData structure and initializing the above mentioned
- fields, call SetRexxPort(). Your Rexx interface is now setup. Note that
- SetRexxPort could fail, so check the return.
-
- ***************************** SetRexxPort() *****************************
- This is the routine that sets up the REXX (communication) port. It should
- be called once before using any other routines.
-
- SYNOPSIS
- waitMask = SetRexxPort(portName,RexxData)
- d0 a1 a5
-
- INPUT
- portName is the desired null-terminated name of your application RexxPort.
- This will be used with the ADDRESS command in Rexx scripts written to
- control your program. This should be in a buffer that is ONE BYTE LARGER
- THAN THE DECLARED NAME. When installing your Rexx port, the lib first
- checks to see if there is already some program using this port name. (There
- can't be two programs with the same port name.) If so, this function
- appends a "2" onto the port name and tries this name. (That explains the
- need for your portname buffer to have an extra byte.) So if your portname
- is "Blort" and you run 2 copies of your program simultaneously, the first
- copy's portname is "Blort", and the 2nd copy's is "Blort2". A third copy
- would have a portname of "Blort3". The library can only resolve up to 9
- multiple copies.
-
- RETURN
- SetRexxPort() returns the signal bit mask to wait on for Rexx messages. This
- can be OR'ed with other signals which your program waits for. This value is
- also stored in the RexxData's RexxMask field.
- If something goes wrong, it simply returns a 0 (z-flag set).
-
-
- ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
- 6) Receiving Rexx commands
-
- You should place a call to ReceiveRexx() within your IDCMP loop. If any
- Rexx messages have been received, this will cause your Func (dispatch) routine
- to be called if this message was sent by some other program (with a command
- that your application understands). If the msg is a reply of one that you
- sent out, the lib will determine whether there was an error, or if it executed
- successfully. If an error, your Error routine is called. If success, your
- Result routine is called.
-
- *************************** ReceiveRexx() ********************************
- Dispatches all REXX messages that the app might have received. It also frees
- up any returned RexxMsgs that the app itself sent out. This function is fast
- if no messages are outstanding, so it can be called fairly often from an
- IDCMP loop. This function may call the application's Result and Error vectors
- in the case of a returned message that was sent out by the application. In
- the case of a received Rexxmsg from someone else, it will call the applica-
- tion's Dispatch function after parsing for a match in the association
- list.
-
- SYNOPSIS
- ReceiveRexx(RexxData)
- a5
-
- RETURNS
- None
-
-
- Note that when some other application sends you a Rexx message, you do not
- need to reply the message (unless your dispatch Func returns 0). The lib does
- this for you. You will need to set the returned Result1 and Result2 fields.
- You do this using SetupResults(). This function allows you to pass returned
- Argstrings to the other application.
-
- ***************************** SetupResults() *****************************
- Use this function to pass back return codes or a return string when replying a
- received REXX msg.
-
- SYNOPSIS
- SetupResults(primary, secondary, string, RexxMsg, RexxData)
- d0 d1 a0 a1 a5
-
- INPUTS
- RexxMsg is the address of the REXX message you are replying.
-
- primary and secondary are the return codes to be stored in the msg's
- rm_Result1 and rm_Result2 fields respectively.
-
- string is a null-term return string. This string is only sent to ARexx if
- the primary return code is 0, and a string was requested (i.e. the Rexxmsg's
- rm_Action field has its RXFB_RESULT bit set). If you have no string to pass
- back, pass a 0.
-
- RETURNS
- None
-
-
- ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
- 7) Sending Rexx commands
-
- There are 3 functions to create and send Rexxmsgs. Two are higher level, and
- one is a lowel level routine. All 3 return a pointer to a RexxMsg created to
- send your command to Rexx, or 0 if an error. In the case of an error, a pointer
- to a null-terminated error message is returned as well. C programmers get this
- message from the global RexxErrMsg (in the RexxInterface.asm module), and asm
- programmers receive the address of the string in a0.
-
-
- *************************** SendRexxCmd() ****************************
- This is the general ARexx command creation interface, but is not the one that
- you will use most of the time; SyncRexxCmd and AsyncRexxCmd are easier to
- understand and use.
-
- SYNOPSIS
- RexxMsg = sendRexxCmd(rm_Action, InitFunc, string, retFunc, Rexxmsg, RexxData)
- d0 d0 d1 a0 a1 a2 a5
-
- INPUTS
- rm_Action is the desired ARexx Msg's command invocation field, such as RXCOMM
-
- string is the address of a null-terminated command string to send to Rexx.
- Upon return from this function, you may dispose of the string.
-
- retFunc is either NULL, indicating that the command should execute
- asynchronously, or the address of a function to be called when the
- message we build up and send out here finally returns. Please note
- that the function supplied here could be called during cleanup after
- a fatal error, so make sure that it is "safe". This function always is
- passed 3 args, the RexxMsg that is being replied (a0) and the rm_Result1
- and rm_Result2 fields in (d0/d1). Return FALSE to abort, or TRUE to continue.
-
- If retFunc is not 0, then you must also pass the address of the Rexxmsg
- which caused this new (asyncronous) command invocation.
-
- InitFunc is the address of an application routine that will be called with
- the new RexxMsg. This can be used to further initialize the RexxMsg
- (ie set up its rm_Args fields) before the msg is actually sent out. The lib
- reserves the last 2 ARGS fields (ARG[14] and ARG[15]), so you must not
- alter these. If InitFunc is 0, then just the default initialization is done.
- The lib always initializes all fields including the RexxMsg's rm_Action,
- ARG[0] command string, rm_Passport, rm_CommAddr, Stdin, Stdout, and node
- before calling your InitFunc. This function should return 0 if all went ok,
- or a pointer to some error message for abort. Note that you can use the
- RexxMsg's ARG[1] to ARG[13] fields for your own use, but you are responsible
- for freeing any argstrings that you stuff into these fields (do this in your
- Error/Result routines. (You could use these fields for storing things besides
- argstrings.)
-
- errormsg = InitFunc(RexxMsg, RexxData);
- d0 a2 a5
-
- RETURNS
- If all goes well, it sends the message to Arexx and returns the RexxMsg
- address. In the case of error, it returns 0 (z-flag set). A null-term error
- msg string is also returned. Note that you should check the return code to
- make sure that your message got out!
- If you have too many msgs currently out (>256), this fails.
- Also, if any of the following checks fail, it fails:
-
- - the application has a rexx port open (ie SetRexxPort succeeded)
- - Rexx is out there (ie the user started up the Arexx server)
- - the rexxsys library opened
- - the lib can create a Rexx message
- - the lib can create an argstring (for the command string)
-
-
- ***************************** SyncRexxCmd() ******************************
- This functions as a synchronous Rexx call. As soon as the action invoked here
- returns, we reply to RexxMsg, passing the return codes back. Returns the addr
- of the created RexxMsg if success or 0 if an error in sending out the RexxMsg
- (z-flag set). The pointer to a null-term error string is also returned in a0
- in the case of error. It sends the message with rm_Action = RXCOMM.
-
- SYNOPSIS
- RexxMsg = SyncRexxCmd(string, RexxMsg, RexxData)
- d0 a0 a2 a5
-
- RETURNS
- See SendRexxCmd()
-
-
- ***************************** ASyncRexxCmd() ******************************
- This function is used to send out an ARexx message and return immediately.
- Its single parameter is the null-term command string to send. Returns the addr
- of the created RexxMsg if success or 0 if an error in sending out the RexxMsg.
- (z-flag set). The pointer to a null-term error string is also returned in the
- case of error. It sends the message with rm_Action = RXCOMM.
-
- SYNOPSIS
- RexxMsg = ASyncRexxCmd(string, RexxData)
- d0 a0 a5
-
- RETURNS
- See SendRexxCmd()
-
-
- ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
- 8) Closing down the Rexx interface
-
- You should call FreeRexxPort(), and then close the rexxapp.library.
-
- ****************************** FreeRexxPort() ****************************
- This function closes down the Rexx port. It MUST be made a part of your
- cleanup routine after you have called SetRexxPort(). It removes the
- Rexxport, replies to any remaining messages and insures that we get replies to
- all the ones we sent out, closes the Rexx system lib, and frees any other
- resources. Note that if we haven't received all of our own Rexxmsgs back, this
- routine waits until we do.
-
- SYNOPSIS
- FreeRexxPort(RexxData);
- a5
-
- RETURNS
- None
-