Function RunRexx() Foundation
Executes a REXX script file.
RunRexx( <cScriptFileName> [, <cArguments,...>] ) --> xReturn
The function RunRexx() returns the return value of the REXX script file.
RunRexx() executes a script file and passes optional arguments to the REXX procedure in this file.
REXX is an interpreter language which automates program execution and allows for easy changes. Using REXX, procedures are programmed which can be called and executed using a REXX command processor. Open Object Rexx (ooRexx) is an open-source REXX interpreter which can be used for executing REXX scripts under Windows, see https://www.oorexx.org.
REXX procedures are typically stored in files with the extension .rex. These are script files comparable to .bat files in DOS. REXX script can be replaced, processed and changed with a simple text editor. They differ from .bat files in that they must always begin with a comment line (/* Comment */) so the characters "/*" must be the first two characters in the file. These characters are key identifiers for the REXX interpreter.
All commands and functions of REXX are usable within a REXX file. If such a file is started by RunRexx() from an Xbase++ application, the REXX procedure runs in the address space of the Xbase++ application. RunRexx() extends the language scope of REXX to all globally visible functions, procedures and dynamic variables of the calling Xbase++ application. This means that all Xbase++ functions and procedures can be called and executed within the REXX script. That includes all the functions of the Xbase++ runtime library and all globally visible user-defined functions and procedures. Also, all dynamic variables visible when the call RunRexx() occurs are visible. Access to lexically scoped variables and calls to functions or procedures declared as STATIC is not possible. The program operation of an Xbase++ application can be changed without compile and link cycles since REXX script files can simply be processed with a text editor.
Passing of arguments to REXX
The function RunRexx() can pass many arguments to the REXX procedure using <cArguments,...>. The passed arguments must always have the data type "character", since REXX is a character based interpreter language. To access the passed arguments within the REXX procedure, REXX provides the command ARG and the function ARG(). The command ARG is generally needed when a REXX procedure is started from the command line. The following REXX procedure demonstrates this and receives two arguments:
The procedure rexxarg1.rex can be started from the command line using the rexx command. It displays the passed arguments on the screen.
When called from the command line, the REXX procedure receives a single character string. The command ARG converts the character string to upper case letters and dissects it at blank spaces to correspond to the number of arguments declared with ARG. The same behavior is also produced with call of the procedure by RunRexx().
Since RunRexx() can pass any number of arguments to a REXX procedure, the use of the REXX function ARG() is important. This function reads the passed arguments individually without changing the case.
The procedure rexxarg2.rex displays all passed arguments on the screen. Additionally, it returns a character string as a return value for RunRexx(). From the view of an Xbase++ application rexxarg2.rex provides the following result (the screen output is indicated as comments):
Accessing Xbase++ variables and functions
When Xbase++ functions are called from a REXX procedure, the Xbase++ function call must always be enclosed in quotation marks. This also applies when accessing dynamic variables. Generally, Xbase++ specific syntax must be enclosed in quotation marks in a REXX procedure.
The contents of dynamic Xbase++ variables (see MEMVAR and FIELD declaration) are read in a REXX procedure by including the variable name. The variable name must be on a separate command line. The value of the variable is assigned at execution of the command line to the general REXX variable "RC" (RC stands for Return Code) and must be saved in a new REXX variable if it is needed for further processing. Generally, the variable RC contains the result of the Xbase++ specific operation, such as the return value of an Xbase++ function.
All Xbase++ specific instructions within the REXX procedure must be syntactically formulated so that they can also be compiled with the macro operator (the Xbase++ runtime compiler actually interprets the REXX command lines directed to Xbase++). The exceptions are command lines that appear on multiple lines. With REXX the character for a line continuation is the comma, not the semicolon as in Xbase++.
The execution of the REXX procedure rexxarg3.rex with RunRexx() leads to the following result:
Communication between Xbase++ and REXX
The fact that Xbase++ functions can be called from a REXX procedure permits "communication" between the Xbase++ application and the REXX procedure. If a REXX procedure calls an Xbase++ user-defined function, that function must be available when the REXX procedure is run. The user-defined function RexxCallsXbase() demonstrates how this is accomplished.
The procedure rexxarg4.rex creates a new PRIVATE variable dDate in the Xbase++ application and assigns the function value of Date() to it with the inline assignment operator. RexxCallsXbase() is then called and the name of the new variable dDate is passed to Xbase++ as a character string. The lifetime of this PRIVATE variable is the execution time of the REXX procedure rexxarg4.rex. The variable is therefore visible in the function RexxCallsXbase() and so access to dDate within Xbase++ is possible.
The function RexxCallsXbase() receives a variable name from the REXX procedure and the contents of the variable dDate created in the REXX procedure can be read in Xbase++ with the macro operator. Of course this procedure is only used for demonstration. The value of dDate could be passed directly to the function which is more efficient. In order to do this, the variable identifier must not be enclosed in single quotation marks:
Used in connection with RunRexx(), REXX offers an ideal opportunity for the creation of "data driven programs". The definition of data occurs within a REXX procedure. It generates data and transmits it to the Xbase++ application.
Select a subcommand handler
With the command ADDRESS, REXX allows instructions to be run in a specific command environment. The environment in which REXX instructions are actually processed is called the "Subcommand handler". Since an Xbase++ application always runs within a command shell, generally two subcommand handlers are available during the execution of REXX procedures. When a REXX procedure is executed by RunRexx(), subcommand handlers are addressed with REXX through symbolic names, which are "XBPP" and "CMD". The subcommand handler "CMD" is the command shell, and "XBPP" is the Xbase++ application.
With the REXX command ADDRESS CMD, instructions are sent to the command shell. In this way, operating system commands can be executed in the background without affecting the Xbase++ application.
Using the REXX procedure settime.rex the system time can be reset from an Xbase++ application. The operating system command "TIME" is directed by ADDRESS to the command shell. An example is in the following Xbase++ program:
Interprocess communication
Using REXX and RunRexx(), communication can take place between different processes (interprocess communication). The REXX command RXQUEUE and the REXX function RXQUEUE() are used to accomplish this. These functions manage queues through which data exchange between two Xbase++ applications is possible. An example program for this technique is in the discussion of the function RunShell().
If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.