Documentation for the ARexx Interface Library (Rxil) Release X0.8 Copyright © 1989 by Donald T. Meyer, Stormgate Software All Rights Reserved Chapters: Function Glossary Variable Glossary Defined Symbol Glossary Structure Descriptions Tutorial Notes In the following document, several terms and documantation conventions will be observed: When refering to ARexx message ports, "private" and "secret" refer to the same port. The code that uses this library may be refered to as the "client". -------------------------------------------------------------------------- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: :: Function Glossary :: :: :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: NAME RxilCheckPort SYNOPSIS RxilCheckPort(); FUNCTION Called by the client program's eventloop upon recieving a message at one of the ports. This handles the dispatching ( via RxilDispatch() ) of ARexx commands, the launching of "looped back" macros, and receiving the replys to macro invocation messages which we have sent to Rexxmaster. This is a "safe" call in that if the ARexx library was unopened or the port opening failed, nothing will go boom! INPUTS None RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilInit(), RxilDispatch() ---------------------------------------------------------------------- NAME RxilHandleReturn SYNOPSIS RxilHandleReturn( rxi ); struct RxilInvocation *rxi; FUNCTION Take appropriate action (i.e., notify user) for the return from an ARexx macro program. NOTE: This function is not yet in it's final form. The final form will probably use a requester, whereas the current implementation merely sends text to the CLI. INPUTS rxi = pointer to a RxilInvocations structure that has been replyed by the RexxMaster. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO ---------------------------------------------------------------------- NAME RxilDeletePort SYNOPSIS RxilDeletePort( port ); struct MsgPort *port; FUNCTION This will safely delete a message port used to recieve commands from ARexx. This is acomplished by setting a failure return code and replying the message if it is from ARexx. If the message is not from ARexx, it is merely replied. WARNING: If the port was/is used to recieve replys, there must be no chance of a reply being pending when this function is called! INPUTS port = pointer to a MsgPort. Normally one that was opened for receiving ARexx commands. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO ---------------------------------------------------------------------- NAME RxilInit SYNOPSIS rdef = RxilInit( flags, portname ); struct RxilDef *rdef; int flags; char *portname; FUNCTION Open the ARexx library and setup our message ports. Then allocate a RxilDef structure and do some default initialization of it. Even though this may fail, that should probably not be fatal since the ARexx functionality is optional. The RxilCheckPort() function is smart enough to just return if the rexx initialization was not successsfull. Not to mention that RxilCheckPort() should never get called since the rexx_sig_bit mask should be zero. INPUTS flags These are various defined constants which control which ports get opened. portname This is the name to use for the public ARexx port that commands will be received at. It is suggested that this be in uppercase and contain no spaces. RESULT A pointer to a RxilDef structure. Return is NULL for failure to initialize the ARexx ports. SIDES HISTORY 01-Aug-89 Creation. BUGS This should probably share one signal bit between both ports to avoid "hogging" signal bits. SEE ALSO RxilCleanup() ---------------------------------------------------------------------- NAME RxilCreateRxi SYNOPSIS rxi = RxilCreateRxi( name, type ); struct RxilInvocation *rxi; char *name; ULONG type; FUNCTION Allocate a RxilInvocation structure and initialize it to the defaults which are contained in the global RxilDef structure. INPUTS name = character string containing the name of the ARexx program that will be launched with the structure. type = determines wether this will be used to launch commands or functions. Must be set to either RXCOMM or RXFUNC. RESULT A pointer to a newly allocated and initialized RxilInvocation structure, or NULL if one could not be allocated. SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilDeleteRxi() ---------------------------------------------------------------------- NAME RxilDeleteRxi SYNOPSIS RxilDeleteRxi( rxi ); struct RxilInvocation *rxi; FUNCTION Remove the structure allocated by a call to RxilCreateRxi() from the linked list, and then frees it's memory. INPUTS rxi = a pointer to the RxilInvocation structure to delete. This must have been allocated by a call to RxilCreateRxi(). RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilCreateRxi() ---------------------------------------------------------------------- NAME RxilOpenConsole SYNOPSIS RxilOpenConsole( console, rexxmsg ); char *console; struct RexxMsg *rexxmsg; FUNCTION This will open an AmigaDOS stream as specified by the console string. The filehandle is then placed in the rm_Stdin and rm_Stdout fields of the RexxMsg. INPUTS console = a string which defines the console stream to be opened. This will normally be something like "CON:0/0/400/100/". rexxmsg = pointer to the RexxMsg that the AmigaDOS file handles are to be set into. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilCloseConsole() ---------------------------------------------------------------------- NAME RxilCloseConsole SYNOPSIS RxilCloseConsole( rexxmsg ) struct RexxMsg *rexxmsg; FUNCTION This will close the AmigaDOS file handles contained in the rm_Stdin and rm_Stdout fields of the RexxMsg. If the handles are the same, only one close is performed. This clears the fields. If the fields are NULL, then no action is taken. This function supports the rm_Stdin and rm_Stdout being seperate handles, even though it's complimentary function, RxilOpenConsole() does not do this. INPUTS rexxmsg = pointer to the RexxMsg whose IO streams are to be closed. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilOpenConsole() ---------------------------------------------------------------------- NAME RxilCmdLock SYNOPSIS RxilCmdLock( rexxmsg ); struct RexxMsg *rexxmsg; FUNCTION This is a "command" which would be called from the dispatch function. This would handle the "LOCK" command that an ARexx program could send to the application requesting access to the private port. INPUTS rexxmsg A pointer to a RexxMsg structure. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilCmdUnlock() ---------------------------------------------------------------------- NAME RxilCmdUnlock SYNOPSIS RxilCmdUnlock( rexxmsg ); struct RexxMsg *rexxmsg; FUNCTION This is a "command" which would be called from the dispatch function. This would handle the "UNLOCK" command that an ARexx program could send to the application requesting access to the private port. Note: The privlege level for this command should be "secret", since anyone who locked us will be able to meet that level, and those who have not locked us can't slip the lock out from under those who did (so to speak). INPUTS rexxmsg A pointer to a RexxMsg structure. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilCmdLock() ---------------------------------------------------------------------- NAME RxilLaunch SYNOPSIS result = RxilLaunch( rxi ) LONG result; struct RxilInvocation *rxi; FUNCTION Launch an ARexx program by sending an invocation message to the RexxMaster process. The RxilInvocation structure which is allocated prior to this call via RxilCreateRxi() contains the information neccessary to launch the program. INPUTS rxi A pointer to an initialized RxilInvocation structure. RESULT Zero if the launch was successful, non-zero otherwise. SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilCreateRxi(), RxilDeleteRxi() ---------------------------------------------------------------------- NAME RxilDispatch SYNOPSIS RxilDispatch( rexxmsg, cmd ); struct RexxMsg *rexxmsg; char *cmd; FUNCTION This is really an "internal" function which is used by the RxilCheckPort() function to dispatch commands. It is not static, since it may be usefull by itself, or it may desireable to replace it with a custom version in some applications. This can be done simply by overriding it, rather than editing the library itself. This is NOT a "safe" call, since it should never be called directly from client code. It is however safe if the client fails to initialize the command table pointer. INPUTS rexxmsg = pointer to the RexxMsg structure for the command we are dispatching. cmd = the command name string. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilCheckPort() ---------------------------------------------------------------------- NAME RxilToRexx SYNOPSIS result = RxilToRexx( cmd, arg0, arg1, arg2, arg3 ); LONG result ULONG cmd STRPTR arg0 STRPTR arg1 STRPTR arg2 STRPTR arg3 FUNCTION Send a command packet to the Rexx Master. This is an asynchronous send, no success or failure will be observed. INPUTS cmd = the command to send. arg0 = a null-terminated string to convert into an Argstring. arg1 = a null-terminated string to convert into an Argstring. arg2 = a null-terminated string to convert into an Argstring. arg3 = a null-terminated string to convert into an Argstring. RESULT Zero for success, non-zero to indicate failure. SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO ---------------------------------------------------------------------- NAME RxilDumpRdef SYNOPSIS RxilDumpRdef( rdef ); struct RxilDef *rdef; FUNCTION This function is for debug and testing purposes. It will dump information about the current ARexx environment to the CLI. INPUTS rdef = pointer to the global RxilDef structure. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO ---------------------------------------------------------------------- NAME RxilCleanup SYNOPSIS RxilCleanup( rdef ) struct RxilDef *rdef; FUNCTION Cleanup the entire ARexx port. This will set the Abort flag, then wait till all ARexx program invocations which we have made are completed. At this time, all ARexx message ports will be closed. Any remaining RxilInvocation structures which were allocated via RxilCreateRxi() and not yet deleted via RxilDeleteRxi() will be cleaned up and freed. The ARexx library will be closed. Finally, the RexxDef structure itself will be freed. INPUTS rdef = pointer to the RxilDef structure returned by a call to RxilInit(). RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilInit(), RxilPending() ---------------------------------------------------------------------- NAME RxilSetResult SYNOPSIS RxilSetResult( rexxmsg, string ); struct RexxMsg *rexxmsg; char *string; FUNCTION This can be called to handle the details of placing a result string into the rexx message packet as the result Argstring. If the string pointer is NULL, a general failure code will be set. This will deal with inability to allocate the Argstring by setting a failure code in the RexxMsg. INPUTS rexxmsg = pointer to the RexxMsg that the reply is being set into. string = pointer to a null terminated text string which will be converted to an Argstring and returned. RESULT SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO ---------------------------------------------------------------------- NAME RxilGetReturn SYNOPSIS rxi = RxilGetReturn(); struct RxilInvocation *rxi; FUNCTION This will return a pointer to any RxilInvocation message that has been replyed (but not yet cleaned up and available). NULL will be returned if all RxilInvocation structures which have been allocated are available or pending. INPUTS None RESULT A pointer to a RxilInvocation structure. If none have been replied and are available to be handled, this will return a NULL. SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO ---------------------------------------------------------------------- NAME RxilCleanupReturn SYNOPSIS RxilCleanupReturn( rxi ); struct RxilInvovcation *rxi; FUNCTION This will take a pointer to a RxilInvocation structure and free what needs to be freed. The RexxMsg pointer is then NULL'ed and the structure's state set to AVAILABLE. This should be called by the main program to cleanup after a function or command has returned and after the main program has done whatever it wanted to with the result. This will close the extension filehandles for Stdin and Stdout. INPUTS rxi = pointer to the RxilInvocation structure to be cleaned up. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilCreateRxi(), RxilDeleteRxi(), RxilGetReturn() ---------------------------------------------------------------------- NAME RxilPending SYNOPSIS flag = RxilPending(); FUNCTION If any ARexx functions or commands have been launched via a call to RxilLaunch(), and have not yet terminated, this will return TRUE. INPUTS None RESULT A boolean flag which indicates if any launches are in progress. SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilLaunch(), RxilCmdPending(), RxilFuncPending() ---------------------------------------------------------------------- NAME RxilCmdPending SYNOPSIS flag = RxilCmdPending(); FUNCTION If any ARexx commands have been launched via a call to RxilLaunch(), and have not yet terminated, this will return TRUE. INPUTS None RESULT A boolean flag which indicates if any launches are in progress. SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilLaunch(), RxilPending(), RxilFuncPending() ---------------------------------------------------------------------- NAME RxilFuncPending SYNOPSIS flag = RxilFuncPending(); FUNCTION If any ARexx functions have been launched via a call to RxilLaunch(), and have not yet terminated, this will return TRUE. INPUTS None RESULT A boolean flag which indicates if any launches are in progress. SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilLaunch(), RxilPending(), RxilCmdPending() ---------------------------------------------------------------------- NAME RxilCheckResult SYNOPSIS RxilCheckResult( rexxmsg ); struct RexxMsg *rexxmsg; FUNCTION Verify that the secondary result field in a RexxMsg is appropriatly set. This should be called for a RexxMsg just prior to replying it. This will deal with the case of a result string being set when the calling program did not request it. It will be freed, and an error code set to indicate to the calling program that it should be requesting a result for this command. INPUTS rexxmsg = pointer to the RexxMsg structure to be checked. RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO ---------------------------------------------------------------------- NAME RxilCancel SYNOPSIS RxilCancel(); FUNCTION Sets the abort condition for ARexx macros. This is accomplished by setting the Abort flag in the RxilDef structure. All ARexx messages received at the ARexx ports while this flag is set will be returned with an error code. Unless the RXIL_NO_CLEAR_ABORT flag is set, the Abort flag will be cleared automaticly when the last ARexx program launched by this application has finished. INPUTS None RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO ---------------------------------------------------------------------- NAME RxilCheckCancel SYNOPSIS flag = RxilCheckCancel(); BOOL flag; FUNCTION Checks to see if the button on the cancel macro requester has been clicked by the user or not. This will return FALSE if the cancel requester is not posted. INPUTS None RESULT A boolean TRUE if the cancel requester has been clicked. SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilPostCancel(), RxilEndCancel() ---------------------------------------------------------------------- NAME RxilPostCancel SYNOPSIS RxilPostCancel(); FUNCTION This will post a cancel requester to allow the user to halt macro execution by clicking a button on the requester. The CancelWindow member of the RxilDef structure controls where the requester is posted. In the current version, the cancel requester always opens it's own window on the same screen as the Window whose pointer is in CancelWindow. If CancelWindow is NULL, the window will open on the WorkBench. INPUTS None RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilCheckCancel(), RxilEndCancel() ---------------------------------------------------------------------- NAME RxilEndCancel SYNOPSIS RxilEndCancel(); FUNCTION Removes the cancel requester. INPUTS None RESULT None SIDES HISTORY 01-Aug-89 Creation. BUGS SEE ALSO RxilPostCancel(), RxilCheckCancel() -------------------------------------------------------------------------- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: :: Variable Glossary :: :: :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: RexxSysBase This is a pointer to the ARexx library opened by RxilInit() and closed by RxilCleanup(). This should never be altered by client code. Defined in the Rxil library modules. global_rdef The pointer to the global RxilDef structure. This must be set to the value returned from the call to RxilInit(). Once set by this call, this should not be altered. Immediatly after calling RxilCleanup(), this should be set to NULL. This must be defined in the client's program. Example: global_rdef = RxilInit( RXIL_PUBLIC, "MyPort" ); . . . RxilCleanup( global_rdef ); global_rdef = NULL; -------------------------------------------------------------------------- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: :: Defined Symbol Glossary :: :: :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: NOTE: THIS SECTION OBVIOUSLY UNFINSHED RXIL_PUBLIC RXIL_PRIVATE RXIL_SECRET RXIL_MAX_ARGS RXIL_NO_ARGCHECK RXIL_ARGV() RXIL_ARCG RXIL_STATE_AVAILABLE RXIL_STATE_PENDING RXIL_STATE_RETURNED RXIL_NOLAUNCH RXIL_NO_CLEARABORT RXIL_NOABORT RXIL_FROM_REXX RXIL_WAITFLAG -------------------------------------------------------------------------- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: :: Structure Descriptions :: :: :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: *************** RxilFunction Structure **************** Name The function name. This can be in upper or lower case. See the CaseFlag member of this structure for more information. Func Vector to the function's 'C' code. ArgCount Number of args expected. Set to NO_ARGCHECK if we don't care or will ascertain within the function itself. Note: This argument count, unlike the value returned by RXIL_ARGC, does not include the command name itself. I.E., if you want to receive one argunt, set this to 1. CaseFlag If set to boolean TRUE, the command name matching will be case sensitive. Privlege Set to either REXX_PUBLIC or REXX_SECRET to control which port(s) this command is valid from. If REXX_PUBLIC, than this command may be executed from either port. *************** RxilDef Structure **************** Flags These are flagbits which can be set to control various things about the Rexx Interface Library. RXIL_NOLAUNCH If set, unrecognized commands received at the ARexx port will be returned with an error code rather than "looped" back out to ARexx. RXIL_NO_CLEARABORT Normally, the library will clear the Abort flag whenever the last ARexx program launched by the library returns. This will disable that feature. RXIL_NOABORT If set, the "Cancel" requester will not appear when an ARexx macro is initiated from the library. PortName Name which will be used for the public Exec message port opened to recieve commands from ARexx. This is set when RxilInit() is called, and subsequent changes will have no effect. Default: none Console An AmigaDOS stream which will be set as the default I/O for commands and functions launched by the application. This will normally be a console stream, such as "CON:10/10/400/100/ARexxStream". This stream will not be used for ARexx programs that have been "looped" back out in response to a command. Default: "CON:10/10/400/100/" Extension This is the extension which will be used by ARexx to search for this programs macros. This should be an application-specific extension. Default: ".rexx" HostPort The Exec Message Port name that command and function invocation messages will be sent to. This is normally "REXX", but may also be "AREXX" if the 1.10 version of ARexx is in use. If "AREXX", commands and functions will "detach", and no return status or value will be available. Default: "REXX" CommandTable This is the pointer to an array of RxilFunction structures which is used for the dispatching of commands received at the application's ARexx port. Default: NULL Abort When set, this flag will cause commands recieved at the ARexx port to be returned with an error code. There are several flag bits which may be set in the Flags member of the RxilDef structure that affect this flag. SecretPortName The name of the "secret" or "private" port which may optionaly be opened by RxilInit(). This name is created by concatenating the word "PRIVATE" and a unique number onto the PortName. This is set when RxilInit() is called, and subsequent changes will have no effect. Default: none CancelWindow If NULL, the cancel requester will be opened upon the WorkBench screen. This may be set to a Window pointer, in which case the cancel requester will open on the screen containing the window. Note that the cancel requester always opens it own window, this member is merely a means of selecting the screen. SigBit Contains the Exec signal bit(s) used by the ARexx port(s). This should be read only via the macro RXIL_WAITFLAG. This should never be altered by client code. FromRexx This contains a value which indicates which port a command is from (public or private). This also indicates that a command is from an ARexx port (when non-zero). Some functions may need to know whether they have been called in response to an ARexx command, or through the "normal" user interface. Error handling and reporting will normally be handled differently in these cases. This should only be read via the macro RXIL_FROMREXX. This should never be altered by client code. Arg An array of pointers to the argument strings for an ARexx command. Like the 'C' argv[] array, the command name will be in the zereoth element, with the first actual argument being RXIL_ARGV(1). These should only be read via the macro RXIL_ARGV(). This should never be altered by client code. ArgCount The count of arguments from the ARexx commandline. Again, like the argc of 'C', this will be 1 if there were no arguments, 2 if there is one argument, etc. This should only be read via the macro RXIL_ARGC. This should never be altered by client code. LockCount If non-zero there is an ARexx program which has been given or acquired a "lock" on the private ARexx port. This should never be altered by client code. Structure members past this point are private, and used only by the Rxil internal functions. They should never be altered by client code, and client code should have little reason to ever read them. *************** RxilInvocation Structure **************** Next This member is private. RexxMsg This member is private. Parent This member is private. IHostPort The name of the Exec message port to send the "launch" mesage to. This will normally be "REXX". Default: global_rdef->HostPort State The current state of the RexxInvocation structure. This will indicate wether or not the structure is available for use (to launch an ARexx program), is waiting for an ARexx program to finish, or that the ARexx program has finished and a result is waiting to be cleaned up. Type This determines whether or not the ARexx program will be launched as a command or a function. This can be either RXCOMM or RXFUNC. Default: Whatever was passed as an argument to CreateRxi(). Name The command (ARexx program) name. This must be set by the client code prior to calling RxilLaunch(). Default: None FileExt This is the extension which will be used by ARexx to search for this program. This should be an application-specific extension. Default: global_rdef->Extension CommAddr This will be the default host ADDRESS for the ARexx program when launched. Default: The secret port name (if open), otherwise the public port name. Console An AmigaDOS stream which will be set as the default I/O for commands and functions launched by the application. This will normally be a console stream, such as "CON:10/10/400/100/ARexxStream". This stream will not be used for ARexx programs that have been "looped" back out in response to a command. Default: global_rdef->Console ActionFlags These are the rm_Action flag bits. Whatever is here will be anded with the rm_Action field of the ARexx program launch RexxMsg. CountArgs If TRUE, the data pointed to by the FuncArg array is not be considered NULL terminated ('C' string style). The argument length must in this case be stored in the ArgLen array. FuncArg Pointer to argument strings for an ARexx function mode invocation only. These are assumed to be NULL terminated 'C' style strings unless the CountArgs flag is TRUE. ArgLen If the CountArgs flag is TRUE, this array contains the lengths of the argument data pointed at by the corresponding members of the FuncArg array. -------------------------------------------------------------------------- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: :: Tutorial :: :: :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: NOTE: THIS SECTION OBVIOUSLY UNFINSHED This implements a toolkit interface package to facilitate doing two things: 1) Add a public and/or private ARexx port to an application program. 2) Allow launching of an ARexx macro from an application program. To do either of the above, three function calls will always be made to this package. RxilInit() RxilCheckPort() RxilCleanup() To set up to recieve commands, a structure containing command names and vectors (plus misc. flags) is defined. By then calling RxilCheckPort(), any valid commands received will then be dispatched to the application routine which handles them. Two types of ports may be opened. A public port, which can recieve commands from any macro, and a private port (though it IS on the list of public ports, the name will be unique each time the program is run) intended to recieve commands from macros launched by the application. To launch commands or functions, a call to RxilCreateRxi() will return a semi-initialized structure which can then, after some small amount of further initilization, be passed to RxilLaunch() which will handle the details of invoking the macro. All structures allocated by RxilCreateRxi() may be deleted individualy via RxilDeleteRxi() or will be released automaticly upon the call to RxilCleanup(). ------------------- Commands that we launch will use the secret port as their initial host address if it is open. If not, they will use the public port. Functions that we launch will default to having "REXX" as their initial host address. Note that in all of the above cases, that these are the values placed in the RexxInvocation structure when it is created. They most definitly may be changed to anything the caller desires prior to being used to launch a macro. ------------------- Logical Consistency Caveats: If no secret port is opened, then the "lock" and "unlock" commands are useless and should NOT be used! Also, if no secret port is opened, commands having a privlege of REXX_SECRET will never be executed! -------------------------------------------------------------------------- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: :: Notes :: :: :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Don't forget to clear the "rexx_abort" flag after things have aborted if you have set the RXIL_NO_CLEARABORT flag. --------------------------------------------------------------------------