A Rexx program can be run directly from the command prompt of the operating system, or from within an application.
You can run a Rexx program directly from the operating system command prompt using Rexx followed by the program name. See Running a Rexx Program.
The Rexx interpreter is a dynamic-link library (DLL) routine (or Unix/Linux shared object). Any application can call the Rexx interpreter to run a Rexx program. The interpreter is fully reentrant and supports Rexx procedures running on several threads within the same process.
A C-language prototype for calling Rexx is in the Rexx.H include file.
RexxStart calls the Rexx interpreter to run a Rexx procedure.
retc = RexxStart(ArgCount, ArgList, ProgramName, Instore, EnvName, CallType, Exits, ReturnCode, Result);
is the number of elements in the ArgList array. This is the value that the ARG() built-in function in the Rexx program returns. ArgCount includes RXSTRINGs that represent omitted arguments. Omitted arguments are empty RXSTRINGs (strptr is null).
is an array of RXSTRING structures that are the Rexx program arguments.
is the address of the ASCII name of the Rexx procedure. If Instore is null, ProgramName must contain at least the file name of the Rexx procedure. You can also provide an extension, drive, and path. If you do not specify a file extension, the default is .CMD. A Rexx program can use any extension. If you do not provide the path and the drive, the Rexx interpreter uses the usual file search (current directory, then environment path).
If Instore is not null, ProgramName is the name used in the PARSE SOURCE instruction. If Instore requests a Rexx procedure from the macrospace, ProgramName is the macrospace function name (see Macrospace Interface).
is an array of two RXSTRING descriptors for in-storage Rexx procedures. If the strptr fields of both RXSTRINGs are null, the interpreter searches for Rexx procedure ProgramName in the Rexx macrospace (see Macrospace Interface). If the procedure is not in the macrospace, the call to RexxStart terminates with an error return code.
If either Instore strptr field is not null, Instore is used to run a Rexx procedure directly from storage.
is an RXSTRING describing a memory buffer that contains the Rexx procedure source. The source must be an exact image of a Rexx procedure disk file, complete with carriage returns, line feeds, and end-of-file characters.
is an RXSTRING containing the translated image of the Rexx procedure. If Instore[1] is empty, the Rexx interpreter returns the translated image in Instore[1] when the Rexx procedure finishes running. The translated image may be used in Instore[1] on subsequent RexxStart calls.
If Instore[1] is not empty, the interpreter runs the translated image directly. The program source provided in Instore[0] is used only if the Rexx procedure uses the SOURCELINE built-in function. Instore[0] can be empty if SOURCELINE is not used. If Instore[0] is empty and the procedure uses the SOURCELINE built-in function, SOURCELINE() returns no lines and any attempt to access the source returns Error 40.
If Instore[1] is not empty, but does not contain a valid Rexx translated image, unpredictable results can occur. The Rexx interpreter might be able to determine that the translated image is incorrect and translate the source again.
Instore[1] is both an input and an output parameter.
If the procedure is executed from disk, the Instore pointer must be null. If the first argument string in Arglist contains the string //T and the CallType is RXCOMMAND, the interpreter performs a syntax check on the procedure source, but does not execute it and does not store any images.
The program calling RexxStart must release Instore[1] using RexxFreeMemory(ptr) when the translated image is no longer needed.
Only the interpreter version that created the image can run the translated image. Therefore, neither change the format of the translated image of a Rexx program, nor move a translated image to other systems or save it for later use. You can, however, use the translated image several times during a single application execution.
is the address of the initial ADDRESS environment name. The ADDRESS environment is a subcommand handler registered using RexxRegisterSubcomExe or RexxRegisterSubcomDll. EnvName is used as the initial setting for the Rexx ADDRESS instruction.
If EnvName is null, the file extension is used as the initial ADDRESS environment. The environment name cannot be longer than 250 characters.
is the type of the Rexx procedure execution. Allowed execution types are:
The Rexx procedure is a system or application command. Rexx commands usually have a single argument string. The Rexx PARSE SOURCE instruction returns COMMAND as the second token.
The Rexx procedure is a subroutine of another program. The subroutine can have several arguments and does not need to return a result. The Rexx PARSE SOURCE instruction returns SUBROUTINE as the second token.
The Rexx procedure is a function called from another program. The subroutine can have several arguments and must return a result. The Rexx PARSE SOURCE instruction returns FUNCTION as the second token.
is an array of RXSYSEXIT structures defining exits for the Rexx interpreter to be used. The RXSYSEXIT structures have the following form:
typedef struct { PSZ sysexit_name; /* name of exit handler */ LONG sysexit_code; /* system exit function code */ } RXSYSEXIT;
The sysexit_name is the address of an ASCII exit handler name registered with RexxRegisterExitExe or RexxRegisterExitDll. Sysexit_code is a code identifying the handler exit type. See System Exit Interface for exit code definitions. An RXENDLST entry identifies the system-exit list end. Exits must be null if exits are not used.
is the integer form of the Result string. If the Result string is a whole number in the range -(2**15) to 2**15-1, it is converted to an integer and also returned in ReturnCode.
is the string returned from the Rexx procedure with the Rexx RETURN or EXIT instruction. A default RXSTRING can be provided for the returned result. If a default RXSTRING is not provided or the default is too small for the returned result, the Rexx interpreter allocates an RXSTRING using GlobalAlloc(size). The caller of RexxStart is responsible for releasing the RXSTRING storage with RexxFreeMemory(ptr).
The Rexx interpreter does not add a terminating null to Result.
The possible RexxStart return codes are:
Interpreter errors. See the Appendix in the Open Object Rexx: Reference for the list of Rexx errors.
No errors occurred. The Rexx procedure ran normally.
A system return code that indicates problems finding or loading the interpreter. See the return codes for the Windows functions LoadLibrary and GetProcAddress for details.
When a macrospace Rexx procedure (see Macrospace Interface) is not loaded in the macrospace, the return code is -3 ("Program is unreadable").
LONG return_code; /* interpreter return code */ RXSTRING argv[1]; /* program argument string */ RXSTRING retstr; /* program return value */ SHORT rc; /* converted return code */ CHAR return_buffer[250]; /* returned buffer */ /* build the argument string */ MAKERXSTRING(argv[0], macro_argument, strlen(macro_argument)); /* set up default return */ MAKERXSTRING(retstr, return_buffer, sizeof(return_buffer)); return_code = RexxStart(1, /* one argument */ argv, /* argument array */ "CHANGE.ED", /* Rexx procedure name */ NULL, /* use disk version */ "Editor", /* default address name */ RXCOMMAND, /* calling as a subcommand */ NULL, /* no exits used */ &rc, /* converted return code */ &retstr); /* returned result */ /* process return value */ ... RexxWaitForTermination(); /* need to return storage? */ if (RXSTRPTR(retval) != return_buffer) GlobalFree(RXSTRPTR(retval)); /* release the RXSTRING */
When RexxStart is executed within an external program (usually a C program), it runs synchronously with the main Rexx activity (thread) that it started. That is, when the main activity terminates, RexxStart returns, and the external program continues running.
To run RexxStart asynchronously, you can start several concurrent activities from the main activity using START or REPLY (see Concurrency). RexxStart is still synchronous to the main activity, that is, it returns when the main activity terminates, but it is asynchronous to the concurrent activities. If a concurrent activity runs longer than the main activity, RexxStart returns when the main activity ends, but the concurrent activity continues to run.
If, however, a concurrent activity is still running when the external program ends, the activity is terminated. To ensure that all activities finish executing, use RexxWaitForTermination or a looped RexxDidRexxTerminate in your external program after RexxStart. The use of RexxWaitForTermination is recommended also for programs that are not expected to use concurrency.
The following example demonstrates how to call MyCMD.CMD from a Cobol program (Rexx is running in the same process as the Cobol program).
PROCESS PGMNAME(MIXED) * You need to specify Rexx.LIB when you link this program, * for example on the COB2 command. * Note that the name RexxStart, used later, is case-sensitive, * and requires the PGMNAME(MIXED) compiler option. ************************************************************* IDENTIFICATION DIVISION. ************************************************************* PROGRAM-ID. 'CALLRexx' AUTHOR. IBM VISUALAGE FOR COBOL. ************************************************************* *NAME: CALLRexx *** * *** *FUNCTION: CALL A Rexx PROCEDURE NAME XXXXXXXX, *** * PASSING ARGUMENT AND GETTING RETURNED DATA. *** * *** *EXTERNAL SUBROUTINES: NONE *** *COPY MEMBERS: NONE *** * *** ************************************************************* ************************************************************* ENVIRONMENT DIVISION. ************************************************************* CONFIGURATION SECTION. ************************************************************* DATA DIVISION. ************************************************************* WORKING-STORAGE SECTION.
************************************************************* * INTERNAL VARIABLES * ************************************************************* 01 WS-WORK-FIELDS. 05 WS-RESULT-AREA PIC X(255) VALUE SPACES. 05 WS-ARGUMENT-AREA PIC X(255) VALUE SPACES. 05 WS-PARM1 PIC X(50) VALUE '55'. 05 WS-PARM2 PIC X(8) VALUE '66'. 01 WS-RexxSTART-PARAMETERS. 05 WS-Rexx-ARGUMENT-COUNT PIC S9(9) VALUE +1 COMP-5. 05 WS-Rexx-ARGUMENT-LIST. 10 WS-ARG-LENGTH PIC 9(9) COMP-5. 10 WS-ARG-POINTER POINTER. 05 WS-Rexx-PROGRAM-NAME PIC X(255) VALUE LOW-VALUES. 05 WS-Rexx-ENV-NAME PIC X(20) VALUE LOW-VALUES. 05 WS-Rexx-RETURN-CODE PIC S9(9) VALUE 0 COMP-5. 05 WS-Rexx-RESULT. 10 WS-RESULT-LENGTH PIC 9(9) COMP-5. 10 WS-RESULT-POINTER POINTER. 05 WS-Rexx-INTERPRETER-RC PIC S9(9) COMP-5. LINKAGE SECTION. PROCEDURE DIVISION. SET WS-ARG-POINTER TO ADDRESS OF WS-ARGUMENT-AREA. MOVE LENGTH OF WS-ARGUMENT-AREA TO WS-ARG-LENGTH. STRING WS-PARM1 DELIMITED BY SPACE ' ' DELIMITED BY SIZE WS-PARM2 DELIMITED BY SPACE INTO WS-ARGUMENT-AREA END-STRING. STRING 'MYCMD' DELIMITED BY SIZE X'00' DELIMITED BY SIZE INTO WS-Rexx-PROGRAM-NAME END-STRING. STRING 'CGISRV' DELIMITED BY SIZE X'00' DELIMITED BY SIZE INTO WS-Rexx-ENV-NAME END-STRING. SET WS-RESULT-POINTER TO ADDRESS OF WS-RESULT-AREA. MOVE LENGTH OF WS-RESULT-AREA TO WS-RESULT-LENGTH.
* Note that the name RexxStart is case sensitive CALL 'RexxStart' USING BY VALUE WS-Rexx-ARGUMENT-COUNT BY REFERENCE WS-Rexx-ARGUMENT-LIST BY REFERENCE WS-Rexx-PROGRAM-NAME BY VALUE 0 BY REFERENCE WS-Rexx-ENV-NAME BY VALUE 0 BY VALUE 0 BY REFERENCE WS-Rexx-RETURN-CODE BY REFERENCE WS-Rexx-RESULT RETURNING WS-Rexx-INTERPRETER-RC. DISPLAY WS-Rexx-RETURN-CODE ' ' WS-Rexx-INTERPRETER-RC. DISPLAY WS-RESULT-LENGTH. DISPLAY WS-RESULT-AREA. GOBACK.
RexxWaitForTermination waits for the termination of all activities of the program that were started by RexxStart. This function puts your program into a wait state. It cannot continue until the activities have finished.
RexxWaitForTermination();
RexxDidRexxTerminate checks for the termination of all activities of the program that were started by RexxStart, and allows your program to continue.
retc = RexxDidRexxTerminate();
Activities are still running.
All activities have been terminated.
while (!RexxDidRexxTerminate()) { /* do your processing */ }