When REXX encounters a line in your script which doesn't begin with a recognizable keyword, nor is a variable assignment (nor a comment), REXX doesn't consider this line to be a REXX instruction. But REXX doesn't consider this line to be an error either.

For example, consider the following line in a script:

echo 'hello'
There is no ECHO keyword in REXX, so REXX doesn't recognize echo as a REXX keyword (such as the keywords CALL, SAY, IF, PARSE, DO, etc). REXX also doesn't regard this as an assignment because there is no = after echo. And it's not a comment because it's not enclosed between /* and */. REXX simply does not know what to do with this line.

So what does REXX do with any line which is not considered to be a REXX instruction?

REXX treats that line as some expression which is first evaluated, and then passed back to the program that launched your script (such as Reginald's Script Launcher). REXX expects that the program will process this line and do something meaningful with it, and then return some value to your script. Your script pauses while the program does this.

In other words, since REXX can't figure out what to do with the line, REXX does whatever minimal processing it can figure out to do, and then passes the line to the program that launched your script, hoping that this program knows what to do with the line.

Let's take our above example. As noted, REXX does not recognize the line as a REXX instruction, so REXX decides to pass the line to the program that launched your script.

But first, REXX evaluates the line (ie, does any minimal processing). REXX sees that echo is not enclosed in quotes (ie, is not a literal string), so REXX assumes that echo is a variable name. REXX substitutes the value of the variable named echo, which if no such variable has been assigned a value, defaults to ECHO. Then, REXX sees the literal string 'hello'. It removes the enclosing quotes. (When evaluating literal strings, the outside quotes are always removed by REXX before it sends the literal string off to the program that launched your script. If you actually wanted a pair of quotes retained, you'd have to double-quote the string so that after REXX removed the outside pair, one pair would still remain).

So, the actual text that gets passed to the program is ECHO hello.

The program that launched your script is expected to process this line and do something with it. We refer to the code (inside of that program) which handles such lines as an environment. And we refer to the line that gets passed as a command string.

So REXX passes the command string ECHO hello to the program's environment.

If you wish to avoid having REXX first perform any evaluation of the line, you could put the entire command string enclosed in quotes, for example:

'echo hello'

In the above line, REXX doesn't regard echo as a variable when evaluating the line. echo is part of the literal string (and remember that REXX never evaluates what is between the quotes of a literal string). REXX simply removes the outside quotes and passes the whole line, as is, to the environment.

Alternately, you could use a variable's value to specify part of the command string. Below, we want REXX to recognize argument as a variable name and substitute its value (ie, 'hello'):

argument = 'hello'
'echo' argument

After the program's environment is passed the command string and does something with it, the environment returns control back to REXX. (ie, Your REXX script resumes at the next instruction). The environment may also return some value that REXX automatically assigns to the variable named 'RC' (or the 'RC' variable will be DROP'ed if the environment returns no value). Furthermore, if there is a problem, the environment may (or may not) raise the FAILURE or ERROR condition.

You'll have to consult the documentation with the program you're using to launch your script, to see what command strings you can pass to it, and what return values (if any) you should expect, and whether it raises FAILURE or ERROR condition if it has a problem.

For example, here we pass our command string of echo hello to the environment, and then check to see if the environment returned some value. If so, we display that value:

'echo hello'
IF SYMBOL('RC') == 'VAR' THEN SAY RC

Multiple environments (ADDRESS keyword)

It is possible that the program could have several different environments to which you can pass a command string. Each different environment may have its own command strings that it recognizes and processes.

Every environment has a unique name. (No two environments can have the same name). This name is chosen by the program itself, and can be anything. You'll have to consult the documentation with the program to see how many environments it has, and what their names are.

The program will initially set one of its environments as the "current environment". This is the environment to which REXX will pass lines that are not recognized as REXX instructions.

But you can use the ADDRESS keyword to select which environment you wish to make the current one. You place the name of the desired environment after the ADDRESS keyword. For example, assume that the program has an environment named Environment 1 to which you would like to send a command string of echo hello. First you use an ADDRESS instruction to select this environment as the current one, and then you type the line which REXX will pass as a command string, as so:

ADDRESS 'Environment 1'
'echo hello'
You can specify more lines to be sent to this environment. You do not need to use another ADDRESS instruction if you desire the same environment. For example, here we send two lines (ie, command strings) to Environment 1:
ADDRESS 'Environment 1'
'echo hello'
'this is line two'
Environment 1 will be sent the two commands strings of echo hello and this is line two, one at a time. You could also check for any return value from each command string, as so:
ADDRESS 'Environment 1'
'echo hello'
IF SYMBOL('RC') == 'VAR' THEN SAY RC
'this is line two'
IF SYMBOL('RC') == 'VAR' THEN SAY RC
One thing you should note is that each time you send a command string to an environment, the RC variable gets changed. So, remember to save its value to another variable if you need to retain that value across another command string.

You can use the ADDRESS keyword as many times as you'd like in your script, to switch between different environments. For example, assume that the program has another environment named Environment 2 to which you would also like to send a command string of my command.

/* Send a command string to Environment 1 */
ADDRESS 'Environment 1'
'echo hello'
IF SYMBOL('RC') == 'VAR' THEN SAY RC

/* Now send a command string to Environment 2 */
ADDRESS 'Environment 2'
'my command'
IF SYMBOL('RC') == 'VAR' THEN SAY RC
If you would like to pass a command string to a second environment, without needing to set it as the current environment, you can do this with one line. You use the ADDRESS keyword, and the name of the desired environment after it -- just like you were setting the current environment. But you also include the command string after the environment name -- all on the same line.
/* Send a command string to Environment 1 */
ADDRESS 'Environment 1'
'echo hello'
IF SYMBOL('RC') == 'VAR' THEN SAY RC

/* Now send a command string to Environment 2,
 * but without first setting it as the
 * "current environment".
 */
ADDRESS 'Environment 2' 'my command'
IF SYMBOL('RC') == 'VAR' THEN SAY RC

/* The next command string gets sent to
 * Environment 1, because we never did
 * change the "current environment".
 */
'echo hello again'
IF SYMBOL('RC') == 'VAR' THEN SAY RC
You can even flip back and forth between two environments by using the ADDRESS keyword alone.
/* Set Environment 1 as current */
ADDRESS 'Environment 1'

/* Now set Environment 2 as current */
ADDRESS 'Environment 2'

/* Flip back to Environment 1 as current */
ADDRESS

/* Flip back to Environment 2 as current */
ADDRESS
You can use the ADDRESS() built-in function to retrieve the name of whichever environment is the current one.

Note: Although the examples above use quotes around the environment name, you do not need to use quotes. REXX will not regard an unquoted environment name as a variable name in the case of an ADDRESS instruction. So for example, consider the following:

/* Set Environment 1 as current */
MyEnv = 'Environment 1'
ADDRESS MyEnv
This does not result in the environment being set to 'Environment 1', but rather, sets the environment to one named MYENV. (Remember that REXX uppercases anything that is not enclosed in quotes).

But, note that an environment name is case-insensitive. So an environment name of 'cmd' is not the same as 'CMD', for example. If you don't quote your environment name, then it will be regarded as all uppercase. If you do quote your environment name, make sure that you specify case exactly as you intend it to be.


CMD environment

If the program that launches your script has no environments at all, then REXX uses a default environment named 'CMD'. Any unrecognized lines in your script get sent to this environment, which is the operating system's shell. This environment is discussed in the next section of this book.

Note: Reginald's Script Launcher does not have its own environment. Therefore, any unrecognized lines in your script get passed to the 'CMD' environment, and are processed by the operating system.