Subcommand Interface

An application can create handlers to process commands from a Rexx program. Once created, the subcommand handler name can be used with the RexxStart function or the Rexx ADDRESS instruction. Subcommand handlers must be registered with the RexxRegisterSubcomExe or RexxRegisterSubcomDll function before they are used.

Registering Subcommand Handlers

A subcommand handler can reside in the same module (executable or DLL) as an application, or it can reside in a separate dynamic-link library. It is recommended that an application that runs Rexx procedures with RexxStart uses RexxRegisterSubcomExe to register subcommand handlers. The Rexx interpreter passes commands to the application subcommand handler entry point. Subcommand handlers created with RexxRegisterSubcomExe are available only to Rexx programs called from the registering application.

The RexxRegisterSubcomDll interface creates subcommand handlers that reside in a dynamic-link library. Any Rexx program using the Rexx ADDRESS instruction can access a dynamic-link library subcommand handler. A dynamic-link library subcommand handler can also be registered directly from a Rexx program using the RXSUBCOM command.

Creating Subcommand Handlers

The following example is a sample subcommand handler definition.

RexxReturnCode REXXENTRY command_handler(
  PCONSTRXSTRING Command,     /* Command string from Rexx            */
  unsigned short *Flags,      /* Returned Error/Failure flags        */
  PRXSTRING Retstr);          /* Returned RC string                  */

where:

Command

is the command string created by Rexx.

command is a null-terminated RXSTRING containing the issued command.

Flags

is the subcommand completion status. The subcommand handler can indicate success, error, or failure status. The subcommand handler can set Flags to one of the following values:

RXSUBCOM_OK

The subcommand completed normally. No errors occurred during subcommand processing and the Rexx procedure continues when the subcommand handler returns.

RXSUBCOM_ERROR

A subcommand error occurred. RXSUBCOM_ERROR indicates a subcommand error occurred; for example, incorrect command options or syntax.

If the subcommand handler sets Flags to RXSUBCOM_ERROR, the Rexx interpreter raises an ERROR condition if SIGNAL ON ERROR or CALL ON ERROR traps have been created. If TRACE ERRORS has been issued, Rexx traces the command when the subcommand handler returns.

RXSUBCOM_FAILURE

A subcommand failure occurred. RXSUBCOM_FAILURE indicates that general subcommand processing errors have occurred. For example, unknown commands usually return RXSUBCOM_FAILURE.

If the subcommand handler sets Flags to RXSUBCOM_FAILURE, the Rexx interpreter raises a FAILURE condition if SIGNAL ON FAILURE or CALL ON FAILURE traps have been created. If TRACE FAILURES has been issued, Rexx traces the command when the subcommand handler returns.

Retstr

is the address of an RXSTRING for the return code. It is a character string return code that is assigned to the Rexx special variable RC when the subcommand handler returns to Rexx. The Rexx interpreter provides a default 256-byte RXSTRING in Retstr. A longer RXSTRING can be allocated with RexxAllocateMemory(size) if the return string is longer than the default RXSTRING. If the subcommand handler sets Retstr to an empty RXSTRING (a null strptr), Rexx assigns the string 0 to RC.

Example

RexxReturnCode REXXENTRY Edit_Commands(
  PCONSTRXSTRING Command,     /* Command string passed from the caller    */
  unsigned short *Flags,      /* pointer too short for return of flags    */
  PRXSTRING Retstr)           /* pointer to RXSTRING for RC return        */
{
  int         command_id;                /* command to process         */
  int         rc;                        /* return code                */
  const char *scan_pointer;              /* current command scan       */
  const char *target;                    /* general editor target      */

  scan_pointer = Command->strptr;      /* point to the command       */
                                       /* resolve command            */
  command_id = resolve_command(&scan_pointer);

  switch (command_id) {                /* process based on command   */

    case   LOCATE:                     /* locate command             */

                                       /* validate rest of command   */
      if (rc = get_target(&scan_pointer, &target)) {
        *Flags = RXSUBCOM_ERROR;       /* raise an error condition   */
        break;                         /* return to Rexx             */
      }
      rc = locate(target);             /* locate target in the file  */
      *Flags = RXSUBCOM_OK;            /* not found is not an error  */
      break;                           /* finish up                  */

...

      default:                         /* unknown command            */
        rc = 1;                        /* return code for unknown    */
        *Flags = RXSUBCOM_FAILURE;     /* this is a command failure  */
        break;
  }

  sprintf(Retstr->strptr, "%d", rc);   /* format return code string  */
                                       /* and set the correct length */
  Retstr->strlength = strlen(Retstr->strptr);
  return 0;                            /* processing completed       */
}

Subcommand Interface Functions

The following sections explain the functions for registering and using subcommand handlers.

RexxRegisterSubcomDll

RexxRegisterSubcomDll registers a subcommand handler that resides in a dynamic-link library routine.

retc = RexxRegisterSubcomDll(EnvName, ModuleName, EntryPoint,
                             UserArea, DropAuth);

Parameters

EnvName (const char *) - input

is the address of an ASCII subcommand handler name.

ModuleName (const char *) - input

is the address of an ASCII dynamic-link library name. ModuleName is the DLL file containing the subcommand handler routine.

EntryPoint (const char *) - input

is the address of an ASCII dynamic-link library procedure name. EntryPoint is the name of the exported routine within ModuleName that Rexx calls as a subcommand handler.

UserArea (const char *) - input

is the address of an area of user-defined information. The user-defined information is a buffer the size of two pointer values. The bytes UserArea buffer is saved with the subcommand handler registration. UserArea can be null if there is no user information to be saved. The RexxQuerySubcom function can retrieve the saved user information.

DropAuth (size_t) - input

is the drop authority. DropAuth identifies the processes that can deregister the subcommand handler. The possible DropAuth values are:

RXSUBCOM_DROPPABLE

Any process can deregister the subcommand handler with RexxDeregisterSubcom.

RXSUBCOM_NONDROP

Only a thread within the same process as the thread that registered the handler can deregister the handler with RexxDeregisterSubcom.

Return Codes

RXSUBCOM_OK0A subcommand has executed successfully.
RXSUBCOM_DUP10A duplicate handler name has been successfully registered. There is either an executable handler with the same name registered in another process, or a DLL handler with the same name registered in another DLL. (To address this subcommand, you must specify its library name.)
RXSUBCOM_NOTREG30Registration was unsuccessful due to duplicate handler and module names (RexxRegisterSubcomExe or RexxRegisterSubcomDll); the subroutine environment is not registered (other Rexx subcommand functions).
RXSUBCOM_NOEMEM1002There is insufficient memory available to complete this request.

RexxRegisterSubcomExe

RexxRegisterSubcomExe registers a subcommand handler that resides within the application code.

retc = RexxRegisterSubcomExe(EnvName, EntryPoint, UserArea);

Parameters

EnvName (const char *) - input

is the address of an ASCII subcommand handler name.

EntryPoint (REXXPFN) - input

is the address of the subcommand handler entry point within the application executable code.

UserArea (const char *) - input

is the address of an area of user-defined information. The user-defined information is a buffer the size of two pointer values. The bytes UserArea buffer is saved with the subcommand handler registration. UserArea can be null if there is no user information to be saved. The RexxQuerySubcom function can retrieve the saved user information.

Return Codes

RXSUBCOM_OK0A subcommand has executed successfully.
RXSUBCOM_DUP10A duplicate handler name has been successfully registered. There is either an executable handler with the same name registered in another process, or a DLL handler with the same name registered in another DLL. (To address this subcommand, you must specify its library name.)
RXSUBCOM_NOTREG30Registration was unsuccessful due to duplicate handler and library names (RexxRegisterSubcomExe or RexxRegisterSubcomDll); the subroutine environment is not registered (other Rexx subcommand functions).
RXSUBCOM_NOEMEM1002There is insufficient memory available to complete this request.

Remarks

If EnvName is the same as a subcommand handler already registered with RexxRegisterSubcomDll, RexxRegisterSubcomExe returns RXSUBCOM_DUP. This is not an error condition. It means that RexxRegisterSubcomExe has successfully registered the new subcommand handler.

A Rexx procedure can register dynamic-link library subcommand handlers with the RXSUBCOM command. For example:

                               /* register Dialog Manager       */
                               /* subcommand handler            */
"RXSUBCOM REGISTER ISPCIR ISPCIR ISPCIR"
Address ispcir                 /* send commands to dialog mgr   */

The RXSUBCOM command registers the Dialog Manager subcommand handler ISPCIR as routine ISPCIR in the ISPCIR dynamic-link library.

Example

WORKAREARECORD  *user_info[2];       /* saved user information     */

user_info[0] = global_workarea;      /* save global work area for  */
user_info[1] = NULL;                 /* re-entrance                */

rc = RexxRegisterSubcomExe("Editor", /* register editor handler    */
    &Edit_Commands,                  /* located at this address    */
    user_info);                      /* save global pointer        */

RexxDeregisterSubcom

RexxDeregisterSubcom deregisters a subcommand handler.

retc = RexxDeregisterSubcom(EnvName, ModuleName);

Parameters

EnvName (const char *) - input

is the address of an ASCII subcommand handler name.

ModuleName (const char *) - input

is the address of an ASCII dynamic-link library name. ModuleName is the name of the dynamic-link library containing the registered subcommand handler. When ModuleName is null, RexxDeregisterSubcom searches the RexxRegisterSubcomExe subcommand handler list for a handler within the current process. If RexxDeregisterSubcom does not find a RexxRegisterSubcomExe handler, it searches the RexxRegisterSubcomDll subcommand handler list.

Return Codes

RXSUBCOM_OK0A subcommand has executed successfully.
RXSUBCOM_NOTREG30Registration was unsuccessful due to duplicate handler and dynalink names (RexxRegisterSubcomExe or RexxRegisterSubcomDll); the subroutine environment is not registered (other Rexx subcommand functions).
RXSUBCOM_NOCANDROP40The subcommand handler has been registered as "not droppable."

Remarks

The handler is removed from the active subcommand handler list.

RexxQuerySubcom

RexxQuerySubcom queries a subcommand handler and retrieves saved user information.

retc = RexxQuerySubcom(EnvName, ModuleName, Flag, UserWord);

Parameters

EnvName (const char *) - input

is the address of an ASCII subcommand handler name.

ModuleName (const char *) - input

is the address of an ASCII dynamic-link library name. ModuleName restricts the query to a subcommand handler within the ModuleName dynamic-link library. When ModuleName is null, RexxQuerySubcom searches the RexxRegisterSubcomExe subcommand handler list for a handler within the current process. If RexxQuerySubcom does not find a RexxRegisterSubcomExe handler, it searches the RexxRegisterSubcomDll subcommand handler list.

Flag (unsigned short *) - output

is the subcommand handler registration flag. Flag is the EnvName subcommand handler registration status. When RexxQuerySubcom returns RXSUBCOM_OK, the EnvName subcommand handler is currently registered. When RexxQuerySubcom returns RXSUBCOM_NOTREG, the EnvName subcommand handler is not registered.

UserWord (char *) - output

is the address of an area that receives the user information saved with RexxRegisterSubcomExe or RexxRegisterSubcomDll. The userarea must be large enough to store two pointer values. UserWord can be null if the saved user information is not required.

Return Codes

RXSUBCOM_OK0A subcommand has executed successfully.
RXSUBCOM_NOTREG30Registration was unsuccessful due to duplicate handler and dynalink names (RexxRegisterSubcomExe or RexxRegisterSubcomDll); the subroutine environment is not registered (other Rexx subcommand functions).

Example

RexxReturnCode REXXENTRY Edit_Commands(
  PCONSTRXSTRING  Command,    /* Command string passed from the caller    */
  unsigned short *Flags,      /* pointer too short for return of flags    */
  PRXSTRING       Retstr)     /* pointer to RXSTRING for RC return        */
{
  WORKAREARECORD  *user_info[2];       /* saved user information     */
  WORKAREARECORD   global_workarea;    /* application data anchor    */
  unsigned short   query_flag;         /* flag for handler query     */


  rc = RexxQuerySubcom("Editor",       /* retrieve application work  */
      NULL,                            /* area anchor from Rexx      */
      &query_flag,
      user_info);

  global_workarea = user_info[0];      /* set the global anchor      */