Before using this information and the product it supports, be sure to read the general information under “Notices” on page
443.
Second edition (September 2000)
This edition applies to Release 1 of CICS Transaction Server for VSE/ESA, program number 5648-054, and to all
subsequent versions, releases, and modifications until otherwise indicated in new editions. Make sure you are using
the correct edition for the level of the product.
Format the RFS Filepools .............................433
Create the Help Files..............................433
Verify the Installation ...............................434
Configure the REXX DB2 Interface.........................435
Bibliography .................................437
CICS Transaction Server for VSE/ESA Release 1 library.................437
Where to Find More Information..........................438
Books from VSE/ESA 2.5 base program libraries ....................438
VSE/ESA Version 2 Release 5 ..........................438
High-Level Assembler Language (HLASM) ......................439
Language Environment for VSE/ESA (LE/VSE) ....................439
VSE/ICCF..................................439
VSE/POWER ................................439
VSE/VSAM .................................439
VTAM for VSE/ESA ..............................439
Books from VSE/ESA 2.5 optional program libraries ...................440
C for VSE/ESA (C/VSE)............................440
COBOL for VSE/ESA (COBOL/VSE) ........................440
DB2 Server for VSE ..............................440
DL/I VSE ..................................441
PL/I for VSE/ESA (PL/I VSE)
...........................441
Contentsxvii
Screen Definition Facility II (SDF II) ........................441
Notices...................................443
Trademarks ..................................445
Index ....................................447
Sending your comments to IBM ..........................455
xviiiCICS TS for VSE/ESA: REXX Guide
Preface
What this book is about
This book describes REXX/CICS or REXX for CICS Transaction Server for VSE/ESA. This IBM program
product provides a native REXX-based application development, customization, prototyping, and
procedures language environment for REXX/CICS, along with associated runtime facilities.
Who this book is for
This book is for users who need to refer to CICS Transaction Server for VSE/ESA REXX instructions and
functions, and for those who need to learn more details about REXX language items such as parsing. It is
also intended for anyone who wants to learn how to write REXX programs. The type of users include:
application programmers, system programmers, end users, administrators, developers, testers, and
support personnel.
What you need to know to understand this book
Within this book, reference may be made to Release 1. The function described in this book has
been added since the release of CICS Transaction Server for VSE/ESA Release 1 and can be
identified within the code as 1.1.1.
If you are not an experienced programmer, and are new to REXX, you should read the guide part of this
book, see page 1.
The book contains two parts: a user's guide and a reference. The user's guide section will help you
become familiar with REXX for CICS Transaction Server for VSE/ESA. The reference section contains the
CICS Transaction Server for VSE/ESA REXX instructions, functions, and commands. The instructions,
functions, and commands are listed alphabetically in their own sections. Also included are details about
general concepts you need to know in order to program in REXX.
The programming language described by this book is called the REstructured eXtended eXecutor
language (commonly referred to as REXX). This book also describes how the CICS Transaction Server for
VSE/ESA REXX language processor (shortened, hereafter, to the language processor) processes or
interprets the REstructured eXtended eXecutor language.
Prerequisites
REXX/CICS runs under CICS Transaction Server for VSE/ESA Version 1 or above. There are no other
prerequisites (other than the prerequisites that CICS TS for VSE/ESA requires).
This chapter describes the REXX programming language and some of its features.
What is REXX?
REXX is an extremely versatile programming language. Common programming structure, readability, and
free format make it a good language for beginners and general users. REXX is also suitable for more
experienced computer professionals because it can be intermixed with commands to host environments, it
provides powerful functions, and it has extensive mathematical capabilities.
REXX programs can do many tasks under CICS. These include issuing EXEC CICS commands, SQL
statements, as well as commands to the CEDA (Resource Definition Online Transaction) and CEMT
(Master Terminal Transaction) utilities.
Features of REXX
In addition to its versatility, REXX has many other features, some of which are:
Ease of use
The REXX language is easy to read and write because many instructions are meaningful English words.
Unlike some lower level programming languages that use abbreviations, REXX instructions are common
words, such as SAY, PULL, IF...THEN...ELSE..., DO...END, and EXIT.
Free format
There are few rules about REXX format. You need not start an instruction in a particular column. You can
skip spaces in a line or skip entire lines. You can have an instruction span of many lines, or have multiple
instructions on one line. You need not predefine variables. You can type instructions in upper, lower, or
mixed case. The few rules about REXX format are covered in section “Syntax of REXX Instructions” on
page 6.
Convenient built-in functions
REXX supplies built-in functions that perform various processing, searching, and comparison operations
for both text and numbers. Other built-in functions provide formatting capabilities and arithmetic
calculations.
Debugging capabilities
When a REXX program running in REXX/CICS encounters an error, REXX writes messages describing the
error. You can also use the REXX TRACE instruction and the interactive debug facility to locate errors in
programs.
Interpreted language
The REXX/CICS product includes the REXX/CICS interpreter. When a REXX program runs, the interpreter
directly processes each line. Languages that are not interpreted must be compiled into machine language
and possibly link-edited before they are run.
Extensive parsing capabilities
REXX includes extensive parsing capabilities for character manipulation. This parsing capability lets you
set up a pattern to separate characters, numbers, and mixed input.
The various components of REXX make it a powerful tool for programmers. REXX is made up of:
v Clauses, which can be instructions, null clauses, or labels. Instructions can be:
– Keyword instructions
– Assignments
– Commands (REXX/CICS and CICS commands and SQL).
The language processor processes keyword instructions and assignments.
v Built-in functions — These functions are built into the language processor and provide convenient
processing options.
v External functions — REXX/CICS provides these functions that interact with the system to do specific
tasks for REXX.
v Data stack functions — A data stack can store data for I/O and other types of processing.
4
CICS TS for VSE/ESA: REXX Guide
Chapter 2. Writing and Running a REXX Program
This chapter introduces programs and their syntax, describes the steps involved in writing and running
programs, and explains concepts you need to understand to avoid common problems.
What you need to run a REXX Program?
Before you can run a REXX Program, you must configure the REXX support. Go through the following
steps:
1. Create the RFS Filepools
2. Install Resource Definitions
3. Update LSRPOOL Definitions
4. Rename supplied Procedures
5. Update CICSTART.PROC
6. Update CICS Initialization JCL
7. Format the RFS Filepools
8. Create the Help Files
9. Verify the Installation
10. Configure the REXX DB2 Interface
For details on configuration, see Appendix K, “Post-Installation Configuration,” on page 431.
What is a REXX Program?
A REXX program consists of REXX language instructions that the REXX interpreter interprets directly. A
program can also contain commands that the host environment executes, such as CICS commands (see
page 81).
One advantage of the REXX language is its similarity to ordinary English. This similarity makes it easy to
read and write a REXX program. For example, to write a line of output, you use the REXX instruction SAY
followed by the text you want written.
/* Sample REXX Program*/
SAY 'Hello world!'
Figure 1. Example of a Simple Program
This program starts with a comment line to identify it as a REXX program. A comment begins with /* and
ends with */. More about comments and why you might need a REXX program identifier appears later on
page 10.
When you run the program, the SAY instruction sends to the terminal output device:
Hello world!
Even in a longer program, the instructions are similar to ordinary English and are easy to understand. For
example, you could use the following to call the program ADDTWO, which adds two numbers: From a
CICS terminal you would clear the screen and enter:
REXX addtwo
For this example, the first number you will enter is 42, and the second number is 21. Here is the ADDTWO
program:
/**************************** REXX *********************************/
/* This program adds two numbers and produces their sum.*/
/*******************************************************************/
say 'Enter first number.'
PULL number1/* Assigns: number1=42 */
say 'Enter second number.'
PULL number2/* Assigns: number2=21 */
sum = number1 + number2
SAY 'The sum of the two numbers is' sum'.'
Figure 2. Example of a Longer Program
When you run the example program, the first PULL instruction assigns the variable number1 the value 42.
The second PULL instruction assigns the variable number2 the value 21. The next line contains an
assignment. The language processor adds the values in number1 and number2 and assigns the result, 63,
to sum. Finally, the SAY instruction displays the output line:
The sum of the two numbers is 63.
Before you try any examples, please read the next two sections, “Syntax of REXX Instructions” and
“Typing in a Program” on page 11.
Syntax of REXX Instructions
Some programming languages have rigid rules about how and where you enter characters on each line.
For example, assembler statements must begin in a certain column. REXX, on the other hand, has simple
syntax rules. You can use upper or lower or mixed case. REXX has no restrictions about the columns in
which you can type.
An instruction can begin in any column on any line. The following are all valid instructions.
SAY 'You can type in any column'
SAY 'You can type in any column'
SAY 'You can type in any column'
These instructions are sent to the terminal output device:
You can type in any column
You can type in any column
You can type in any column
The Format of REXX Instructions
The REXX language has free format. This means you can insert extra spaces between words. For
example, the following all mean the same:
total=num1+num2
total =num1+num2
total = num1+num2
total = num1 + num2
You can also insert blank lines throughout a program without causing an error.
The Letter Case of REXX Instructions
You can enter a REXX instruction in lowercase, uppercase, or mixed case. For example, SAY, Say, and say
all have the same meaning. The language processor translates alphabetic characters to uppercase, unless
you enclose them in single or double quotation marks.
Using Quotation Marks in an Instruction
A series of characters within matching quotation marks is a literal string. The following examples contain
literal strings.
6
CICS TS for VSE/ESA: REXX Guide
Writing and Running a REXX Program
SAY 'This is a REXX literal string.' /* Using single quotation marks */
SAY "This is a REXX literal string." /* Using double quotation marks */
Do not enclose a literal string with one each of the two different types of quotation marks. For example,
the following is incorrect:
SAY 'This is a REXX literal string." /* Using mismatched quotation marks */
If you omit the quotation marks around a literal string in a SAY instruction, the language processor usually
translates the statement to uppercase. For example,
SAY This is a REXX string.
results in:
THIS IS A REXX STRING.
(This assumes none of the words is the name of a variable that you have already assigned a value. In
REXX, the default value of a variable is its own name in uppercase.)
If a string contains an apostrophe, you can enclose the literal string in double quotation marks.
SAY "This isn't difficult!"
You can also use two single quotation marks in place of the apostrophe, because a pair of single quotation
marks is processed as one.
SAY 'This isn''t difficult!'
Either way, the outcome is the same.
This isn't difficult!
Ending an instruction
A line usually contains one instruction except when it contains a semicolon (;) or ends with a comma (,).
The end of the line or a semicolon indicates the end of an instruction. If you put one instruction on a line,
the end of the line delineates the end of the instruction. If you put multiple instructions on one line, you
must separate adjacent instructions with a semicolon.
SAY 'Hi!'; say 'Hi again!'; say 'Hi for the last time!'
This example would result in three lines.
Hi!
Hi again!
Hi for the last time!
Continuing an instruction
A comma is the continuation character. It indicates that the instruction continues to the next line. The
comma, when used in this manner, also adds a space when the lines are concatenated. Here is how the
comma continuation character works when a literal string is being continued on the next line.
SAY 'This is an extended',
'REXX literal string.'
The comma at the end of the first line adds a space (between extended and REXX when the two lines are
concatenated for output. A single line results:
This is an extended REXX literal string.
The following two instructions are identical and yield the same result:
SAY 'This is',
'a string.'
Chapter 2. Writing and Running a REXX Program7
Writing and Running a REXX Program
SAY 'This is' 'a string.'
The space between the two separate strings is preserved:
This is a string.
Continuing a literal string without adding a space
If you need to continue an instruction to a second or more lines, but do not want REXX to add spaces in
the line, use the concatenation operand (two single OR bars, ||).
SAY 'This is an extended literal string that is bro'||,
'ken in an awkward place.'
This example results in one line no space in the word “broken”.
This is an extended literal string that is broken in an awkward place.
Also note that the following two instructions are identical and yield the same result:
SAY 'This is' ||,
'a string.'
SAY 'This is' || 'a string.'
These examples result in:
This isa string.
In both examples, the concatenation operator deletes spaces between the two strings.
The following example demonstrates the free format of REXX.
/************************* REXX *****************************/
SAY 'This is a REXX literal string.'
SAY'This is a REXX literal string.'
SAY 'This is a REXX literal string.'
SAY,
'This',
'is',
'a',
'REXX',
'literal',
'string.'
SAY'This is a REXX literal string.';SAY'This is a REXX literal string.'
SAY 'This is a REXX literal string.'
Figure 3. Example of Free Format
Running this example results in six lines of identical output, followed by one indented line.
This is a REXX literal string.
This is a REXX literal string.
This is a REXX literal string.
This is a REXX literal string.
This is a REXX literal string.
This is a REXX literal string.
This is a REXX literal string.
Thus, you can begin an instruction anywhere on a line, you can insert blank lines, and you can insert extra
spaces between words in an instruction. The language processor ignores blank lines, and it ignores
spaces that are greater than one. This flexibility of format lets you insert blank lines and spaces to make a
program easier to read.
Blanks and spaces are only significant during parsing, see section “Parsing Data” on page 73.
8
CICS TS for VSE/ESA: REXX Guide
Writing and Running a REXX Program
Types of REXX Clauses
REXX clauses can be: instructions, null clauses, and labels. Instructions can be keyword instructions,
assignments, or commands. The following example shows a program with these types of clauses. A
description of each type of clause follows the example.
/* QUOTA REXX program. Two car dealerships are competing to */
/* sell the most cars in 30 days. Who will win?*/
store_a=0; store_b=0
DO 30
CALL sub
END
IF store_a>store_b THEN SAY "Store_a wins!"
ELSE IF store_b>store_a THEN SAY "Store_b wins!"
ELSE SAY "It's a tie!"
EXIT
sub:
store_a=store_a+RANDOM(0,20) /* RANDOM returns a random number in */
store_b=store_b+RANDOM(0,20) /* in specified range, here 0 to 20 */
RETURN
Keyword Instructions
A keyword instruction tells the language processor to do something. It begins with a REXX keyword that
identifies what the language processor is to do. For example, DO can group instructions and execute them
repetitively, and IF tests whether a condition is met. SAY writes to the current terminal output device.
IF, THEN and ELSE are three keywords that work together in one instruction. Each keyword forms a
clause, which is a subset of an instruction. If the expression that follows the IF keyword is true, the
instruction that follows the THEN keyword is processed. Otherwise, the instruction that follows the ELSE
keyword is processed. (Note that a semicolon is needed before the ELSE if you are putting an ELSE
clause on the same line with a THEN.) If you want to put more than one instruction after a THEN or ELSE,
use a DO before the group of instructions and an END after them. More information about the IF
instruction appears in section “Using Conditional Instructions” on page 33.
The EXIT keyword tells the language processor to end the program. Using EXIT in the preceding example
is necessary because, otherwise, the language processor would execute the code in the subroutine after
the label sub:. EXIT is not necessary in some programs (such as those without subroutines), but it is good
programming practice to include it. More about EXIT appears in section “EXIT Instruction” on page 48.
Assignment
An assignment gives a value to a variable or changes the current value of a variable. A simple assignment
instruction is:
number = 4
In the preceding program, a simple assignment instruction is: store_a=0. The left side of the assignment
(before the equal sign) contains the name of the variable to receive a value from the right side (after the
equal sign). The right side can be an actual value (such as 4) or an expression. An expression is
something that needs to be evaluated, such as an arithmetic expression. The expression can contain
numbers, variables, or both.
number=4+4
number = number + 4
In the first example, the value of number is 8. If the second example directly followed the first in a program,
the value of number would become 12. More about expressions is in section “Using Expressions” on page
21.
Chapter 2. Writing and Running a REXX Program9
Writing and Running a REXX Program
Label
A label, such as sub: is a symbolic name followed by a colon. A label can contain either single- or
double-byte characters or a combination of single- and double-byte characters. (Double-byte characters
are valid only if OPTIONS ETMODE is the first instruction in your program.) A label identifies a portion of
the program and is commonly used in subroutines and functions, and with the SIGNAL instruction. (Note
that you need to include a RETURN instruction at the end of a subroutine to transfer control back to the
main program.) More about the use of labels appears in Chapter 6, “Writing Subroutines and Functions,”
on page 57 and section “SIGNAL Instruction” on page 50.
Null Clause
A null clause consists of only blanks or comments or both. The language processor ignores null clauses,
but they make a program easier to read.
Comments
A comment begins with /* and ends with */. Comments can be on one or more lines or on part of a
line. You can put information in a comment that might not be obvious to a person reading the
REXX instructions. Comments at the beginning of a program can describe the overall purpose of
the program and perhaps list special considerations. A comment next to an individual instruction
can clarify its purpose.
Note: REXX/CICS does not require that a REXX program begin with a comment. However, for
portability reasons, you may want to start each REXX program with a comment that
includes the word REXX.
Not every language processor requires this program identifier. However, to run the same exec on
MVS TSO and CICS, you should include the /* REXX */ program identifier to satisfy TSO
requirements.
Blank lines
Blank lines separate groups of instructions and aid readability. The more readable a program is,
the easier it is to understand and maintain.
Commands
A command is a clause consisting of only an expression. Commands are sent to a previously defined
environment for processing. (You should enclose in quotation marks any part of the expression not to be
evaluated.) The example program did not include any commands. The following example includes a
command in an ADDRESS instruction:
/* REXX program including a command */
ADDRESS REXXCICS 'DIR'
ADDRESS is a keyword instruction. When you specify an environment and a command on an ADDRESS
instruction, a single command is sent to the environment you specify. In this case, the environment is
REXXCICS. The command is the expression that follows the environment:
'DIR'
The DIR command lists the files in your current file system directory. For more details about changing the
host command environment, see section “Changing the Host Command Environment” on page 83.
More information about issuing commands appears in Chapter 8, “Using Commands from a program,” on
page 81.
Programs Using Double-Byte Character Set Names
You can use double-byte character set (DBCS) names in your REXX programs for literal strings, symbols,
and comments. Such character strings can be single-byte, double-byte, or a combination of both. To use
DBCS names, OPTIONS ETMODE must be the first instruction in the program. This specifies that the
language processor should check strings containing DBCS characters for validity. You must enclose DBCS
characters within shift-out (SO) and shift-in (SI) delimiters. (The SO character is X'0E', and the SI
10
CICS TS for VSE/ESA: REXX Guide
Writing and Running a REXX Program
character is X'0F') The SO and SI characters are non-printable. In the following example, the less than (<)
and greater than (>) symbols represent shift-out (SO) and shift-in (SI), respectively. For example,
<.S.Y.M.D> and <.D.B.C.S.R.T.N> represent DBCS symbols in the following example.
Example
The following is an example of a program using a DBCS variable name and a DBCS subroutine label.
/*REXX */
OPTIONS 'ETMODE'/* ETMODE to enable DBCS variable names */
<.S.Y.M.D> = 10/* Variable with DBCS characters between */
y.<.S.Y.M.D> = JUNK
CALL <.D.B.C.S.R.T.N>/* Call subroutine with DBCS name*/
EXIT
<.D.B.C.S.R.T.N>:/* Subroutine with DBCS name*/
DOi=1TO10
IF y.i = JUNK THEN/* Does y.i match the DBCS variable's
SAY 'Value of the DBCS variable is : ' <.S.Y.M.D>
END
RETURN
/* shift-out (<) and shift-in (>)*/
value?*/
Typing in a Program
When you type in the following program, use the REXX/CICS editor for files that reside in the REXX File
System (RFS).
The name of the program is HELLO EXEC (for now, assume that the file type is exec).
1. Sign on to a CICS Transaction Server for VSE/ESA terminal by entering CESN and supplying your user
ID and password when it is requested.
2. Clear the screen.
3. Type:
edit hello.exec
4. Type in the program, exactly as it is shown in Figure 4, beginning with /* REXX HELLO EXEC */. Then
file it using the EDIT command:
====> file
Now your program is ready to run.
/* REXX HELLO EXEC*/
/* A conversation*/
say "Hello! What is your name?"
pull who
if who = "" then say "Hello stranger!"
else say "Hello" who
Figure 4. HELLO EXEC
Running a Program
Clear the screen before running an exec. If you want to run a program that has a file type of EXEC, you
type in REXX followed by its file name. In this case, type rexx hello on the command line and press Enter.
Try it!
Suppose your name is Sam. Type sam and press Enter. Hello SAM is displayed.
Chapter 2. Writing and Running a REXX Program11
Writing and Running a REXX Program
rexx hello
Hello! What is your name?
sam
Hello SAM
Here is what happens:
1. The SAY instruction displays Hello! What is your name?
2. The PULL instruction pauses the program, waiting for a reply.
3. You type sam on the command line and then press Enter.
4. The PULL instruction puts the word SAM into the variable (the place in the computer's storage) called
who.
5. The IF instruction asks, Is who equal to nothing?
who=""
This means, “is the value stored in who equal to nothing?” To find out, REXX substitutes that stored
value for the variable name. So the question now is: Is SAM equal to nothing?
"SAM" = ""
6. Not true. The instruction after then is not processed. Instead, REXX processes the instruction after
else.
7. The SAY instruction displays "Hello" who, which is evaluated as
Hello SAM
Now, here is what happens if you press Enter without typing a response first.
hello
Hello! What is your name?
Hello stranger!
Then again, maybe you did not understand that you had to type in your name. (Perhaps the program
should make your part clearer.) Anyhow, if you just press Enter instead of typing a name:
1. The PULL instruction puts "" (nothing) into the place in the computer's storage called who.
2. Again, the IF instruction tests the variable
who=""
meaning: Is the value of who equal to nothing? When the value of who is substituted, this scans as:
""=""
And this time, it is true.
3. So the instruction after then is processed, and the instruction after else is not.
Interpreting Error Messages
When you run a program that contains an error, an error message often includes the line on which the
error occurred and gives an explanation of the error. Error messages can result from syntax errors and
from computational errors. For example, the following program has a syntax error.
12
CICS TS for VSE/ESA: REXX Guide
Writing and Running a REXX Program
/************************** REXX **********************************/
/* This REXX program contains a deliberate error of not closing*/
/* a comment. Without the error, it would pull input to produce */
/* a greeting.*/
/******************************************************************/
PULL who/* Get the person's name.
IF who = '' THEN
SAY 'Hello, stranger'
ELSE
SAY 'Hello,' who
Figure 5. Example of a program with a Syntax Error
When the program runs, the language processor sends the following lines of output.
7 +++ PULL who/* Get the person's name.IF who =
'' THEN SAY 'Hello, stranger'ELSESAY 'Hello,' who
CICREX453E Error 6 running HELLO EXEC, line 7: Unmatched "/*" or quote
The program runs until the language processor detects the error, the missing */ at the end of the
comment. The PULL instruction does not use the data from the data stack or terminal because this line
contains the syntax error. The program ends, and the language processor sends the error messages.
The first error message begins with the line number of the statement where the language processor
detected the error. Three pluses (+++) and the contents of the statement follow this.
7 +++ PULL who/* Get the person's name.IF who =
'' THEN SAY 'Hello, stranger' ELSESAY 'Hello,' who
The second error message begins with the message number. A message containing the program name,
the line where the language processor found the error, and an explanation of the error follow this.
CICREX453E Error 6 running HELLO EXEC, line 7: Unmatched "/*" or quote
For more information about the error, you can go to the message explanations in Appendix A, “Error
Numbers and Messages,” on page 379.
To fix the syntax error in this program, add */ to the end of the comment on line 7.
PULL who/* Get the person's name. */
How to Prevent Translation to Uppercase
The language processor generally translates alphabetic characters to uppercase before processing them.
The alphabetic characters can be within a program, such as words in a REXX instruction, or they can be
external to a program and processed as input. You can prevent the translation to uppercase as follows:
Characters within a program
To prevent translation of alphabetic characters in a program to uppercase, simply enclose the characters in
single or double quotation marks. The language processor does not change numbers and special
characters, regardless of whether they are in quotation marks. Suppose you use a SAY instruction with a
phrase containing a mixture of alphabetic characters, numbers, and special characters; the language
processor changes only the alphabetic characters.
SAY The bill for lunch comes to £123.51!
results in:
THE BILL FOR LUNCH COMES TO £123.51!
(This example assumes none of the words are the names of variables that have been assigned other
values.)
Chapter 2. Writing and Running a REXX Program13
Writing and Running a REXX Program
Quotation marks ensure that information in a program is processed exactly as typed. This is important in
the following situations:
v For output that must be lowercase or a mixture of uppercase and lowercase.
v To ensure that commands are processed correctly. For example, if a variable name in a program is the
same as a command name, the program can end in error when the command is issued. It is a good
programming practice to avoid using variable names that are the same as commands and to enclose all
commands in quotation marks.
Characters Input to a program
When reading input or passing input from another program, the language processor also changes
alphabetic characters to uppercase before processing them. To prevent translation to uppercase, use the
PARSE instruction.
For example, the following program reads input from the terminal and sends this information to the
terminal output device.
/************************** REXX ***********************************/
/* This REXX program gets the name of an animal from the input*/
/* stream and sends it to the terminal.*/
/*******************************************************************/
PULL animal/* Get the animal name.*/
SAY animal
Figure 6. Example of Reading Input and Writing Output
If the input is tyrannosaurus, the language processor produces the output:
TYRANNOSAURUS
To cause the language processor to read input exactly as it is presented, use the PARSE PULL instruction
instead of the PULL instruction.
PARSE PULL animal
Now if the input is TyRannOsauRus, the output is:
TyRannOsauRus
Exercises - Running and Modifying the Example Programs
You can write and run the preceding example. Now change the PULL instruction to a PARSE PULL
instruction and note the difference.
Passing Information to a program
When a program runs, you can pass information to it in several ways:
v By using PULL to get information from the program stack or terminal input device.
v By specifying input when calling the program.
Getting Information from the Program Stack or Terminal Input Device
The PULL instruction is one way for a program to receive input. Repeating an earlier example shows this.
Here is how to call the ADDTWO program:
REXX addtwo
Here is the ADDTWO program.
14
CICS TS for VSE/ESA: REXX Guide
Writing and Running a REXX Program
/**************************** REXX ******************************/
/* This program adds two numbers and produces their sum.*/
/****************************************************************/
PULL number1
PULL number2
sum = number1 + number2
SAY 'The sum of the two numbers is' sum'.'
Figure 7. Example of a program That Uses PULL
The PULL instruction can extract more than one value at a time from the terminal by separating a line of
input. The following variation of the example shows this.
REXX addtwo 42 21
The PULL instruction extracts the numbers 42 and 21 from the terminal.
/**************************** REXX ******************************/
/* This program adds two numbers and says their sum*/
/****************************************************************/
PULL number1 number2
sum = number1 + number2
SAY 'The sum of the two numbers is' sum'.'
Figure 8. Variation of an Example that Uses PULL
Specifying Values When Calling a program
Another way for a program to receive input is through values you specify when you call the program. For
example to pass the two numbers 42 and 21 to a program named ADD, you could use the CICS
command:
REXX add 42 21
The program ADD uses the ARG instruction to assign the input to variables as shown in the following
example.
/**************************** REXX ******************************/
/* This program receives two numbers as input, adds them, and */
/* produces their sum.*/
/****************************************************************/
ARG number1 number2
sum = number1 + number2
SAY 'The sum of the two numbers is' sum'.'
Figure 9. Example of a program That Uses the ARG Instruction
ARG assigns the first number 42,tonumber1, and the second number 21,tonumber2.
If the number of values is fewer or more than the number of variable names after ARG or PULL, errors
can occur, as the following sections describe.
Specifying Too Few Values
If you specify fewer values than the number of variables after PULL or ARG, the extra variables are set to
the null string. Here is an example in which you pass only one number to the program:
REXX add 42
The language processor assigns the value 42 to number1, the first variable following ARG. It assigns the
null string to number2, the second variable. In this situation, the program ends with an error when it tries to
add the two variables. In other situations, the program might not end in error.
Specifying Too Many Values
When you specify more values than the number of variables following PULL or ARG, the last variable gets
the remaining values. For example, you pass three numbers to the program ADD:
Chapter 2. Writing and Running a REXX Program15
Writing and Running a REXX Program
REXX add 42 21 10
The language processor assigns the value 42 to number1, the first variable following ARG. It assigns the
value 21 10 to number2, the second variable. In this situation, the program ends with an error when it tries
to add the two variables. In other situations, the program might not end in error.
To prevent the last variable from getting the remaining values, use a period (.) at the end of the PULL or
ARG instruction.
ARG number1 number2 .
The period acts as a dummy variable to collect unwanted extra information. (In this case, number1 receives
42, number2 receives 21, and the period ensures the 10 is discarded. If there is no extra information, the
period is ignored. You can also use a period as a placeholder within the PULL or ARG instruction as
follows:
ARG . number1 number2
In this case, the first value, 42, is discarded and number1 and number2 get the next two values, 21 and 10.
Preventing Translation of Input to Uppercase
Like the PULL instruction, the ARG instruction changes alphabetic characters to uppercase. To prevent
translation to uppercase, use PARSE ARG as in the following example.
/**************************** REXX ********************************/
/* This program receives the last name, first name, and score of */
/* a student and reports the name and score.*/
/******************************************************************/
PARSE ARG lastname firstname score
SAY firstname lastname 'received a score of' score'.'
Figure 10. Example of a program That Uses PARSE ARG
Exercises - Using the ARG Instruction
The left column shows the input values sent to a program. The right column is the ARG instruction within
the program that receives the input. What value does each variable receive?
InputVariables Receiving Input
1. 115 -23 66 5.8
ARG first second third
2. .2 0 569 2E6
ARG first second third fourth
3. 13 13 13 13
ARG first second third fourth fifth
4. Weber Joe 91
ARG lastname firstname score
5. Baker Amanda Marie 95
PARSE ARG lastname firstname score
6. Callahan Eunice 88 62
PARSE ARG lastname firstname score .
ANSWERS
1. first = 115, second = -23, third = 66 5.8
2. first = .2, second = 0, third = 569, fourth = 2E6
3. first = 13, second = 13, third = 13, fourth = 13, fifth = null
Values passed to a program are usually called arguments. An argument can consist of one word or a
string of words. Blanks separate words within an argument from each other. The number of arguments
passed depends on how the program is called.
Using the CALL Instruction or a REXX Function Call
When you call a REXX program using either the CALL instruction or a REXX function call, you can pass
up to 20 arguments to the program. Separate each argument from the next with a comma.
For more information about functions and subroutines, see Chapter 6, “Writing Subroutines and Functions,”
on page 57. For more information about arguments, see section “Parsing Multiple Strings as Arguments”
on page 78.
Chapter 2. Writing and Running a REXX Program17
18CICS TS for VSE/ESA: REXX Guide
Chapter 3. Using Variables and Expressions
This chapter describes variables, expressions, and operators, and explains how to use them in REXX
programs.
Program Variables
One of the most powerful aspects of computer programming is the ability to process variable data to
achieve a result. Regardless of the complexity of a process, when data is unknown or varies, you
substitute a symbol for the data. This is much like substituting x and y in an algebraic equation.
x=y+29
The symbol, when its value can vary, is called a variable. A group of symbols or numbers that must be
calculated to be resolved is called an expression.
Using Variables
A variable is a character or group of characters representing a value. A variable can contain either singleor double-byte characters or both. (Double-byte characters are valid only if OPTIONS ETMODE is the first
instruction of your program.) The following variable big represents the value one million or 1,000,000.
big = 1000000
Variables can refer to different values at different times. If you assign a different value to big, it gets the
value of the new assignment, until it is changed again.
big = 999999999
Variables can also represent a value that is unknown when the program is written. In the following
example, the user's name is unknown, so it is represented by the variable who.
PARSE PULL who/* and puts it in variable "who"*/
/* Gets name from current input stream */
Variable Names
A variable name, the part that represents the value, is always on the left of the assignment statement and
the value itself is on the right. In the following example, the variable name is variable1.
variable1 = 5
SAY variable1
As a result of the preceding assignment statement, the language processor assigns variable1 the value 5,
and the SAY produces:
5
Variable names can consist of:
A–Zuppercase alphabetic
a–zlowercase alphabetic
0–9numbers
?!._ special characters
X'41'–X'FE'
double-byte character set (DBCS) characters. (OPTIONS ETMODE must be the first instruction in
your program for these characters to be valid in a variable name.)
v The first character cannot be 0 through 9 or a period (.)
v The variable name cannot exceed 250 bytes. For names containing DBCS characters, count each
DBCS character as 2 bytes, and count the shift-out (SO) and shift-in (SI) as 1 byte each.
v SO (X'0E') and SI (X'0F') must delimit DBCS characters within a DBCS name. Also note that:
– SO and SI cannot be contiguous.
– Nesting of SO / SI is not permitted.
– A DBCS name cannot contain a DBCS blank (X'4040').
v The variable name should not be RC, SIGL, or RESULT, which are REXX special variables. More about
special variables appears later in this book.
Examples of acceptable variable names are:
ANSWER?98BAWord3number the_ultimate_value
Also, if OPTIONS ETMODE is the first instruction in your program, the following are valid DBCS variable
names, where < represents shift-out, > represents shift-in, X, Y, and Z represent DBCS characters, and
lowercase letters and numbers represent themselves.
<.X.Y.Z>number_<.X.Y.Z><.X.Y>1234<.Z>
Variable Values
The value of the variable, which is the value the variable name represents, might be categorized as
follows:
v A constant, which is a number that is expressed as:
An integer (12)
A decimal (12.5)
A floating point number (1.25E2)
A signed number (-12)
A string constant (' 12')
v A string, which is one or more words that may or may not be within quotation marks, such as:
This value can be a string.
'This value is a literal string.'
v The value from another variable, such as:
variable1 = variable2
In the preceding example, variable1 changes to the value of variable2, but variable2 remains the same.
v An expression, which is something that needs to be calculated, such as:
Before a variable is assigned a value, its value is the value of its own name translated to uppercase. For
example, if the variable new has not been assigned a value, then
SAY new
produces
NEW
Exercises - Identifying Valid Variable Names
Which of the following are valid REXX variable names?
1. 8eight
2. £25.00
3. MixedCase
4. nine_to_five
5. result
20
CICS TS for VSE/ESA: REXX Guide
Using Variables and Expressions
ANSWERS
1. Incorrect, because the first character is a number.
2. Incorrect, because the first character is a “£”.
3. Valid
4. Valid
5. Valid, but it is a special variable name that you should use only to receive results from a subroutine.
Using Expressions
An expression is something that needs to be evaluated and consists of numbers, variables, or strings, and
zero or more operators. The operators determine the kind of evaluation to do on the numbers, variables,
and strings. There are four types of operators: arithmetic, comparison, logical, and concatenation.
Arithmetic Operators
Arithmetic operators work on valid numeric constants or on variables that represent valid numeric
constants.
Types of Numeric Constants
12A whole number has no decimal point or commas. Results of arithmetic operations with whole
numbers can contain a maximum of nine digits unless you override this default by using the
NUMERIC DIGITS instruction. For information about the NUMERIC DIGITS instruction, see
section section “NUMERIC” on page 150. Examples of whole numbers are:
123456789091221 999
12.5A decimal number includes a decimal point. Results of arithmetic operations with decimal
numbers are limited to a total maximum of nine digits (NUMERIC DIGITS default) before and after
the decimal. Examples of decimal numbers are:
123456.789 0.888888888
1.25E2
A floating point number in exponential notation, is said to be in scientific notation. The number
after the "E" represents the number of places the decimal point moves. Thus 1.25E2 (also written
as 1.25E+2) moves the decimal point to the right two places and results in 125. When an "E" is
followed by a minus (-), the decimal point moves to the left. For example, 1.25E-2 is .0125.
You can use floating point numbers to represent very large or very small numbers. For more
information about scientific notation (floating point numbers), see section “Exponential Notation” on
page 222.
-12A signed number with a minus (-) next to the number represents a negative value. A signed
number with a plus (+) next to the number represents a positive value. When a number has no
sign, it is processed as if it has a positive value.
The arithmetic operators you can use are:
Operator
Meaning
+Add
−Subtract
*Multiply
/Divide
%Divide and return a whole number without a remainder
//Divide and return the remainder only
Chapter 3. Using Variables and Expressions21
Using Variables and Expressions
**Raise a number to a whole number power
−number
(Prefix −) Same as the subtraction 0 - number
+number
(Prefix +) Same as the addition 0 + number
Using numeric constants and arithmetic operators, you can write arithmetic expressions such as:
7 + 2/* result is 9*/
7 - 2/* result is 5*/
7 * 2/* result is 14*/
7 ** 2/* result is 49*/
7 ** 2.5/* result is an error */
Division
Notice that three operators represent division. Each operator computes the result of a division expression
in a different way.
/Divide and express the answer possibly as a decimal number. For example:
7 / 2/* result is 3.5 */
6 / 2/* result is 3*/
%Divide and express the answer as a whole number. The remainder is ignored. For example:
7 % 2/* result is 3*/
//Divide and express the answer as the remainder only. For example:
7 // 2/* result is 1*/
Order of Evaluation
When you have more than one operator in an arithmetic expression, the order of numbers and operators
can be critical. For example, in the following expression, which operation does the language processor
perform first?
7+2*(9/3)-1
Proceeding from left to right, the language processor evaluates the expression as follows:
v First it evaluates expressions within parentheses.
v Then it evaluates expressions with operators of higher priority before expressions with operators of
lower priority.
Arithmetic operator priority is as follows, with the highest first:
Table 1. Arithmetic Operator Priority
- +Prefix operators
**Power (exponential)
*/%//Multiplication and division
+ -Addition and subtraction
Thus, the preceding example would be evaluated in the following order:
1. Expression in parentheses
7+2*(9/3)-1
\___/
3
2. Multiplication
22
CICS TS for VSE/ESA: REXX Guide
Using Variables and Expressions
7+2*3-1
\___/
6
3. Addition and subtraction from left to right
7+6-1=12
Using Arithmetic Expressions
You can use arithmetic expressions in a program many different ways. The following example uses several
arithmetic operators to round and remove extra decimal places from a dollar and cents value.
/****************************** REXX *********************************/
/* This program computes the total price of an item including sales */
/* tax, rounded to two decimal places. The cost and percent of the */
/* tax (expressed as a decimal number) are passed to the program*/
/* when you run it.*/
/*********************************************************************/
PARSE ARG cost percent_tax
total = cost + (cost * percent_tax)/* Add tax to cost.*/
price = ((total * 100 + .5) % 1) / 100/* Round and remove extra */
SAY 'Your total cost is £'price'.'
Figure 11. Example Using Arithmetic Expressions
/* decimal places.*/
Exercises—Calculating Arithmetic Expressions
1. What line of output does the following program produce?
pa=1
ma=1
kids = 3
SAY "There are" pa + ma + kids "people in this family."
2. What is the value of:
a. 6-4+1
b. 6-(4+1)
c. 6*4+2
d. 6*(4+2)
e. 24%5/2
ANSWERS
1. There are 5 people in this family.
2. The values are as follows:
a. 3
b. 1
c. 26
d. 36
e. 2
Comparison Operators
Expressions that use comparison operators do not return a number value as do arithmetic expressions.
Comparison expressions return either 1, which represents true, or 0, which represents false.
Comparison operators can compare numbers or strings and perform evaluations, such as:
Are the terms equal? (A=Z)
Is the first term greater than the second? (A>Z)
Is the first term less than the second? (A<Z)
Chapter 3. Using Variables and Expressions23
Using Variables and Expressions
For example, if A=4and Z=3, then the results of the previous comparison questions are:
You often use a comparison expression in an IF...THEN...ELSE instruction. The following example uses an
IF...THEN...ELSE instruction to compare two values. For more information about this instruction, see
section “IF...THEN...ELSE Instructions” on page 33.
24
CICS TS for VSE/ESA: REXX Guide
Using Variables and Expressions
/****************************** REXX *********************************/
/* This program compares what you paid for lunch for two*/
/* days in a row and then comments on the comparison.*/
/*********************************************************************/
PARSE PULL yesterday/* Gets yesterday's price from input stream */
PARSE PULL today/* Gets today's price */
IF today > yesterday THEN/* lunch cost increased */
SAY "Today's lunch cost more than yesterday's."
ELSE/* lunch cost remained the same or decreased */
SAY "Today's lunch cost the same or less than yesterday's."
Figure 12. Example Using a Comparison Expression
Exercises - Using Comparison Expressions
1. Based on the preceding example of using a comparison expression, what result does the language
processor produce from the following lunch costs?
Yesterday's Lunch
Today's Lunch
4.423.75
3.503.50
3.754.42
2. What is the result (0 or 1) of the following expressions?
a. "Apples" = "Oranges"
b. " Apples" = "Apples"
c. " Apples" == "Apples"
d. 100 = 1E2
e. 100 \= 1E2
f. 100 \== 1E2
ANSWERS
1. The language processor produces the following sentences:
a. Today's lunch cost the same or less than yesterday's.
b. Today's lunch cost the same or less than yesterday's.
c. Today's lunch cost more than yesterday's.
2. The expressions result in the following. Remember 0 is false and 1 is true.
a. 0
b. 1
c. 0 (The first " Apples" has a space.)
d. 1
e. 0
f. 1
Logical (Boolean) Operators
Logical expressions, like comparison expressions, return 1 (true) or 0 (false) when processed. Logical
operators combine two comparisons and return 1 or 0 depending on the results of the comparisons.
The logical operators are:
Chapter 3. Using Variables and Expressions25
Using Variables and Expressions
Operator
Meaning
&AND
Returns 1 if both comparisons are true. For example:
(4 > 2) & (a = a)/* true, so result is 1 */
(2 > 4) & (a = a)/* false, so result is 0 */
|Inclusive OR
Returns 1 if at least one comparison is true. For example:
(4 > 2) | (5 = 3)/* at least one is true, so result is 1 */
(2 > 4) | (5 = 3)/* neither one is true, so result is 0 */
&&Exclusive OR
Returns 1 if only one comparison (but not both) is true. For example:
(4 > 2) && (5 = 3) /* only one is true, so result is 1*/
(4 > 2) && (5 = 5) /* both are true, so result is 0*/
(2 > 4) && (5 = 3) /* neither one is true, so result is 0 */
Prefix \,¬
Logical NOT
Negates—returning the opposite response. For example:
\ 0/* opposite of 0, so result is 1*/
\ (4 > 2)/* opposite of true, so result is 0 */
Using Logical Expressions
You can use logical expressions in complex conditional instructions and as checkpoints to screen
unwanted conditions. When you have a series of logical expressions, for clarification, use one or more
sets of parentheses to enclose each expression.
IF ((A < B) | (J < D)) & ((M = Q) | (M = D)) THEN ....
The following example uses logical operators to make a decision.
/****************************** REXX ********************************/
/* This program receives arguments for a complex logical expression */
/* that determines whether a person should go skiing. The first*/
/* argument is a season and the other two can be 'yes' or 'no'.*/
/********************************************************************/
PARSE ARG season snowing broken_leg
IF ((season = 'WINTER') | (snowing ='YES')) & (broken_leg ='NO')
THEN SAY 'Go skiing.'
ELSE
SAY 'Stay home.'
Figure 13. Example Using Logical Expressions
When arguments passed to this example are SPRING YES NO, the IF clause translates as follows:
IF ((season = 'WINTER') | (snowing ='YES')) & (broken_leg ='NO') THEN
\______________/\____________/\_____________/
falsetruetrue
26
CICS TS for VSE/ESA: REXX Guide
Using Variables and Expressions
\___________________//
true/
\_____________________________/
true
As a result, when you run the program, it produces the result:
Go skiing.
Exercises - Using Logical Expressions
A student applying to colleges has decided to evaluate them according to the following specifications:
IF (inexpensive | scholarship) & (reputable | nearby) THEN
SAY "I'll consider it."
ELSE
SAY "Forget it!"
A college is inexpensive, did not offer a scholarship, is reputable, but is more than 1000 miles away.
Should the student apply?
ANSWER
Yes. The conditional instruction works out as follows:
IF (inexpensive | scholarship) & (reputable | nearby) THEN ...
\__________/ \___________/\_________/ \______/
truefalsetruefalse
\___________/\_________/
truetrue
\_________________________/
true
Concatenation Operators
Concatenation operators combine two terms into one. The terms can be strings, variables, expressions, or
constants. Concatenation can be significant in formatting output.
The operators that indicate how to join two terms are as follows:
Operator
Meaning
blank Concatenates terms and places one blank between them. If more than one blank separates terms,
this becomes a single blank. For example:
SAY trueblue/* result is TRUE BLUE */
||Concatenates terms with no blanks between them. For example:
(8 / 2)||(3 * 3)/* result is 49 */
abuttal
Concatenates terms with no blanks between them. For example:
per_cent'%'/* if per_cent = 50, result
You can use abuttal only with terms that are of different types, such as a literal string and a
symbol, or when only a comment separates two terms.
Using Concatenation Operators
One way to format output is to use variables and concatenation operators as in the following example.
is 50% */
Chapter 3. Using Variables and Expressions27
Using Variables and Expressions
/****************************** REXX *********************************/
/* This program formats data into columns for output.*/
/*********************************************************************/
A more sophisticated way to format information is with parsing and templates. Information about parsing
appears in section “Parsing Data” on page 73.
Priority of Operators
When more than one type of operator appears in an expression, what operation does the language
processor do first?
IF (A > 7**B) & (B < 3)
Like the priority of operators for the arithmetic operators, there is an overall priority that includes all
operators. The priority of operators is as follows with the highest first.
Table 2. Overall Operator Priority
\or¬ - +Prefix operators
**Power (exponential)
*/%//Multiply and divide
+ -Add and subtract
blank || abuttalConcatenation operators
== = >< and so onComparison operators
&Logical AND
| &&Inclusive OR and exclusive OR
Thus, given the following values
A=8
B=2
C=10
the language processor would evaluate the previous example
IF (A > 7**B) & (B < 3)
as follows:
1. Evaluate what is inside the first set of parentheses.
a. Evaluate A to 8.
b. Evaluate B to 2.
c. Evaluate 7**2.
d. Evaluate8>49isfalse (0).
2. Evaluate what is inside the next set of parentheses.
a. Evaluate B to 2.
b. Evaluate2<3istrue (1).
28
CICS TS for VSE/ESA: REXX Guide
Using Variables and Expressions
3. Evaluate 0&1is 0
Exercises - Priority of Operators
1. What are the answers to the following examples?
a. 22 + (12 * 1)
b. -6/-2>(45%7/2)-1
c. 10*2-(5+1)//5*2+15-1
2. In the example of the student and the college from the previous exercise on page “Exercises - Using
Logical Expressions” on page 27, if the parentheses were removed from the student's formula, what
would be the outcome for the college?
IF inexpensive | scholarship & reputable | nearby THEN
SAY "I'll consider it."
ELSE
SAY "Forget it!"
Remember the college is inexpensive, did not offer a scholarship, is reputable, but is 1000 miles away.
ANSWERS
1. The results are as follows:
a. 34 (22 + 12 = 34)
b. 1 (true) (3>3-1)
c. 32(20-2+15-1)
2. I'll consider it.
The & operator has priority, as follows, but the outcome is the same as the previous version with the
parentheses.
IF inexpensive | scholarship & reputable | nearby THEN
\_________/\_________/\_______/\____/
truefalsetruefalse
\\___________//
\false/
\_________________//
true/
\____________________/
true
Tracing Expressions with the TRACE Instruction
You can use the TRACE instruction to show how the language processor evaluates each operation of an
expression as it reads it, or to show the final result of an expression. These two types of tracing are useful
for debugging programs.
Tracing Operations
To trace operations within an expression, use the TRACE I (TRACE Intermediates) form of the TRACE
instruction. The language processor breaks down all expressions that follow the instruction and analyzes
them as:
>V>- Variable value - The data traced is the contents
>L>- Literal value - The data traced is a literal
>O>- Operation result - The data traced is the result
The following example uses the TRACE I instruction. (The line numbers are not part of the program. They
facilitate the discussion of the example that follows it.)
of a variable.
(string, uninitialized variable, or constant).
of an operation on two terms.
Chapter 3. Using Variables and Expressions29
Using Variables and Expressions
1 /************************* REXX ***************************/
2 /* This program uses the TRACE instruction to show how*/
3 /* an expression is evaluated, operation by operation.*/
4 /**********************************************************/
5 a=9
6 y=2
7 TRACE I
8
9 IFa+1>5*yTHEN
10SAY 'a is big enough.'
11 ELSE NOP/* No operation on the ELSE path */
Figure 15. TRACE Shows How REXX Evaluates an Expression
When you run the example, the SAY instruction produces:
The 9 is the line number. The *-* indicates that what follows is the data from the program,
IFa+1<5*y. The remaining lines break down all the expressions.
Tracing Results
To trace only the final result of an expression, use the TRACE R (TRACE Results) form of the TRACE
instruction. The language processor analyzes all expressions that follow the instruction as follows:
>>>Final result of an expression
If you changed the TRACE instruction operand in the previous example from an I to an R, you would see
the following results.
9*-*IFa+1>5*y
>>>"0"
In addition to tracing operations and results, the TRACE instruction offers other types of tracing, see
section “TRACE” on page 166.
Exercises - Using the TRACE Instruction
Write a program with a complex expression, such as:
IF(a>z)|(c<2*d)THEN ....
Define a, z, c, and d in the program and use the TRACE I instruction.
ANSWER
30
CICS TS for VSE/ESA: REXX Guide
Using Variables and Expressions
/****************************** REXX ********************************/
/* This program uses the TRACE instruction to show how the language */
/* processor evaluates an expression, operation by operation.*/
/********************************************************************/
This chapter introduces instructions that alter the sequential execution of a program and demonstrates
how to use those instructions.
Conditional, Looping, and Interrupt Instructions
Generally, when a program runs, one instruction after another executes, starting with the first and ending
with the last. The language processor, unless told otherwise, executes instructions sequentially.
You can change the order of execution within a program by using REXX instructions that cause the
language processor to skip some instructions, repeat others, or transfer control to another part of the
program. These REXX instructions can be classified as follows:
v Conditional instructions set up at least one condition in the form of an expression. If the condition is
true, the language processor selects the path following that condition. Otherwise the language
processor selects another path. The REXX conditional instructions are:
IF expression THEN...ELSE
SELECT WHEN expression...OTHERWISE...END
v Looping instructions tell the language processor to repeat a set of instructions. A loop can repeat a
specified number of times or it can use a condition to control repeating. REXX looping instructions are:
DO repetitor...END
DO WHILE expression...END
DO UNTIL expression...END
v Interrupt instructions tell the language processor to leave the program entirely or leave one part of the
program and go to another part, either permanently or temporarily. The REXX interrupt instructions are:
EXIT
SIGNAL label
CALL label...RETURN
Using Conditional Instructions
There are two types of conditional instructions:
v IF...THEN...ELSE can direct the execution of a program to one of two choices.
v SELECT WHEN...OTHERWISE...END can direct the execution to one of many choices.
IF...THEN...ELSE Instructions
The examples of IF...THEN...ELSE instructions in previous chapters demonstrate the two-choice selection.
In a flow chart, this appears as follows:
As a REXX instruction, the flowchart example looks like:
IF expression THEN instruction
You can also arrange the clauses in one of the following ways to enhance readability:
IF expression THEN
instruction
ELSE
instruction
or
IF expression
THEN
ELSE
When you put the entire instruction on one line, you must use a semicolon before the ELSE to separate
the THEN clause from the ELSE clause.
IF expression THEN instruction; ELSE instruction
Generally, at least one instruction should follow the THEN and ELSE clauses. When either clause has no
instructions, it is good programming practice to include NOP (no operation) next to the clause.
IF expression THEN
instruction
ELSE NOP
ELSE instruction
instruction
instruction
If you have more than one instruction for a condition, begin the set of instructions with a DO and end them
with an END.
IF weather = rainy THEN
SAY 'Find a good book.'
ELSE
DO
PULL playgolf/* Gets data from input stream */
If playgolf='YES' THEN SAY 'Fore!'
END
Without the enclosing DO and END, the language processor assumes only one instruction for the ELSE
clause.
Nested IF...THEN...ELSE Instructions
Sometimes it is necessary to have one or more IF...THEN...ELSE instructions within other
IF...THEN...ELSE instructions. Having one type of instruction within another is called nesting. With nested
IF instructions, it is important to match each IF with an ELSE and each DO with an END.
IF weather = fine THEN
DO
SAY 'What a lovely day!'
IF tenniscourt = free THEN
SAY 'Let''s play tennis!'
ELSE NOP
END
ELSE
SAY 'We should take our raincoats!'
Not matching nested IFs to ELSEs and DOs to ENDs can have some surprising results. If you eliminate
the DOs and ENDs and the ELSE NOP, as in the following example, what is the outcome?
34
CICS TS for VSE/ESA: REXX Guide
Control Flow within a Program
/******************************** REXX *******************************/
/* This program demonstrates what can happen when you do not include */
/* DOs, ENDs, and ELSEs in nested IF...THEN...ELSE instructions.*/
/*********************************************************************/
weather = 'fine'
tenniscourt = 'occupied'
IF weather = 'fine' THEN
SAY 'What a lovely day!'
IF tenniscourt = 'free' THEN
SAY 'Let''s play tennis!'
ELSE
SAY 'We should take our raincoats!'
Figure 17. Example of Missing Instructions
Looking at the program you might assume the ELSE belongs to the first IF. However, the language
processor associates an ELSE with the nearest unpaired IF. The outcome is as follows:
What a lovely day!
We should take our raincoats!
Chapter 4. Controlling the Flow within a program35
Control Flow within a Program
Exercise - Using the IF...THEN...ELSE Instruction
Write the REXX instructions for the following flowchart:
Z=2
A=3
Tr ueFalse
C=3
A=0
Tr ueFalse
Tr ueFalse
Tr ueFalse
C=2
Z=1
A=1
ANSWER
IFa=0THEN
IFc=2THEN
z=1
ELSE NOP
ELSE
IFz=2THEN
IFc=3THEN
a=1
ELSE
a=3
ELSE NOP
36
CICS TS for VSE/ESA: REXX Guide
Control Flow within a Program
SELECT WHEN...OTHERWISE...END Instruction
To select one of any number of choices, use the SELECT WHEN...OTHERWISE...END instruction. In a
flowchart it appears as follows:
SELECT
THEN
WHEN
WHEN
WHEN
expression
False
expression
False
expression
Tr ue
Tr ue
Tr ue
instruction
THEN
instruction
THEN
instruction
OTHERWISE
instruction(s)
END
As a REXX instruction, the flowchart example looks like:
SELECT
WHEN expression THEN instruction
WHEN expression THEN instruction
WHEN expression THEN instruction
:
:
OTHERWISE
instruction(s)
END
The language processor scans the WHEN clauses starting at the beginning until it finds a true expression.
After it finds a true expression, it ignores all other possibilities, even though they might also be true. If no
WHEN expressions are true, it processes the instructions following the OTHERWISE clause.
As with IF...THEN...ELSE, when you have more than one instruction for a possible path, begin the set of
instructions with a DO and end them with an END. However, if more than one instruction follows the
OTHERWISE keyword, DO and END are not necessary.
Chapter 4. Controlling the Flow within a program37
Control Flow within a Program
/******************************** REXX *******************************/
/* This program receives input with a person's age and sex. In*/
/* reply, it produces a person's status as follows:*/
/*BABIES- under 5*/
/*GIRLS- female 5 to 12*/
/*BOYS- male 5 to 12*/
/*TEENAGERS - 13 through 19*/
/*WOMEN- female 20 and up*/
/*MEN- male 20 and up*/
/*********************************************************************/
PARSE ARG age sex .
SELECT
WHEN age < 5 THEN/* person younger than 5 */
status = 'BABY'
WHEN age < 13 THEN/* person between 5 and 12 */
DO
IF sex = 'M' THEN/* boy between 5 and 12 */
status = 'BOY'
ELSE/* girl between 5 and 12 */
status = 'GIRL'
END
WHEN age < 20 THEN/* person between 13 and 19 */
status = 'TEENAGER'
OTHERWISE
IF sex = 'M' THEN/* man 20 or older */
status = 'MAN'
ELSE/* woman 20 or older */
status = 'WOMAN'
END
SAY 'This person should be counted as a' status'.'
Figure 18. Example Using SELECT WHEN...OTHERWISE...END
Each SELECT must end with an END. Indenting each WHEN makes a program easier to read.
Exercises - Using SELECT WHEN...OTHERWISE...END
"Thirty days hath September, April, June, and November; all the rest have thirty-one, save February alone
..."
Write a program that uses the input of a number from 1 to 12, representing the month, and produces the
number of days in that month. Assume the user specifies the month number as an argument when calling
the program. (Include in the program an ARG instruction to assign the month number into the variable
month). Then have the program produce the number of days. For month 2, this can be 28 or 29.
ANSWER
38
CICS TS for VSE/ESA: REXX Guide
/******************************** REXX *******************************/
/* This program uses the input of a whole number from 1 to 12 that*/
/* represents a month. It produces the number of days in that*/
/* month.*/
/*********************************************************************/
ARG month
SELECT
WHEN month = 9 THEN
days = 30
WHEN month = 4 THEN
days = 30
WHEN month = 6 THEN
days = 30
WHEN month = 11 THEN
days = 30
WHEN month = 2 THEN
days = '28 or 29'
OTHERWISE
days = 31
END
SAY 'There are' days 'days in Month' month'.'
Figure 19. Possible Solution
Control Flow within a Program
Using Looping Instructions
There are two types of looping instructions, repetitive loops and conditional loops. Repetitive loops let
you repeat instructions a certain number of times. Conditional loops use a condition to control repeating.
All loops, regardless of the type, begin with the DO keyword and end with the END keyword.
Repetitive Loops
The simplest loop tells the language processor to repeat a group of instructions a specific number of
times. It uses a constant after the keyword DO.
DO 5
SAY 'Hello!'
END
When you run this example, it produces five lines of Hello!:
Hello!
Hello!
Hello!
Hello!
Hello!
You can also use a variable in place of a constant, as in the following example, which gives you the same
results.
number = 5
DO number
SAY 'Hello!'
END
A variable that controls the number of times a loop repeats is called a control variable. Unless you
specify otherwise, the control variable increases by 1 each time the loop repeats.
Chapter 4. Controlling the Flow within a program39
Control Flow within a Program
DO number=1TO5
SAY 'Loop' number
SAY 'Hello!'
END
SAY 'Dropped out of the loop when number reached' number
This example results in five lines of Hello! preceded by the number of the loop. The number increases at
the bottom of the loop and is tested at the top.
Loop 1
Hello!
Loop 2
Hello!
Loop 3
Hello!
Loop 4
Hello!
Loop 5
Hello!
Dropped out of the loop when number reached 6
You can change the increment of the control variable with the keyword BY as follows:
DO number=1TO10BY2
SAY 'Loop' number
SAY 'Hello!'
END
SAY 'Dropped out of the loop when number reached' number
This example has results similar to the previous example except the loops are numbered in increments of
two.
Loop 1
Hello!
Loop 3
Hello!
Loop 5
Hello!
Loop 7
Hello!
Loop 9
Hello!
Dropped out of the loop when number reached 11
Infinite Loops
What happens when the control variable of a loop cannot attain the last number? For example, in the
following program segment, count does not increase beyond 1.
DO count=1to10
SAY 'Number' count
count = count - 1
END
The result is called an infinite loop because count alternates between 1 and 0, producing an endless
number of lines saying Number 1.
If your program is in an infinite loop, contact the operator to cancel it. An authorized user can issue the
CEMT SET TASK PURGE command to halt an exec.
DO FOREVER Loops
Sometimes you might want to write an infinite loop purposely; for instance, in a program that reads records
from a file until it reaches the end of the file. You can use the EXIT instruction to end an infinite loop when
a condition is met, as in the following example. More about the EXIT instruction appears in section “EXIT
Instruction” on page 48.
40
CICS TS for VSE/ESA: REXX Guide
Control Flow within a Program
/******************************* REXX ********************************/
/* This program processes strings until the value of a string is*/
/* a null string.*/
/*********************************************************************/
DO FOREVER
PULL string/* Gets string from input stream */
IF string = '' THEN
PULL file_name
IF file_name = '' THEN
EXIT
ELSE
DO
result = process(string)/* Calls a user-written function */
IF result = 0 THEN SAY "Processing complete for string:" string
ELSE SAY "Processing failed for string:" string
END
END
Figure 20. Example Using a DO FOREVER Loop
This example sends strings to a user-written function for processing and then issues a message that the
processing completed successfully or failed. When the input string is a blank, the loop ends and so does
the program. You can also end the loop without ending the program by using the LEAVE instruction. The
following topic describes this.
/* to do processing on string.*/
LEAVE Instruction
The LEAVE instruction causes an immediate exit from a repetitive loop. Control goes to the instruction
following the END keyword of the loop. An example of using the LEAVE instruction follows:
/******************************** REXX *******************************/
/* This program uses the LEAVE instruction to exit from a DO*/
/* FOREVER loop.*/
/*********************************************************************/
DO FOREVER
PULL string/* Gets string from input stream*/
IF string = 'QUIT' then
LEAVE
ELSE
DO
result = process(string)/* Calls a user-written function */
IF result = 0 THEN SAY "Processing complete for string:" string
ELSE SAY "Processing failed for string:" string
END
END
SAY 'Program run complete.'
Figure 21. Example Using the LEAVE Instruction
/* to do processing on string.*/
ITERATE Instruction
The ITERATE instruction stops execution from within the loop and passes control to the DO instruction at
the top of the loop. Depending on the type of DO instruction, the language processor increases and tests
a control variable or tests a condition to determine whether to repeat the loop. Like LEAVE, ITERATE is
used within the loop.
DO count=1TO10
IF count = 8
THEN
ITERATE
ELSE
SAY 'Number' count
END
This example results in a list of numbers from 1 to 10 with the exception of number 8.
Chapter 4. Controlling the Flow within a program41
Control Flow within a Program
Number 1
Number 2
Number 3
Number 4
Number 5
Number 6
Number 7
Number 9
Number 10
Exercises - Using Loops
1. What are the results of the following loops?
DO digit=1TO3
a.
SAY digit
END
SAY 'Digit is now' digit
b. DO count = 10 BY -2 TO 6
SAY count
END
SAY 'Count is now' count
c. DO index = 10 TO 8
SAY 'Hup! Hup! Hup!'
END
SAY 'Index is now' index
2. Sometimes an infinite loop can occur when input to end the loop does not match what is expected. For
instance, in the example of using the LEAVE Instruction on page 41, what happens when the input is
Quit and a PARSE PULL instruction replaces the PULL instruction?
PARSE PULL file_name
ANSWERS
1. The results of the repetitive loops are as follows:
a.1
2
3
Digit is now 4
b.10
8
6
Count is now 4
c.Index is now 10
2. The program would be unable to leave the loop because Quit is not equal to QUIT. In this case,
omitting the PARSE keyword is preferred because regardless of whether the input is quit, QUIT,or
Quit, the language processor translates the input to uppercase before comparing it to QUIT.
Conditional Loops
There are two types of conditional loops, DO WHILE and DO UNTIL. One or more expressions control
both types of loops. However, DO WHILE loops test the expression before the loop executes the first time
and repeat only when the expression is true. DO UNTIL loops test the expression after the loop executes
at least once and repeat only when the expression is false.
42
CICS TS for VSE/ESA: REXX Guide
DO WHILE Loops
DO WHILE loops in a flowchart appear as follows:
DO WHILE
Control Flow within a Program
expression
Tr ue
instruction(s)
False
END
As REXX instructions, the flowchart example looks like:
DO WHILE expression/* expression must be true */
instruction(s)
END
Use a DO WHILE loop when you want to execute the loop while a condition is true. DO WHILE tests the
condition at the top of the loop. If the condition is initially false, the language processor never executes the
loop.
You can use a DO WHILE loop instead of the DO FOREVER loop in the example of using the LEAVE
instruction on page 41. However, you need to initialize the loop with a first case so the condition can be
tested before you get into the loop. Notice the first case initialization in the first PULL of the following
example.
/******************************** REXX *******************************/
/* This program uses a DO WHILE loop to send a string to a*/
/* user-written function for processing.*/
/*********************************************************************/
PULL string/* Gets string from input stream */
DO WHILE string \= 'QUIT'
result = process(string)/* Calls a user-written function */
IF result = 0 THEN SAY "Processing complete for string:" string
ELSE SAY "Processing failed for string:" string
PULL string
END
SAY 'Program run complete.'
/* to do processing on string.*/
Figure 22. Example Using DO WHILE
Exercise - Using a DO WHILE Loop
Write a program with a DO WHILE loop that uses as input a list of responses about whether passengers
on a commuter airline want a window seat. The flight has 8 passengers and 4 window seats. Discontinue
the loop when all the window seats are taken. After the loop ends, produce the number of window seats
taken and the number of responses processed.
ANSWER
Chapter 4. Controlling the Flow within a program43
Control Flow within a Program
/******************************** REXX *******************************/
/* This program uses a DO WHILE loop to keep track of window seats*/
/* in an 8-seat commuter airline.*/
/*********************************************************************/
window_seats = 0/* Initialize window seats to 0 */
passenger = 0/* Initialize passengers to 0*/
DO WHILE (passenger < 8) & (window_seats \= 4)
/******************************************************************/
/* Continue while the program has not yet read the responses of*/
/* all 8 passengers and while all the window seats are not taken. */
/******************************************************************/
PULL window/* Gets "Y" or "N" from input stream */
passenger = passenger + 1 /* Increase number of passengers by 1 */
IF window = 'Y' THEN
window_seats = window_seats+1/*Increase window seats by 1 */
ELSE NOP
END
SAY window_seats 'window seats were assigned.'
SAY passenger 'passengers were questioned.'
Figure 23. Possible Solution
DO UNTIL Loops
DO UNTIL loops in a flowchart appear as follows:
DO UNTIL
instruction(s)
expression
False
Tr ue
END
As REXX instructions, the flowchart example looks like:
DO UNTIL expression/* expression must be false */
instruction(s)
END
Use DO UNTIL loops when a condition is not true and you want to execute the loop until the condition is
true. The DO UNTIL loop tests the condition at the end of the loop and repeats only when the condition is
false. Otherwise, the loop executes once and ends. For example:
44
CICS TS for VSE/ESA: REXX Guide
Control Flow within a Program
/******************************** REXX ******************************/
/* This program uses a DO UNTIL loop to ask for a password. If the */
/* password is incorrect three times, the loop ends.*/
/********************************************************************/
password = 'abracadabra'
time = 0
DO UNTIL (answer = password) | (time = 3)
PULL answer/* Gets ANSWER from input stream */
time = time + 1
END
Figure 24. Example Using DO UNTIL
Exercise - Using a DO UNTIL Loop
Change the program in the previous exercise on page “Exercise - Using a DO WHILE Loop” on page 43
from a DO WHILE to a DO UNTIL loop and achieve the same results. Remember that DO WHILE loops
check for true expressions and DO UNTIL loops check for false expressions, which means their logical
operators are often reversed.
Chapter 4. Controlling the Flow within a program45
Control Flow within a Program
ANSWER
/******************************** REXX *******************************/
/* This program uses a DO UNTIL loop to keep track of window seats*/
/* in an 8-seat commuter airline.*/
/*********************************************************************/
window_seats = 0/* Initialize window seats to 0 */
passenger = 0/* Initialize passengers to 0*/
DO UNTIL (passenger >= 8) | (window_seats = 4)
/******************************************************************/
/* Continue while the program has not yet read the responses of*/
/* all 8 passengers and while all the window seats are not taken. */
/******************************************************************/
PULL window/* Gets "Y" or "N" from input stream */
passenger = passenger + 1 /* Increase number of passengers by 1 */
IF window = 'Y' THEN
window_seats = window_seats+1/*Increase window seats by 1 */
ELSE NOP
END
SAY window_seats 'window seats were assigned.'
SAY passenger 'passengers were questioned.'
Figure 25. Possible Solution
Combining Types of Loops
You can combine repetitive and conditional loops to create a compound loop. The following loop is set to
repeat 10 times while the quantity is less than 50, at which point it stops.
quantity = 20
DO number=1TO10WHILE quantity < 50
quantity = quantity + number
SAY 'Quantity = 'quantity ' (Loop 'number')'
You can substitute a DO UNTIL loop, change the comparison operator from < to >, and get the same
results.
quantity = 20
DO number=1TO10UNTIL quantity > 50
quantity = quantity + number
SAY 'Quantity = 'quantity ' (Loop 'number')'
END
Nested DO Loops
Like nested IF...THEN...ELSE instructions, DO loops can contain other DO loops. A simple example
follows:
46
CICS TS for VSE/ESA: REXX Guide
Control Flow within a Program
DO outer=1TO2
DO inner=1TO2
SAY 'HIP'
END
SAY 'HURRAH'
END
The output from this example is:
HIP
HIP
HURRAH
HIP
HIP
HURRAH
If you need to leave a loop when a certain condition arises, use the LEAVE instruction followed by the
name of the control variable of the loop. If the LEAVE instruction is for the inner loop, processing leaves
the inner loop and goes to the outer loop. If the LEAVE instruction is for the outer loop, processing leaves
both loops.
To leave the inner loop in the preceding example, add an IF...THEN...ELSE instruction that includes a
LEAVE instruction after the IF instruction.
DO outer=1TO2
DO inner=1TO2
IF inner > 1 THEN
LEAVE inner
ELSE
SAY 'HIP'
END
SAY 'HURRAH'
END
The result is as follows:
HIP
HURRAH
HIP
HURRAH
Exercises - Combining Loops
1. What happens when the following program runs?
DO outer=1TO3
SAY/* Produces a blank line */
DO inner=1TO3
SAY 'Outer' outer 'Inner' inner
END
END
2. Now what happens when the LEAVE instruction is added?
DO outer=1TO3
SAY/* Produces a blank line */
DO inner=1TO3
IF inner = 2 THEN
LEAVE inner
ELSE
SAY 'Outer' outer 'Inner' inner
END
END
ANSWERS
1. When this example runs, it produces the following:
Chapter 4. Controlling the Flow within a program47
Control Flow within a Program
Outer 1 Inner 1
Outer 1 Inner 2
Outer 1 Inner 3
Outer 2 Inner 1
Outer 2 Inner 2
Outer 2 Inner 3
Outer 3 Inner 1
Outer 3 Inner 2
Outer 3 Inner 3
2. The result is one line of output for each of the inner loops.
Outer 1 Inner 1
Outer 2 Inner 1
Outer 3 Inner 1
Using Interrupt Instructions
Instructions that interrupt the flow of a program can cause the program to:
v End (EXIT)
v Skip to another part of the program marked by a label (SIGNAL)
v Go temporarily to a subroutine either within the program or outside the program (CALL or RETURN).
EXIT Instruction
The EXIT instruction causes a REXX program to unconditionally end and return to where the program was
called. If another program called the REXX program, EXIT returns to that calling program. More about
calling external routines appears later in this chapter and in Chapter 6, “Writing Subroutines and
Functions,” on page 57. For more detailed information on the EXIT instruction, see section “EXIT” on page
143.
Besides ending a program, EXIT can also return a value to the caller of the program. If the program was
called as a subroutine from another REXX program, the value is received in the REXX special variable
RESULT. If the program was called as a function, the value is received in the original expression at the
point where the function was called. Otherwise, the value is received in the REXX special variable RC.
The value can represent a return code and can be in the form of a constant or an expression that is
computed.
/******************************** REXX ****************************/
/* This program uses the EXIT instruction to end the program and */
/* return a value indicating whether a job applicant gets the*/
/* job. A value of 0 means the applicant does not qualify for*/
/* the job, but a value of 1 means the applicant gets the job.*/
/* The value is placed in the REXX special variable RESULT.*/
/******************************************************************/
PULL months_experience/* Gets number from input stream*/
PULL references/* Gets "Y" or "N" from input stream */
PULL start_tomorrow/* Gets "Y" or "N" from input stream */
IF (months_experience > 24) & (references = 'Y') & (start_tomorrow= 'Y')
THEN job = 1/* person gets the job*/
ELSE job = 0/* person does not get the job */
EXIT job
Figure 26. Example Using the EXIT Instruction
48
CICS TS for VSE/ESA: REXX Guide
Control Flow within a Program
CALL and RETURN Instructions
The CALL instruction interrupts the flow of a program by passing control to an internal or external
subroutine. An internal subroutine is part of the calling program. An external subroutine is another
program. The RETURN instruction returns control from a subroutine back to the calling program and
optionally returns a value. For more detailed information on the CALL and RETURN instructions, see
sections “CALL” on page 135 and “RETURN” on page 161.
When calling an internal subroutine, CALL passes control to a label specified after the CALL keyword.
When the subroutine ends with the RETURN instruction, the instructions following CALL are processed.
instruction(s)
CALL sub1
instruction(s)
EXIT
sub1:
instruction(s)
RETURN
When calling an external subroutine, CALL passes control to the program name that is specified after the
CALL keyword. When the external subroutine completes, you can use the RETURN instruction to return to
where you left off in the calling program.
MAIN
instruction(s)
CALL sub2
instruction(s)
…
…
...
sub2:
instruction(s)
RETURN
For more information about calling subroutines, see Chapter 6, “Writing Subroutines and Functions,” on
page 57.
Chapter 4. Controlling the Flow within a program49
Control Flow within a Program
SIGNAL Instruction
The SIGNAL instruction, like CALL, interrupts the usual flow of a program and causes control to pass to a
specified label. The label to which control passes can be before or after the SIGNAL instruction. Unlike
CALL, SIGNAL does not return to a specific instruction to resume execution. When you use SIGNAL from
within a loop, the loop automatically ends. When you use SIGNAL from an internal routine, the internal
routine does not return to its caller. For more detailed information on the SIGNAL instruction, see section
“SIGNAL” on page 164.
In the following example, if the expression is true, then the language processor goes to the label
Emergency: and skips all instructions in between.
IF expression THEN
SIGNAL Emergency
ELSE
instruction(s)
Emergency:
instruction(s)
SIGNAL is useful for testing programs or providing an emergency course of action. It should not be used
as a convenient way to move from one place in a program to another. SIGNAL does not provide a way to
return as does the CALL instruction described in the previous topic.
For more information about the SIGNAL instruction, see page 86 and section “SIGNAL” on page 164.
50
CICS TS for VSE/ESA: REXX Guide
Chapter 5. Using Functions
This chapter defines what a function is and describes how to use the built-in functions.
What is a Function?
A function is a sequence of instructions that can receive data, process it, and return a value. In REXX,
there are several kinds of functions:
v Built-in functions are built into the language processor. More about built-in functions appears later in this
chapter.
v User-written functions are those an individual user writes or an installation supplies. These can be
internal or external. An internal function is part of the current program that starts at a label. An
external function is a self-contained program or program outside the calling program. More information
about user-written functions appears in section “Writing Subroutines and Functions” on page 58.
Regardless of the kind of function, all functions return a value to the program that issued the function call.
To call a function, type the function name immediately followed by parentheses enclosing arguments to the
function (if any). There can be no space between the function name and the left parenthesis.
function(arguments)
A function call can contain up to 20 arguments separated by commas. Arguments can be:
v Constant
All functions must return values. When the function returns a value, the value replaces the function call. In
the following example, the language processor adds the value the function returns to 7 and produces the
sum.
SAY 7 + function(arguments)
A function call generally appears in an expression. Therefore a function call, like an expression, does not
usually appear in an instruction by itself.
Example of a Function
Calculations that functions represent often require many instructions. For instance, the simple calculation
for finding the highest number in a group of three numbers, might be written as follows:
/***************************** REXX **********************************/
/* This program receives three numbers as arguments and analyzes*/
/* which number is the greatest.*/
/*********************************************************************/
PARSE ARG number1, number2, number3 .
IF number1 > number2 THEN
IF number1 > number3 THEN
greatest = number1
ELSE
greatest = number3
ELSE
IF number2 > number3 THEN
greatest = number2
ELSE
greatest = number3
RETURN greatest
Figure 27. Finding a Maximum Number
Rather than writing multiple instructions every time you want to find the maximum of a group of three
numbers, you can use a built-in function that does the calculation for you and returns the maximum
number. The function is called MAX, and you can use it as follows:
MAX(number1,number2,number3,....)
To find the maximum of 45, -2, number, and 199 and put the maximum into the symbol biggest, write the
following instruction:
biggest = MAX(45,-2,number,199)
Built-In Functions
More than 50 functions are built into the language processor. The built-in functions fall into the following
categories:
v Arithmetic functions
Evaluate numbers from the argument and return a particular value.
v Comparison functions
Compare numbers, or strings, or both and return a value.
v Conversion functions
Convert one type of data representation to another type of data representation.
v Formatting functions
Manipulate the characters and spacing in strings supplied in the argument.
v String manipulating functions
Analyze a string supplied in the argument (or a variable representing a string) and return a particular
value.
v Miscellaneous functions
Do not clearly fit into any of the other categories.
The following tables briefly describe the functions in each category. For a complete description of these
functions, see Chapter 14, “Functions,” on page 171.
52
CICS TS for VSE/ESA: REXX Guide
Using Functions
Arithmetic Functions
FunctionDescription
ABSReturns the absolute value of the input number.
DIGITSReturns the current setting of NUMERIC DIGITS.
FORMReturns the current setting of NUMERIC FORM.
FUZZReturns the current setting of NUMERIC FUZZ.
MAXReturns the largest number from the list specified, formatted according to the current NUMERIC
settings.
MINReturns the smallest number from the list specified, formatted according to the current
NUMERIC settings.
RANDOMReturns a quasi-random, non-negative whole number in the range specified.
SIGNReturns a number that indicates the sign of the input number.
TRUNCReturns the integer part of the input number and optionally a specified number of decimal
places.
Comparison Functions
FunctionDescription
COMPAREReturns 0 if the two input strings are identical. Otherwise, returns the position of the first
character that does not match.
DATATYPEReturns a string indicating the input string is a particular data type, such as a number or
character.
SYMBOLReturns VAR, LIT,orBAD to indicate the state of the symbol (variable, literal, or bad).
Conversion Functions
FunctionDescription
B2XReturns the hexadecimal representation of the input binary string. (Binary to Hexadecimal).
C2DReturns the decimal representation of the input character string. (Character to Decimal).
C2XReturns the hexadecimal representation of the input character string. (Character to
Hexadecimal).
D2CReturns the character representation of the input decimal string. (Decimal to Character).
D2XReturns the hexadecimal representation of the input decimal string. (Decimal to Hexadecimal).
X2BReturns the binary representation of the input hexadecimal string. (Hexadecimal to Binary).
X2CReturns the character representation of the input hexadecimal string. (Hexadecimal to
Character).
X2DReturns the decimal representation of the input hexadecimal string. (Hexadecimal to Decimal).
Chapter 5. Using Functions53
Using Functions
Formatting Functions
FunctionDescription
CENTER or
CENTRE
COPIESReturns the specified number of concatenated copies of the input string.
FORMATReturns the input number, rounded and formatted.
JUSTIFY
LEFTReturns a string of the specified length, truncated or padded on the right as needed.
RIGHTReturns a string of the specified length, truncated or padded on the left as needed.
SPACEReturns the words in the input string with a specified number of pad characters between each
1
Returns a string of a specified length with the input string centered in it, with pad characters
added as necessary to make up the length.
Returns a specified string formatted by adding pad characters between words to justify to both
margins.
word.
String Manipulating Functions
FunctionDescription
ABBREVReturns a string indicating if one string is equal to the specified number of leading characters of
another string.
DELSTRReturns a string after deleting a specified number of characters, starting at a specified point in
the input string.
DELWORDReturns a string after deleting a specified number of words, starting at a specified word in the
input string.
1
FIND
1
INDEX
INSERTReturns a character string after inserting another input string into it from a specified character
LASTPOSReturns the starting character position of the last occurrence of one string in another.
LENGTHReturns the length of the input string.
OVERLAYReturns a string that is the target string overlaid by a second input string.
POSReturns the character position of one string in another.
REVERSEReturns a character string that is the reverse of the original.
STRIPReturns a character string after removing leading or trailing characters or both from the input
SUBSTRReturns a portion of the input string beginning at a specified character position.
SUBWORDReturns a portion of the input string starting at a specified word number.
TRANSLATEReturns a character string with each character of the input string translated to another character
VERIFYReturns a number indicating whether an input string is composed only of characters from
WORDReturns a word from an input string as a specified number indicates.
WORDINDEXReturns the character position in an input string of the first character in the specified word.
WORDLENGTHReturns the length of a specified word in the input string.
Returns the word number of the first word of a specified phrase found within the input string.
Returns the character position of the first character of a specified string found in the input string.
position.
string.
or unchanged.
another input string or returns the character position of the first unmatched character.
1. Is a non-SAA built-in function REXX/CICS provides.
54
CICS TS for VSE/ESA: REXX Guide
Using Functions
FunctionDescription
WORDPOSReturns the word number of the first word of a specified phrase in the input string.
WORDSReturns the number of words in the input string.
Miscellaneous Functions
FunctionDescription
ADDRESSReturns the name of the environment to which commands are currently being sent.
ARGReturns an argument string or information about the argument strings to a program or internal
routine.
BITANDReturns a string composed of the two input strings logically ANDed together, bit by bit.
BITORReturns a string composed of the two input strings logically ORed together, bit by bit.
BITXORReturns a string composed of the two input strings eXclusive ORed together, bit by bit.
CONDITIONReturns the condition information, such as name and status, associated with the current trapped
condition.
DATEReturns the date in the default format (dd mon yyyy) or in one of various optional formats.
ERRORTEXTReturns the error message associated with the specified error number.
EXTERNALSThis function always returns a 0.
LINESIZEReturns the width of the current output device.
QUEUEDReturns the number of lines remaining in the external data queue at the time when the function
is called.
SOURCELINEReturns either the line number of the last line in the source file or the source line a number
specifies.
TIMEReturns the local time in the default 24-hour clock format (hh:mm:ss) or in one of various
optional formats.
TRACEReturns the trace actions currently in effect.
USERID
VALUEReturns the value of a specified symbol and optionally assigns it a new value.
XRANGEReturns a string of all 1-byte codes (in ascending order) between and including specified starting
1
Returns the current user ID. This is the last user ID specified on the SETUID command, the
user ID of the calling REXX program if one program calls another, the user ID under which the
job is running, or the job name.
and ending values.
Testing Input with Built-In Functions
Some of the built-in functions provide a convenient way to test input. When a program uses input, the user
might provide input that is not valid. For instance, in the example of using comparison expressions on
page 24, the program uses a dollar amount in the following instruction.
If the program pulls only a number, the program processes that information correctly. However, if the
program pulls a number preceded by a dollar sign or pulls a word, such as nothing, the program returns
an error. To avoid getting an error, you can check the input with the DATATYPE function as follows.
IF DATATYPE(yesterday) \= 'NUM'
THEN DO
SAY 'The input amount was in the wrong format.'
EXIT
END
Chapter 5. Using Functions55
Using Functions
Other useful built-in functions to test input are WORDS, VERIFY, LENGTH, and SIGN.
Exercise - Writing a program with Built-In Functions
Write a program that checks a file name for a length of 8 characters. If the name is longer than 8
characters, the program truncates it to 8 and sends a message indicating the shortened name. Use the
built-in functions LENGTH, see page 188, and SUBSTR, see page 192.
ANSWER
/***************************** REXX *********************************/
/* This program tests the length of a file name.*/
/* If the name is longer than 8 characters, the program truncates */
/* extra characters and sends a message indicating the shortened*/
/* name.*/
/********************************************************************/
PULL name/* Gets name from input stream*/
IF LENGTH(name) > 8 THEN/* Name is longer than 8 characters*/
DO
name = SUBSTR(name,1,8)/* Shorten name to first 8 characters */
SAY 'The name you specified was too long.'
SAY name 'will be used.'
END
ELSE NOP
Figure 28. Possible Solution
56
CICS TS for VSE/ESA: REXX Guide
Chapter 6. Writing Subroutines and Functions
This chapter shows how to write subroutines and functions and discusses their differences and similarities.
What are Subroutines and Functions?
Subroutines and functions are routines made up of a sequence of instructions that can receive data,
process it, and return a value. The routines can be:
Internal
The routine is within the current program, marked by a label, and only that program uses the
routine.
External
A REXX subroutine that exists as a separate file.
In many aspects, subroutines and functions are the same. However, they are different in a few major
aspects, such as how to call them and the way they return values.
v Calling a subroutine
To call a subroutine, use the CALL instruction followed by the subroutine name (label or program
member name). You can optionally follow this with up to 20 arguments separated by commas. The
subroutine call is an entire instruction.
CALL subroutine_name argument1, argument2,...
v Calling a function
To call a function, use the function name (label or program member name) immediately followed by
parentheses that can contain arguments. There can be no space between the function name and the
left parentheses. The function call is part of an instruction, for example, an assignment instruction.
z = function(argument1, argument2,...)
v Returning a value from a subroutine
A subroutine does not have to return a value, but when it does, it sends back the value with the
RETURN instruction.
RETURN value
The calling program receives the value in the REXX special variable named RESULT.
SAY 'The answer is' RESULT
v Returning a value from a function
A function must return a value. When the function is a REXX program, the value is returned with either
the RETURN or EXIT instruction.
RETURN value
The calling program receives the value at the function call. The value replaces the function call, so that
in the following example, z = value.
z = function(argument1, argument2,...)
When to Write Subroutines Rather Than Functions
The actual instructions that make up a subroutine or a function can be identical. It is the way you want to
use them in a program that turns them into either a subroutine or a function. For example, you can call the
built-in function SUBSTR as either a function or a subroutine. This is how to call SUBSTR as a function to
shorten a word to its first eight characters:
a = SUBSTR('verylongword',1,8)/* a is set to 'verylong' */
You get the same results if you call SUBSTR as a subroutine.
CALL SUBSTR 'verylongword', 1, 8
a = RESULT/* a is set to 'verylong' */
When deciding whether to write a subroutine or a function, ask yourself the following questions:
v Is a returned value optional? If so, write a subroutine.
v Do I need a value returned as an expression within an instruction? If so, write a function.
The rest of this chapter describes how to write subroutines and functions and finally summarizes the
differences and similarities between the two.
Writing Subroutines and Functions
A subroutine is a series of instructions that a program calls to perform a specific task. The instruction that
calls the subroutine is the CALL instruction. You can use the CALL instruction several times in a program
to call the same subroutine.
When the subroutine ends, it can return control to the instruction that directly follows the subroutine call.
The instruction that returns control is the RETURN instruction.
instruction(s)
CALL sub1
instruction(s)
EXIT
sub1:
instruction(s)
RETURN
A function is a series of instructions that a program calls to perform a specific task and return a value. As
Chapter 5, “Using Functions,” on page 51 describes, a function can be built-in or user-written. Call a
user-written function the same way as a built-in function: specify the function name immediately followed
by parentheses that can contain arguments. There can be no blanks between the function name and the
left parenthesis. The parentheses can contain up to 20 arguments or no arguments at all.
function(argument1, argument2,...)
or
function()
A function requires a return value because the function call generally appears in an expression.
z = function(arguments1, argument2,...)
When the function ends, it can use the RETURN instruction to send back a value to replace the function
call.
58
CICS TS for VSE/ESA: REXX Guide
Writing Subroutines and Functions
instruction(s)
z=func1(arg1, arg2)
instruction(s)
EXIT
instruction(s)
RETURN
Both subroutines and functions can be internal (designated by a label) or external (designated by the
subroutine or function in the REXX File System/VSE Librarian sublibrary member name). The two
preceding examples illustrate an internal subroutine named sub1 and an internal function named func1.
IMPORTANT NOTE
Because internal subroutines and functions generally appear after the main part of the program,
when you have an internal subroutine or function, it is important to end the main part of the program
with the EXIT instruction.
The following illustrates an external subroutine named sub2.
MAIN
instruction(s)
CALL sub2
instruction(s)
…
…
...
sub2:
instruction(s)
RETURN
The following illustrates an external function named func2.
Chapter 6. Writing Subroutines and Functions59
Writing Subroutines and Functions
MAIN
instruction(s)
z=func2(arg1)
instruction(s)
…
…
…
exit
FUNC2
ARG var1
instruction(s)
RETURN value
When to Use Internal Versus External Subroutines or Functions
To determine whether to make a subroutine or function internal or external, you might consider factors,
such as:
v Size of the subroutine or function. Very large subroutines and functions often are external, whereas
small ones fit easily within the calling program.
v How you want to pass information. It is quicker to pass information through variables in an internal
subroutine or function. The next topic describes passing information this way.
v Whether the subroutine or function might be of value to more than one program or user. If so, an
external subroutine or function is preferable.
v Performance. For functions, the language processor searches for an internal function before it searches
for an external function.
Passing Information
A program and its internal subroutine or function can share the same variables. Therefore, you can use
commonly shared variables to pass information between caller and internal subroutine or function. You can
also use arguments to pass information to and from an internal subroutine or an internal function. External
subroutines, however, cannot share variables with the caller. To pass information to them, you need to use
arguments or some other external way, such as the data stack. (Remember: An internal function does not
need to pass arguments within the parentheses that follow the function call. However, all functions, both
internal and external, must return a value.)
Passing Information by Using Variables
When a program and its internal subroutine or function share the same variables, the value of a variable is
what was last assigned. This is regardless of whether the assignment was in the main part of the program
or in the subroutine or function.
The following example shows passing information to a subroutine. The variables number1, number2, and
answer are shared. The value of answer is assigned in the subroutine and used in the main part of the
program.
60
CICS TS for VSE/ESA: REXX Guide
Writing Subroutines and Functions
/******************************* REXX ********************************/
/* This program receives a calculated value from an internal*/
/* subroutine and uses that value in a SAY instruction.*/
/*********************************************************************/
Figure 29. Example of Passing Information in a Variable Using a Subroutine
The next example is the same, except it passes information to a function rather than a subroutine. The
subroutine includes the variable answer on the RETURN instruction. The language processor replaces the
function call with the value in answer.
/******************************* REXX ********************************/
/* This program receives a calculated value from an internal*/
/* function and uses SAY to produce that value.*/
/*********************************************************************/
number1 = 5
number2 = 10
SAY add()/* Produces 15 */
SAY answer/* Also produces 15 */
EXIT
add:
answer = number1 + number2
RETURN answer
Figure 30. Example of Passing Information in a Variable Using a Function
Using the same variables in a program and its internal subroutine or function can sometimes create
problems. In the next example, the main part of the program and the subroutine use the same control
variable, i, for their DO loops. As a result, the DO loop runs only once in the main program because the
subroutine returns to the main program with i=6.
Chapter 6. Writing Subroutines and Functions61
Writing Subroutines and Functions
/******************************* REXX ********************************/
/*NOTE: This program contains an error.*/
/* It uses a DO loop to call an internal subroutine, and the*/
/* subroutine uses a DO loop with the same control variable as the*/
/* main program. The DO loop in the main program runs only once.*/
/*********************************************************************/
number1 = 5
number2 = 10
DOi=1TO5
CALL subroutine
SAY answer/* Produces 105 */
END
EXIT
subroutine:
DOi=1TO5
answer = number1 + number2
number1 = number2
number2 = answer
END
RETURN
Figure 31. Example of a Problem Caused by Passing Information in a Variable Using a Subroutine
The next example is the same, except it passes information using a function instead of a subroutine.
/******************************* REXX ********************************/
/*NOTE: This program contains an error.*/
/* It uses a DO loop to call an internal function, and the*/
/* function uses a DO loop with the same control variable as the*/
/* main program. The DO loop in the main program runs only once.*/
/*********************************************************************/
number1 = 5
number2 = 10
DOi=1TO5
SAY add()/* Produces 105 */
END
EXIT
add:
DOi=1TO5
answer = number1 + number2
number1 = number2
number2 = answer
END
RETURN answer
Figure 32. Example of a Problem Caused by Passing Information in a Variable Using a Function
To avoid this kind of problem in an internal subroutine or function, you can use:
v The PROCEDURE instruction, as the next topic describes.
v Different variable names in a subroutine or function than in the main part of the program. For a
subroutine, you can pass arguments on the CALL instruction; section “Passing Information by Using
Arguments” on page 64 describes this.
Protecting Variables with the PROCEDURE Instruction: When you use the PROCEDURE instruction
immediately after the subroutine or function label, all variables in the subroutine or function become local
to the subroutine or function; they are shielded from the main part of the program. You can also use the
PROCEDURE EXPOSE instruction to protect all but a few specified variables.
62
CICS TS for VSE/ESA: REXX Guide
Writing Subroutines and Functions
The following examples show how results differ when a subroutine or function uses or does not use
PROCEDURE.
/******************************* REXX ********************************/
/* This program uses a PROCEDURE instruction to protect the*/
/* variables within its subroutine.*/
/*********************************************************************/
Figure 33. Example of Subroutine Using the PROCEDURE Instruction
/******************************* REXX ********************************/
/* This program does not use a PROCEDURE instruction to protect the */
/* variables within its subroutine.*/
/*********************************************************************/
Figure 34. Example of Subroutine without the PROCEDURE Instruction
The next two examples are the same, except they use functions rather than subroutines.
/******************************* REXX ********************************/
/* This program uses a PROCEDURE instruction to protect the*/
/* variables within its function.*/
/*********************************************************************/
Figure 35. Example of Function Using the PROCEDURE Instruction
Chapter 6. Writing Subroutines and Functions63
Writing Subroutines and Functions
/******************************* REXX ********************************/
/* This program does not use a PROCEDURE instruction to protect the */
/* variables within its function.*/
/*********************************************************************/
Figure 36. Example of Function without the PROCEDURE Instruction
Exposing Variables with PROCEDURE EXPOSE: To protect all but specific variables, use the EXPOSE
option with the PROCEDURE instruction, followed by the variables that are to remain exposed to the
subroutine or function.
The next example uses PROCEDURE EXPOSE in a subroutine.
/******************************* REXX ********************************/
/* This program uses a PROCEDURE instruction with the EXPOSE option */
/* to expose one variable, number1, in its subroutine. The other*/
/* variable, number2, is set to null and the SAY instruction*/
/* produces this name in uppercase.*/
/*********************************************************************/
Figure 37. Example Using PROCEDURE EXPOSE in Subroutine
The next example is the same except PROCEDURE EXPOSE is in a function instead of a subroutine.
/******************************* REXX ********************************/
/* This program uses a PROCEDURE instruction with the EXPOSE option */
/* to expose one variable, number1, in its function.*/
/*********************************************************************/
Figure 38. Example Using PROCEDURE EXPOSE in a Function
For more information about the PROCEDURE instruction, see section “PROCEDURE” on page 155.
Passing Information by Using Arguments
A way to pass information to either internal or external subroutines or functions is through arguments.
When calling a subroutine, you can pass up to 20 arguments separated by commas on the CALL
instruction as follows:
In a function call, you can pass up to 20 arguments separated by commas.
function(argument1,argument2,argument3,...)
Using the ARG Instruction: A subroutine or function can receive the arguments with the ARG
instruction. In the ARG instruction, commas also separate arguments.
ARG arg1, arg2, arg3, ...
The names of the arguments that are passed do not have to be the same as those on the ARG instruction
because information is passed by position rather than by argument name. The first argument sent is the
first argument received and so forth. You can also set up a template in the CALL instruction or function
call. The language processor then uses this template in the corresponding ARG instruction. For information
about parsing with templates, see section “Parsing Data” on page 73.
In the following example, the main routine sends information to a subroutine that computes the perimeter
of a rectangle. The subroutine returns a value in the variable perim by specifying the value in the RETURN
instruction. The main program receives the value in the special variable RESULT.
Figure 40. Example of Passing Arguments on the Call to an Internal Routine
In the two preceding examples, notice the positional relationships between long and length, and wide and
width. Also notice how information is received from variable perim. Both programs include perim on a
RETURN instruction. For the program with a subroutine, the language processor assigns the value in
perim to the special variable RESULT. For the program using a function, the language processor replaces
the function call perimeter(long,wide) with the value in perim.
Using the ARG Built-in Function: Another way for a subroutine or function to receive arguments is with
the ARG built-in function. This function returns the value of a particular argument. A number represents the
argument position.
For instance, in the previous example, instead of the ARG instruction:
ARG length, width
you can use the ARG function as follows:
length = ARG(1)/* puts the first argument into length */
width = ARG(2)/* puts the second argument into width */
For more information about the ARG function see section “ARG” on page 134.
Receiving Information from a Subroutine or Function
Although a subroutine or function can receive up to 20 arguments, it can specify only one expression on
the RETURN instruction. That expression can be:
v A number
RETURN 55
v One or more variables whose values are substituted (or their names if no values have been assigned).
RETURN value1 value2 value3
v A literal string
RETURN 'Work complete.'
v An arithmetic, comparison, or logical expression whose value is substituted.
RETURN 5 * number
66
CICS TS for VSE/ESA: REXX Guide
Writing Subroutines and Functions
Exercise - Writing an Internal and an External Subroutine
Write a program that plays a simulated coin toss game and produces the accumulated scores.
There should be four possible inputs:
v 'HEADS'
v 'TAILS'
v '' (Null—to quit the game)
v None of these three (incorrect response).
Write an internal subroutine without arguments to check for valid input. Send valid input to an external
subroutine that uses the RANDOM built-in function to generate random outcomes. Assume HEADS = 0
and TAILS = 1, and use RANDOM as follows:
RANDOM(0,1)
Compare the valid input with the value from RANDOM. If they are the same, the user wins one point; if
they are different, the computer wins one point. Return the result to the main program where results are
tallied.
ANSWER
/***************************** REXX ********************************/
/* This program plays a simulated coin toss game.*/
/* The input can be heads, tails, or null ("") to quit the game.*/
/* First an internal subroutine checks input for validity.*/
/* An external subroutine uses the RANDOM built-in function to*/
/* obtain a simulation of a throw of dice and compares the user*/
/* input to the random outcome. The main program receives*/
/* notification of who won the round. It maintains and produces*/
/* scores after each round.*/
/*******************************************************************/
PULL flip/* Gets "HEADS", "TAILS", or ""*/
computer = 0; user = 0/* Initializes scores to zero*/
CALL check/* Calls internal subroutine, check */
DO FOREVER
CALL throw/* Calls external subroutine, throw */
/* from input stream.*/
IF RESULT = 'machine' THEN /* The computer won*/
computer = computer + 1/* Increase the computer score*/
ELSE/* The user won*/
user = user + 1/* Increase the user score*/
SAY 'Computer score = ' computer'Your score = ' user
PULL flip
CALL check/* Call internal subroutine, check */
END
EXIT
Figure 41. Possible Solution (Main Program)
Chapter 6. Writing Subroutines and Functions67
Writing Subroutines and Functions
/*************************** REXX ************************************/
/* This internal subroutine checks for valid input of "HEADS",*/
/* "TAILS", or "" (to quit). If the input is anything else, the*/
/* subroutine says the input is not valid and gets the next input. */
/* The subroutine keeps repeating until the input is valid.*/
/* Commonly used variables return information to the main program*/
/*********************************************************************/
check:
DO UNTIL outcome = 'correct'
SELECT
WHEN flip = 'HEADS' THEN
outcome = 'correct'
WHEN flip = 'TAILS' THEN
outcome = 'correct'
WHEN flip = '' THEN
EXIT
OTHERWISE
outcome = 'incorrect'
PULL flip
END
END
RETURN
Figure 42. Possible Solution (Internal Subroutine Named CHECK)
/******************************* REXX ********************************/
/* This external subroutine receives the valid input, analyzes it, */
/* gets a random "flip" from the computer, and compares the two.*/
/* If they are the same, the user wins. If they are different,*/
/* the computer wins. The routine returns the outcome to the*/
/* calling program.*/
/*********************************************************************/
throw:
ARG input
IF input = 'HEADS' THEN
userthrow = 0/* heads = 0 */
ELSE
userthrow = 1/* tails = 1 */
compthrow = RANDOM(0,1)/* choose a random number*/
IF compthrow = userthrow THEN
outcome = 'human'/* user chose correctly*/
ELSE
outcome = 'machine'/* user chose incorrectly*/
RETURN outcome
Figure 43. Possible Solution (External Subroutine named THROW)
/* between 0 and 1*/
Exercise - Writing a Function
Write a function named AVG that receives a list of numbers separated by blanks and computes their
average. The final answer can be a decimal number. To call this function, you would use:
AVG(number1 number2 number3...)
Use the WORDS (see section “WORDS” on page 198) and WORD (see section “WORD” on page 197)
built-in functions.
ANSWER
68
CICS TS for VSE/ESA: REXX Guide
Writing Subroutines and Functions
/******************************* REXX ********************************/
/* This function receives a list of numbers, adds them, computes*/
/* their average, and returns the average to the calling program.*/
/*********************************************************************/
ARG numlist/* receive the numbers in a single variable */
sum = 0/* initialize sum to zero */
DOn=1TOWORDS(numlist)/* Repeat for as many times as there */
number = WORD(numlist,n)/* Word #n goes to number */
sum = sum + number/* Sum increases by number */
END
average = sum / WORDS(numlist)/* Compute the average*/
RETURN average
Figure 44. Possible Solution
/* are numbers*/
Chapter 6. Writing Subroutines and Functions69
Writing Subroutines and Functions
Subroutines and Functions—Similarities and Differences
The following tables highlight similarities and differences between subroutines and functions:
Similarities between Subroutines and Functions
Can be internal or external.
Internal
– Can pass information by using common variables
– Can protect variables with the PROCEDURE instruction
– Can pass information by using arguments.
External
– Must pass information by using arguments
– Can use the ARG instruction or the ARG built-in function to receive arguments.
Uses the RETURN instruction to return to the caller.
Differences between Subroutines and Functions
SubroutinesFunctions
CallingCall by using the CALL instruction, followed
by the subroutine name and, optionally, up to
20 arguments.
Returning a ValueMight return a value to the caller. If you
include a value on the RETURN instruction,
the language processor assigns this value to
the REXX special variable RESULT.
Call by specifying the function's name,
immediately followed by parentheses that
optionally contain up to 20 arguments.
Must return a value. Specify a value on the
RETURN instruction; the language processor
replaces the function call with this value.
70
CICS TS for VSE/ESA: REXX Guide
Chapter 7. Manipulating Data
This chapter describes how to use compound variables and stems and explains parsing.
Using Compound Variables and Stems
Sometimes it is useful to store groups of related data in a way that makes data retrieval easy. For
example, you could store a list of employee names in an array and retrieve them by number. An array is
an arrangement of elements in one or more dimensions, identified by a single name. An array called
employee could contain names as follows:
EMPLOYEE
(1) Adams, Joe
(2) Crandall, Amy
(3) Devon, David
(4) Garrison, Donna
(5) Leone, Mary
(6) Sebastian, Isaac
In some computer languages, you use the number of the element to access an element in an array. For
example, employee(1) would retrieve Adams, Joe. In REXX, you use compound variables.
What Is a Compound Variable?
You can use compound variables to create an array or a list of variables in REXX. A compound variable,
for example: employee.1, consists of a stem and a tail. A stem is a symbol with a period at the end. Here
are some examples of stems:
FRED.
Array.
employee.
A tail is similar to a subscript. It follows the stem and consists of additional parts of the name that can be
constant symbols (as in employee.1), simple symbols (as in employee.n), or null. Thus, in REXX,
subscripts need not necessarily be numeric. A compound variable contains at least one period with
characters on both sides of it. Here are some more examples of compound variables:
FRED.5
Array.Row.Col
employee.name.phone
You cannot do any substitution for the name of the stem but you can use substitution for the tail. For
example:
employee.7='Amy Martin'
new=7
employee.new='May Davis'
say employee.7/* Produces: May Davis */
As with other REXX variables, if you have not previously assigned a value to a variable in a tail, it takes
on the value of its own name in uppercase.
first = 'Fred'
last = 'Higgins'
name = first.last/* NAME is assigned FIRST.Higgins*/
SAY name.first.middle.last /* Produces NAME.Fred.MIDDLE.Higgins*/
/* The value FIRST appears because the*/
/* variable FIRST is a stem, which*/
/* cannot change.*/
You can use a DO loop to initialize a group of compound variables and set up an array.
After the names are in the group of compound variables, you can easily access a name by its number or
by a variable that represents its number.
name = 3
SAY employee.name/* Produces 'Devon, David' */
For more information about compound variables, see section “Compound Symbols” on page 122.
Using Stems
When working with compound variables, it is often useful to initialize an entire collection of variables to the
same value. You can do this easily by using an assignment that includes a stem. For example, number.=0
initializes all array elements in the array named number. to 0.
You can change the values of all compound variables in an array the same way. For example, to change
all employee names to Nobody, use the following assignment instruction:
employee. = 'Nobody'
As a result, all compound variables beginning with the stem employee., previously assigned or not, have
the value Nobody. After a stem assignment, you can assign individual compound variables new values.
employee.='Nobody'
SAY employee.5/* Produces 'Nobody' */
SAY employee.10/* Produces 'Nobody' */
SAY employee.oldest/* Produces 'Nobody' */
employee.new = 'Clark, Evans'
SAY employee.new/* Produces 'Clark, Evans' */
You can use stems with the EXECIO and RFS commands when reading to and writing from a file. See
section “EXECIO” on page 344 for information about EXECIO. See section “RFS” on page 363 for
information about RFS. RFS is the preferred I/O method under CICS.
Exercises - Using Compound Variables and Stems
1. After these assignment instructions, what do the following SAY instructions produce?
a = 3/* assigns '3' to variable 'A' */
d = 4/*'4' to'D' */
c = 'last'/*'last' to'C' */
a.d = 2/*'2' to'A.4' */
a.c = 5/*'5' to'A.last' */
z.a.d = 'cv3d' /*'cv3d' to'Z.3.4' */
a.SAY a
b.SAY D
c.SAY c
d.SAY a.a
e.SAY A.D
f.SAY d.c
g.SAY c.a
72
CICS TS for VSE/ESA: REXX Guide
h.SAY a.first
i.SAY z.a.4
2. After these assignment instructions, what output do the SAY instructions produce?
Parsing is separating data and assigning parts of it into one or more variables. Parsing can assign each
word in the data into a variable or can divide the data into smaller parts. Parsing is also useful to format
data into columns.
The variables to receive data are named in a template. A template is a model telling how to split the data.
It can be as simple as a list of variables to receive data. More complex templates can contain patterns;
section “Parsing with Patterns” on page 75 explains patterns.
Parsing Instructions
The REXX parsing instructions are PULL, ARG, and PARSE. (PARSE has several variants.)
PULL Instruction
Other chapters show PULL as an instruction that reads input and assigns it to one or more variables. If the
program stack contains information, the PULL instruction takes information from the program stack. When
the program stack is empty, PULL takes information from the current terminal input device. See section
“Getting Information from the Program Stack or Terminal Input Device” on page 14 for information about
the data stack.
/* This REXX program parses the string "Knowledge is power."*/
You can include the optional keyword UPPER on any variant of the PARSE instruction.This causes the
language processor to uppercase character information before assigning it into variables. For example,
using PARSE UPPER PULL... gives the same result as using PULL.
ARG Instruction
The ARG instruction takes information passed as arguments to a program, function, or subroutine, and
puts it into one or more variables. To pass the three arguments Knowledge is power. to a REXX program
named sample:
1. Call the program and pass the arguments as a string following the exec name:
REXX sample Knowledge is power.
2. Use the ARG instruction to receive the three arguments into variables.
PARSE UPPER ARG has the same result as ARG. It uppercases character information before assigning it
into variables.
PARSE VALUE ... WITH Instruction
The PARSE VALUE...WITH instruction parses a specified expression, such as a literal string, into one or
more variables whose names follow the WITH subkeyword.
PARSE VALUE 'Knowledge is power.' WITH word1 word2 word3
PARSE VALUE does not uppercase character information before assigning it into variables. If you want
uppercase translation, use PARSE UPPER VALUE. You could use a variable instead of a string in PARSE
VALUE (you would first assign the variable the value):
string='Knowledge is power.'
PARSE VALUE string WITH word1 word2 word3
PARSE VAR does not uppercase character information before assigning it into variables. If you want
uppercase translation, use PARSE UPPER VAR.
More about Parsing into Words
In the preceding examples, the number of words in the data to parse is always the same as the number of
variables in the template. Parsing always assigns new values to all variables named in the template. If
there are more variable names than words in the data to parse, the leftover variables receive null (empty)
values. If there are more words in the data to parse than variable names in the template, each variable
gets one word of data in sequence except the last variable, which gets the remainder of the data.
In the next example, there are more variable names in the template than words of data; the leftover
variable receives a null value.
PARSE VALUE 'Extra variables' WITH word1 word2 word3
In the next example there are more words in the data than variable names in the template; the last
variable gets the remainder of the data. The last variable name can contain several words and possibly
leading and trailing blanks.
PARSE VALUE 'More wordsin data' WITH var1 var2 var3
Parsing into words generally removes leading and trailing blanks from each word before putting it into a
variable. However, when putting data into the last variable, parsing removes one word-separator blank but
retains any extra leading or trailing blanks. There are two leading blanks before words. Parsing removes
both the word-separator blank and the extra leading blank before putting 'words' into var2. There are four
leading blanks before in. Because var3 is the last variable, parsing removes the word-separator blank but
keeps the extra leading blanks. Thus, var3 receives ' in data' (with three leading blanks).
A period in a template acts as a placeholder. It receives no data. You can use a period as a "dummy
variable" within a group of variables or at the end of a template to collect unwanted information.
string='Example of using placeholders to discard junk'
PARSE VAR string var1 . var2 var3 .
/* var1 contains 'Example'*/
/* var2 contains 'using'*/
/* var3 contains 'placeholders' */
/* The periods collect the words 'of' and 'to discard junk' */
For more information about parsing instructions, see section “PARSE” on page 152.
Parsing with Patterns
The simplest template is a group of blank-separated variable names. This parses data into blank-delimited
words. The preceding examples all use this kind of template. Templates can also contain patterns. A
pattern can be a string, a number, or a variable representing either of these.
Chapter 7. Manipulating Data75
Manipulating Data
String
If you use a string in a template, parsing checks the input data for a matching string. When assigning data
into variables, parsing generally skips over the part of the input string that matches the string in the
template.
phrase = 'To be, or not to be?'/* phrase containing comma*/
PARSE VAR phrase part1 ',' part2/* template containing comma */
/* part1 contains 'To be'*/
/* part2 contains ' or not to be?' */
/*as string separator*/
In this example, notice that the comma is not included with 'To be' because the comma is the string
separator. (Notice also that part2 contains a value that begins with a blank. Parsing splits the input string
at the matching text. It puts data up to the start of the match in one variable and data starting after the
match in the next variable.
Variable
When you do not know in advance what string to specify as separator in a template, you can use a
variable enclosed in parentheses.
separator = ','
phrase = 'To be, or not to be?'
PARSE VAR phrase part1 (separator) part2
/* part1 contains 'To be'*/
/* part2 contains ' or not to be?' */
Again, in this example, notice that the comma is not included with 'To be' because the comma is the string
separator.
Number
You can use numbers in a template to indicate the column at which to separate data. An unsigned integer
indicates an absolute column position. A signed integer indicates a relative column position.
An unsigned integer or an integer with the prefix of an equal sign (=) separates the data according to
absolute column position. The first segment starts at column 1 and goes up to, but does not include, the
information in the column number specified. Subsequent segments start at the column numbers specified.
quote = 'Ignorance is bliss.'
PARSE VAR quote part1 5 part2
The following code has the same result:
quote = 'Ignorance is bliss.'
PARSE VAR quote 1 part1 =5 part2
Specifying the numeric pattern 1 is optional. If you do not use a numeric pattern to indicate a starting point
for parsing, this defaults to 1. The example also shows that the numeric pattern 5 is the same as =5.
When each variable in a template has column numbers both before and after it, the two numbers indicate
the beginning and the end of the data for the variable.
Thus, you could use numeric patterns to skip over part of the data:
quote = 'Ignorance is bliss.'
PARSE VAR quote 2 var1 35var2 78var3 var 4 var5
SAY var1||var2||var3 var4 var5 /* || means concatenate */
....+....1....+....2
/* Says: grace is bliss. */
A signed integer in a template separates the data according to relative column position. The plus or minus
sign indicates movement right or left, respectively, from the starting position. In the next example,
remember that part1 starts at column 1 (by default because there is no number to indicate a starting
point).
+5 part2 means parsing puts into part2 data starting in column 6 (1+5=6). +5 part3 means data put into
part3 starts with column 11 (6+5=11), and so on. The use of the minus sign is similar to the use of the
plus sign. It identifies a relative position in the data string. The minus sign “backs up” (moves to the left) in
the data string.
In this example, part1 receives characters starting at column 1 (by default). +10 part2 receives characters
starting in column 11 (1+10=11). +3 part3 receives characters starting in column 14 (11+3=14). -3 part4
receives characters starting in column 11 (14-3=11).
To provide more flexibility, you can define and use variable numeric patterns in a parsing instruction. To do
this, first define the variable as an unsigned integer before the parsing instruction. Then, in the parsing
instruction, enclose the variable in parentheses and specify one of the following before the left parenthesis:
v A plus sign (+) to indicate column movement to the right
v A minus sign (-) to indicate column movement to the left
v An equal sign (=) to indicate an absolute column position.
Chapter 7. Manipulating Data77
Manipulating Data
(Without +, −,or= before the left parenthesis, the language processor would consider the variable to be a
string pattern.) The following example uses the variable numeric pattern movex.
For more information about parsing, see Chapter 15, “Parsing,” on page 203.
Parsing Multiple Strings as Arguments
When passing arguments to a function or a subroutine, you can specify multiple strings to be parsed. The
ARG, PARSE ARG, and PARSE UPPER ARG instructions parse arguments. These are the only parsing
instructions that work on multiple strings.
To pass multiple strings, use commas to separate adjacent strings.
The next example passes three arguments to an internal subroutine.
The first argument is two words "String One" to parse into three variable names, word1, word2, and word3.
The third variable, word3, is set to null because there is no third word. The second and third arguments are
parsed entirely into variable names string2 and string3.
For more information about parsing multiple arguments that have been passed to a program or subroutine,
see section “Parsing Multiple Strings” on page 211.
Exercise - Practice with Parsing
What are the results of the following parsing examples?
quote = 'Experience is the best teacher.'
1.
PARSE VAR quote word1 word2 word3
a) word1 =
b) word2 =
c) word3 =
quote = 'Experience is the best teacher.'
2.
PARSE VAR quote word1 word2 word3 word4 word5 word6
a) word1 =
b) word2 =
c) word3 =
d) word4 =
e) word5 =
f) word6 =
PARSE VALUE 'Experience is the best teacher.' WITH word1 word2 . . word3
3.
a) word1 =
b) word2 =
78
CICS TS for VSE/ESA: REXX Guide
Loading...
+ hidden pages
You need points to download manuals.
1 point = 1 manual.
You can buy points or you can get point for every manual you upload.