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.
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.
The following example is a sample subcommand handler definition.
ULONG APIENTRY command_handler( PRXSTRING Command, /* Command string from Rexx */ PUSHORT Flags, /* Returned Error/Failure flags */ PRXSTRING Retstr); /* Returned RC string */
where:
is the command string created by Rexx.
command is a null-terminated RXSTRING containing the issued command.
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:
The subcommand completed normally. No errors occurred during subcommand processing and the Rexx procedure continues when the subcommand handler returns.
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.
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.
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 GlobalAlloc(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.
ULONG APIENTRY Edit_Commands( PRXSTRING Command, /* Command string passed from the caller */ PUSHORT Flags, /* pointer too short for return of flags */ PRXSTRING Retstr) /* pointer to RXSTRING for RC return */ { LONG command_id; /* command to process */ LONG rc; /* return code */ PSZ scan_pointer; /* current command scan */ PSZ 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 */ }
The following sections explain the functions for registering and using subcommand handlers.
RexxRegisterSubcomDll registers a subcommand handler that resides in a dynamic-link library routine.
retc = RexxRegisterSubcomDll(EnvName, ModuleName, EntryPoint, UserArea, DropAuth);
is the address of an ASCII subcommand handler name.
is the address of an ASCII dynamic-link library name. ModuleName is the DLL file containing the subcommand handler routine.
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.
is the address of an 8-byte area of user-defined information. The 8 bytes UserArea addresses are 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.
is the drop authority. DropAuth identifies the processes that can deregister the subcommand handler. The possible DropAuth values are:
Any process can deregister the subcommand handler with RexxDeregisterSubcom.
Only a thread within the same process as the thread that registered the handler can deregister the handler with RexxDeregisterSubcom.
RXSUBCOM_OK | 0 | A subcommand has executed successfully. |
RXSUBCOM_DUP | 10 | A 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_NOTREG | 30 | Registration was unsuccessful due to duplicate handler and dynalink names (RexxRegisterSubcomExe or RexxRegisterSubcomDll); the subroutine environment is not registered (other Rexx subcommand functions). |
RXSUBCOM_NOEMEM | 1002 | There is insufficient memory available to complete this request. |
EntryPoint can only be a 32-bit routine.
RexxRegisterSubcomExe registers a subcommand handler that resides within the application code.
retc = RexxRegisterSubcomExe(EnvName, EntryPoint, UserArea);
is the address of an ASCII subcommand handler name.
is the address of the subcommand handler entry point within the application executable code.
is the address of an 8-byte area of user-defined information. The 8 bytes UserArea addresses are 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 user information.
RXSUBCOM_OK | 0 | A subcommand has executed successfully. |
RXSUBCOM_DUP | 10 | A 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_NOTREG | 30 | Registration was unsuccessful due to duplicate handler and dynalink names (RexxRegisterSubcomExe or RexxRegisterSubcomDll); the subroutine environment is not registered (other Rexx subcommand functions). |
RXSUBCOM_NOEMEM | 1002 | There is insufficient memory available to complete this request. |
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.
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 deregisters a subcommand handler.
retc = RexxDeregisterSubcom(EnvName, ModuleName);
is the address of an ASCII subcommand handler name.
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.
RXSUBCOM_OK | 0 | A subcommand has executed successfully. |
RXSUBCOM_NOTREG | 30 | Registration was unsuccessful due to duplicate handler and dynalink names (RexxRegisterSubcomExe or RexxRegisterSubcomDll); the subroutine environment is not registered (other Rexx subcommand functions). |
RXSUBCOM_NOCANDROP | 40 | The subcommand handler has been registered as "not droppable." |
The handler is removed from the active subcommand handler list.
RexxQuerySubcom queries a subcommand handler and retrieves saved user information.
retc = RexxQuerySubcom(EnvName, ModuleName, Flag, UserWord);
is the address of an ASCII subcommand handler name.
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.
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.
is the address of an 8-byte area that receives the user information saved with RexxRegisterSubcomExe or RexxRegisterSubcomDll. UserWord can be null if the saved user information is not required.
ULONG APIENTRY Edit_Commands( PRXSTRING Command, /* Command string passed from the caller */ PUSHORT 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 */ USHORT 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 */