Professional Documents
Culture Documents
REXX Programming
For TSO and CMS
Dan ODea
December 30, 2004
Table of Contents
Introduction . . . . . .
Goals of the course. .
Uses of REXX; what is
a REXX program?. . .
CLIST vs. REXX . . . .
How does TSO know the
difference?. . . . .
What is REXX?. . . . .
3
4
5
6
7
8
Getting Started
10
Allocating REXX files. 10
Connecting your execs
to your session. . . 13
Get on with it!
General syntax . . .
REXX keywords. . . .
Variables and labels
Literals . . . . . .
SAY instruction. . .
REXXTRY exec . . . .
.
.
.
.
.
.
14
14
17
18
20
22
22
23
23
25
27
28
29
30
30
32
Data handling
35
PARSE instruction. . . 35
User interactions. . . 38
PARSE EXTERNAL . . . . 38
References,
Appendix A,
Appendix B,
Appendix C,
Appendix D:
Error handling
Interactive debugger
Trace options . . . .
EXECUTIL. . . . . . .
Error traps . . . . .
Examples. . . . . . .
.
.
.
.
.
.
.
.
.
.
40
40
41
42
43
46
Arithmetic
49
Arithmetic operations . . 49
Precision . . . . . . . . 50
Control Structures
51
SELECT instruction. . . . 51
Looping . . . . . . . . . 53
Talking to the environment 57
What environment? . . . . 59
Edit macros . . . . . . . 61
Modular programming in REXX
Functions and subroutines
Some built-in functions .
User-written functions
Internal. . . . . . . .
External. . . . . . . .
62
62
63
67
68
71
74
TSO Interactions
Messages and OUTTRAP.
The stack . . . . . .
NEWSTACK and DELSTACK
TSO and the stack . .
77
77
79
81
83
.
.
.
.
.
.
.
.
File I/O
86
Reading . . . . . . . . . 87
Writing . . . . . . . . . 88
Updating. . . . . . . . . 89
Page 90
page 92: examples of REXX code
page 96: answers to questions
Page 106: solutions to exercises
complete list of REXX built-in functions (with
separate page numbers and TOC).
2
Introduction
There are two basic types of programming languages: compiled and interpreted. The
first kind, such as COBOL or Assembler, must pass through two steps. The first step
converts text (your source code) into object code, something the machine can understand.
The second step converts the object code into an executable module. Only then can you
see if your program runs.
TSO CLISTs and the original BASIC language are interpreted. An interpreted
language runs the source code directly, one line at a time.
You can do a lot with CLISTs, but they have some annoying quirks. There are also
some things you just cant do in a CLIST. On the other hand, COBOL works with
machine and data files and doesnt have user friendly interfaces. Assembler, while
extremely powerful, is somewhat obtuse.
What we programmers like to see is a language thats user-friendly, so we can quickly
write workable programs. It should be easy to read, so nearly anyone can write a tool or
debug an existing one. It must be fully functional, so no additional programming is
needed. Finally, it must be portable so you can run it anywhere. There is such a
language; its called REXX.
To program in REXX in zOS, you need three things.
Understand how the TSO stack works and how to use it.
Create complete applications. In some cases the application might be better done
in COBOL or assembler, but in most cases the REXX version is efficient enough
to leave as-is.
REXX execs:
2. Lots of &&&&&.
2. English-like syntax.
3. Obscure at times.
5. Bad at mathematics.
5. Good at mathematics.
6. Unique to TSO.
CLIST
PROC 1 DSN
ALLOCATE FILE(A) DA(&DSN)
REXX
/* REXX program */
Arg DSN
ALLOCATE FILE(A) DA(DSN)
Trivia
CLIST is an acronym for Command LIST.
REXX is an acronym for Restructured EXtended eXecutor.
REXXs many powerful built-in functions allow for fewer instructions to create
certain data structures.
You can code compound variables (arrays) and matrixes (like COBOL
OCCURS clauses) in REXX.
Questions
What language is this program written in?
10
10
11
C
U
S
V
ISPF Library:
Project . .
Group . . .
Type . . . .
Other Partitioned, Sequential or VSAM Data Set:
Data Set Name . . . my.rexx.exec
Volume Serial . . .
(If not cataloged, required for option "C")
Data Set Password
. .
11
12
. . . : ISDODEA.MY.REXX.EXEC
Management class
Storage class .
Volume serial .
Device type . .
Data class . . .
Space units . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. tracks
. 5
1
. 10
. FB
. 255
.
: PDS
Expiration date . . .
Enter "/" to select option
Allocate Multiple Volumes
Fill in as shown:
Five tracks are enough for this class. My own current REXX PDS is only two
cylinders.
Ten directory blocks is forty members or so.
RECFM = VB, LRECL = 255.
12
13
Now save the program. Congratulations, youve written your first REXX exec!
13
14
1.
2.
3.
4.
5.
6.
*/
REXX does not have line numbers per se. The REXX interpreter keeps track of line
numbers, which may be displayed when an error message occurs. When editing a REXX
exec, your edit profile should be NUMBER OFF.
Remember, a REXX exec must have the word REXX somewhere on Line 1. It
doesnt have to be first, although that is a typical convention.
Comments in REXX begin with a /*, and must end with a */. REXX does not
close the comment until it finds a */. For example, this is a long comment line:
The answer is 3
on the terminal.
Line 6 ends the program.
14
15
EXIT 10
passes a 10 back to the calling program.
You can test this with the WHEN TSO command, or as a variable.
Questions
What does a REXX exec always start with?
/*
X =
Y =
Z =
Say
REXX */
10
20
Y - X
The answer is Z
15
16
Say Hello
This is a box comment. Note each line is not closed. Only the first and last lines have
slashes; the first slash starts the comment, and the last finishes it.
Say,
Next?
You can also have multiple statements on a line by separating each statement with a
semicolon:
DataSetName
datasetNAME
DATASETNAME
However, text enclosed in quotes remains intact. For example:
17
REXX Keywords
Keywords: SAY, DO, IF, EXIT
Literals: Moe, Larry, Curley, 1234, 9876
Variables: A, XYZ, DSN, MyFileName
Assignments: A = B
Command: ALLOCATE, DELETE, LOGOFF
A literal is itself. It doesnt stand for anything. Unassigned variables are considered
literals. For example this program produces two lines of output, shown below.
/* REXX */
Say Curley
Curley = 2
Say Curley
READY
<rexx name>
Curley
2
READY
17
18
REXX Variables
Variables contain information. They stand for another thing. For example, in this
statement
A + B
A and B are variables containing numbers (you cant add A and B).
Anything starting with a word REXX does not understand is taken to be a TSO
command and given to TSO.
Assignments are understood by REXX and are not sent to TSO.
SAY is understood by REXX, so REXX carries out the instruction.
DELETE is not understood by REXX and is sent to TSO for processing.
To send something directly to TSO, put quotes around it and put it first on the line (or
after an IF). For example, these REXX statements do the same thing:
REXX Labels
Labels name a subroutine, user-written function, target of a transfer-of-control
instruction, or error trap. The label must be the first thing on a line, followed by a colon.
The label can be on a line by itself.
COMPUTE:
C = A + B
COMPUTE:
C = A + B
18
19
Questions
Do these use the correct syntax? If not, whats wrong with them?
True or false: the EXIT statement must always be the very last line in the program.
BARK Hello
Exercise #1
Write an exec to execute the following two TSO commands:
TIME
SEND Sample REXX U(*)
Include the comment,
19
20
LISTCAT
The null string is represented by or .
The maximum size of a literal is 250 characters.
Numeric literals may have quotes, unlike COBOL. These are all valid:
A = 1
B = 2
C = A + B + 3
C contains 6.
If theres an E in the number, its scientific notation. For example, 2E+4 is 2 times
10 to the fourth power, or 20,000.
Literals can be hex strings. Hex characters must be in quotes, with an X after the
last quote. For example,
Say F1F2F3X
produces 123 as its output.
20
21
A Pitfall
Anytime you put an X after a string, REXX takes it as a hex string. Look at this
example.
X = 5 + 6
Say The answer is X
Say The answer is X
Literal Questions
What does this program do?
/* REXX TRY ME
Say Greeting
*/
Exercise #2
Write an exec to display these three lines:
3 + 1 is 4
3 + 1 is 4
OBrien
21
22
Say 5 - 3
What does this display on the terminal?
SAY 5 3
What does this display on the terminal?
SAY 5 3
22
23
The Variable
Variables:
Contain information.
23
24
24
25
1_time_only
ProGraMmer_NamE
Last_Name
input-data
Say
/* REXX exec */
MESSAGE = MESSAGE
SAY MESSAGE
EXIT
Exercise #3
Write an exec to:
25
26
Concatenation
To display or connect variables you can just put them next to each other. If they are
separated by any number of spaces, they are connected by a single space. For example:
Say Hi
- or -
Fred
Greeting = Hi
Person = Fred
Say Greeting Person
Salary = 10000
Person = Barney
Say SalaryPerson
SalaryPerson is a separate variable from Salary and Person.
How do we separate variables but be able to concatenate them together?
26
27
More on Concatenation
The concatenation operator is two vertical bars: ||. Here are some examples of
concatenation, both with and without the bars:
1.Var1 = Up
2.Var2 = Away
3.Var3 = per
4.Var4 = son
5.Say Var1 Var1 and Var2
6.Say Var1 Var1 and Var2
7.Say Var1 Var1 and Var2
8.Say Var2 Var3 Var4
9.Say Var2 Var3||Var4
10. Say Var2 Var1||Var3 Var4
The results of the Say statements are:
The concatenation operator is needed only when concatenating two variables. There
is no need to use it when concatenating literals with variables.
Say Elle
||
Woody
When this prints, how many spaces are between Elle and Woody?
Say Elle
Woody
27
28
Conditional Operators
As in all programming languages, REXX has an IF statement. The statement follows a
standard format.
If expression
Then one instruction
Else one instruction
The statement can also be put on one line.
The REXX verb NOP (No OPeration) tells REXX to do nothing. Here is an example
of a complete IF statement:
If Marital_Status = MARRIED
Then NOP
Else Say Say, I was wondering....
A complete list of comparison operators is found in Appendix D. However, here are a
few examples.
>
<
=
==
<>
Greater than
Less than
Numerically equivalent, e. g. 001 = 1.
Strings are equivalent when padded with
blanks (e. g. New York = New York
).
Equal in every way. For example:
001 == 001
True
001 == 1
False
New York == New York
False
Not equal
You must use the symbols. For example, you cannot code
If A greater than B
28
29
If A = B Then Do
A = B 1
Say A was equal to B, but now its not.
End
If A = B
Then Do
Say A is equal to B.
Say B is equal to A.
End
Else Say A is not equal to B.
DO groups are quite flexible, may be nested, and can be run multiple times. Well
talk more about DO groups later in the course.
29
30
Inexact Comparisons
1000.0001 is pretty close to 1000. In normal mathematics, the two are not equal.
With the REXX instruction NUMERIC FUZZ, they can be equal. The syntax of the
FUZZ instruction is:
Numeric Fuzz 1
*/
9 significant digits is the default. REXX normally looks at all significant digits.
FUZZ tells REXX to ignore the least significant digit or digits. Here are some examples:
*/
Exercise #4
Write an exec to:
30
31
Boolean Operators
Boolean operators allow more than one compare on one statement. The standard
operators are:
Say 1 = 2
displays 0 because the comparison is false.
Be careful!
A = B = 2
checks to see if B = 2. If it is, it produces a 1, so A is set to 1. If its not, A is set to 0.
The value in B is not affected.
31
32
A Specific Example
Heres something you wouldnt do, but it shows how REXX works.
ABC = CDE
REXX processes it as:
32
33
Exercise #5
Write an exec to execute the LISTCAT ENTRY(dsn) command. Pass the DSN using
ARG. Make sure it works on your own datasets and datasets not belonging to you.
33
34
35
Exercise #6
Write an exec to accept three pieces of information and display them in reverse order
of entry. If more than three are entered, display an error message.
Exercise #7
Write an exec to examine information passed to it. Perform the following checks.
35
36
The template is a mask or filter through which data must pass before being distributed
to the variables. The template may be:
All forms of PARSE place the information into variables. They all work the same
way, the only difference being the origin of the data. All the variables in the template are
changed.
PARSE is sometimes used in short forms:
36
37
Literals in a Template
All the templates weve seen so far were just a list of variables. You can tell REXX
how to distribute information into variables. That gives you more control over how
information is passed to the exec. Consider this:
ONE = HOW;
TWO = ARE;
THREE = YOU TODAY
REST = HOT ISNT IT?
Anything before the literal is stored into the leading variable(s). Anything after the
literal goes into the trailing variable(s).
You can use a variable containing a delimiter. Consider this:
ONE = THERE;
TWO = ARE;
THREE = TWO AND 1
REST = 2 DOZEN EGGS.
37
38
Question
If you execute the exec with the command shown, what are the results?
Exercise #8
Write an exec to accept two arguments: the day of the week and the weather. If the
day is Friday and the weather is rainy, display Head for office!. If the day is Friday
and the weather is not rainy, display Go Rock Cats!.
38
39
39
40
Question
You want the user to enter three, and only three, items of information separated by
spaces. What does your PULL look like?
Exercise #9
Write an exec to ask for three, and only three, words and display them in reversed
order.
Exercise #10
Write a front end exec for the DELETE command. Have it ask, Are you sure?. If
the dataset name is junk.data, dont ask.
Exercise #11
Write an exec to compute the percent increase of one number over another. Ask for
the two amounts from the terminal. The formula is:
% increase = 100 * ((new old) / old)
Imagine your old salary was $34,000 and your new salary is $80,000. You would
calculate your percent increase as:
100 * ((80000 34000) / 34000)
Exercise #12
Ask for the weather and the day of the week from the terminal. If its raining, ask
how many inches are expected.
If its Friday and sunny or cloudy, display Head for the golf course!
If its Saturday and less than .5 inches, display Fishing pole, please!
40
41
If you just press ENTER after PA1 or ATTN, the exec continues.
You can trace the execution of your exec. There are many options to trace; these are
described on the next page.
You can code most trace options (including EXECUTIL statements) inside a REXX
exec. Youd probably remove them when the exec has been released to the general
public.
Main programs and their subroutines do not share tracing settings.
TRACE !
DELETE MY.CNTL.PDS
TRACE !
DELETE MY.CNTL.PDS
You can specify the abbreviation shown above, or the full word (e. g. TRACE
NORMAL).
41
42
Tracing Options
Least amount of things traced
TRACE !
TRACE O
Nothing traced.
TRACE N
TRACE F
TRACE E
TRACE !C
TRACE C
TRACE L
Labels only
TRACE A
TRACE S
TRACE !R
TRACE R
TRACE ?R
TRACE !I
TRACE I
42
43
Using EXECUTIL
EXECUTIL TS turns interactive debugging on within the exec. There is no special
reason for doing this in an exec, TRACE ? works.
EXECUTIL TE turns interactive debugging off within the exec. There is no special
reason for doing this in an exec, TRACE OFF works.
EXECUTIL HT stops the display to the terminal.
EXECUTIL RT restarts the display to the terminal.
Interactive Debugging
During interactive debugging, your exec stops. You can do these things:
EXECUTIL TE
STATUS CICTMDRI
TRACE ?
Questions
Your program is running, apparently not doing anything, and wont stop. What do
you type in to see what its doing?
Youre in interactive trace, single-stepping through the program, and want to quit.
What do you type in to get the program to complete without further tracing?
Can you regain control of a runaway program by typing EXECUTIL TS?
43
44
Error Trapping
REXX allows five types of error trapping routines. There are two types of error trap.
One quits the program, the other continues running from the point of the error. Well
take a look at both.
Some errors should halt the program. The program should inform the user of the error
before shutting down.
Error traps are generally set up at the beginning of the program. Conditions occurring
after that are intercepted wherever they happen. Control jumps to the error handling
routine. Usually the routine contains an EXIT. Here is the syntax:
Signal on condition
:
:
condition:
/* handle the condition
Exit
*/
The other type of error traps are subroutines. Control returns to the instruction
immediately after the one causing the error. You may not return anything. The RESULT
variable is not set. Here is the syntax.
Call on condition
:
:
condition:
/* handle the condition
Return
*/
You can name the routine if you want to, as in this example.
Call on condition,
NAME routine_name
:
:
routine_name:
*/
44
45
Say D2X(ABS(RC))
If you dont have a FAILURE trap, REXX displays the failed command and continues
with the exec.
NOVALUE: remember, it is legal to use undefined variables; REXX considers them
literals. However, you may want to catch that. This is useful in debugging, but after the
program works there is no need to leave it in. If you dont set up a NOVALUE trap,
undefined variables are seen as literals.
PA1/ATTN: capture the user hitting the ATTN or PA1 keys. If you dont set a
HALT trap, hitting PA1 or ATTN, then typing HI, ends the exec. Dont prevent the user
from stopping execution!
On the next page are some examples of each trap.
45
46
Trapping Examples
Signal on Syntax
Call
on Error
Signal on Failure
Call
on NoValue
Call
on Halt
:
:
Syntax:
Say Syntax error
Exit
Error:
Say Command failed
Return
Failure:
Say Oops!
Say Error code is D2X(ABS(RC))
Exit
NoValue:
Say Please define your variables
Return
Halt:
Say Want to stop now (Y/N)?
Pull REPLY
If REPLY = Y Then Exit
Return
To turn off the error trap, use OFF instead of ON:
Signal
Signal
Signal
Signal
Signal
off
off
off
off
off
Syntax
Error
Failure
NoValue
Halt
46
47
The special REXX variable SIGL contains the line number of the statement sent to
the error trap.
The function ERRORTEXT(RC) gives the message REXX puts out for a syntax
error.
The function CONDITION(D) displays the string in error with a NOVALUE trap
(i.e. the variable in error).
The Infamous Go To
As you may have guessed, SIGNAL can send to a label, even without an error
condition. This is the equivalent of the GOTO. If you do use SIGNAL as a GOTO, it
should go to an exit point.
Do not use SIGNAL to exit loop structures or subroutines as it destroys loop or
subroutine structure. There are better ways to exit subroutines.
47
48
*/
DELETE NO.SUCH.DATASET
WHAT COMMAND IS THIS
SALARY-INCREASE = 10
Say ERROR_MESSAGE
Exit
ERROR:
Say Command to TSO did not work on line SIGL
Say Command was SOURCELINE(SIGL)
Return
SYNTAX:
Say Syntax error on line SIGL
Say Instruction was SOURCELINE(SIGL)
Say REXX error message: ERRORTEXT(RC)
Say Problem is in: CONDITION(D)
Exit
FAILURE:
Say Command to TSO did not work on line SIGL
Say Command was SOURCELINE(SIGL)
Say Abend Code was RC
If RC = -3 Then Say Command not found.
Exit
48
49
Questions
Should you leave error traps in execs going into production?
How does the NOVALUE trap help enforce good programming practice?
ERRORTEXT(RC) is used in which error trap?
Exercise #13
Write an exec asking for a dataset name. It then issues the TSO command LISTD on
it. Set up an error trap to intercept the command not working.
In the error trap, display the line of the program in error, the string producing the
error, and the error code from TSO. Ask for the dataset name again, re-execute the
command, and exit.
49
50
Operators
+
Add, as in 1 + 1 = 2.
Subtract, as in 1 - 1 = 0.
Multiply, as in 2 * 3 = 6.
Divide, as in 4 / 2 = 2.
Integer divide, as in 5 % 2 = 2.
//
Remainder, as in 5 // 2 = 1.
**
50
51
Arithmetic Precision
REXX can do math to almost any precision, and very quickly. You can run out of
memory using too great a precision. The default precision is 9 digits. Try the following
on your own machine:
Exercise #14
Write an exec asking for two numbers, and then multiply them. Set an error trap to
intercept any error such as invalid numbers.
Exercise #15
Write an exec asking for an LRECL and a BLKSIZE, then determine if the BLKSIZE
is an even multiple of the LRECL. Tell the user if it is or is not.
51
52
Select
When expression Then instruction
Otherwise instruction
End
You can have as many WHEN expressions as you need to complete your selection.
Each expression is checked in order. When an expression is found to be true, that
instruction is executed and the program continues after the END. If none of the
expressions are true, the OTHERWISE instruction is executed.
The instruction may be another SELECT, a DO group, or any valid REXX instruction.
Here is a concrete example:
Select
When DAY = 1 Then Say Sunday
When DAY = 2 Then Say Monday
When DAY = 3 Then Say Tuesday
When DAY = 4 Then Say Wednesday
When DAY = 5 Then Say Thursday
When DAY = 6 Then Say Friday
When DAY = 7 Then Say Saturday
Otherwise Say Unknown day of the week.
End
52
53
Exercise #16
Write a metric conversion exec. The exec should accept two arguments: UNIT and
QUANTITY.
UNIT can have one of these possible values: LITER, QUART, MILE, or
KILOMETER.
It returns the equivalent of Quantity in the other measurement system based on this
table.
1
1
1
1
liter
quart
mile
kilometer
=
=
=
=
1.057 quarts
0.946 liters
1.6 kilometers
0.625 miles
53
54
Do
instructions
End
This runs the group of instructions once. There are several modifiers you can use with
the DO group to make the group run more than once, or even not at all.
If you want to run the loop a specific number of times, code a number. For example,
this DO group runs 3 times:
Do 3
Say Hello
End
A variable can be used instead of a number if you need to change the number of times
the loop is run for each execution.
Do variable_name
Say And so on...
End
If you want to run the loop at least once, until some condition is true, use the UNTIL
clause. The UNTIL is checked after the loop has been executed.
54
55
More DO Loops
You can step through a variable for a DO loop. This is useful for going through a
table:
Do I = 1 to 10
Say Number of times through loop: I
End
EndLoop = 10; Y = 1
Do Z = 1 to EndLoop By 2
Say Loop counter is: Z
Say Number of times through loop: Y
Y = Y + 1
End
Say Countdown:
Do J = 10 to 1 By -1
Say J
End
55
56
Do Forever
If TIME() > 12:00:00 Then Leave
Say Is it lunch time yet?
End
LEAVE gets you out of the loop.
In any loop you may encounter a condition such that, while you dont want to leave
the loop, you also dont want to execute the rest of the instructions in it. REXX has a
way to do that. The ITERATE instruction tells REXX to never mind the rest of the
loop, go back to the top, increment, and continue from there. Heres an example for
those not liking the number 13.
Do I = 1 to 15
If I = 13 Then Iterate
Say I is I
End
The result of the above loop is this.
I
I
I
I
I
I
I
I
I
I
I
I
I
I
is
is
is
is
is
is
is
is
is
is
is
is
is
is
1
2
3
4
5
6
7
8
9
10
11
12
14
15
56
57
Questions
What is the ending value of I in this example? Run it to find out.
Do I = 1 To 4
Say I
End
Say Ending value of I is I
What is the result of running this after 12:00 noon? Run it to find out (but please
dont do so until 11:59!).
Exercise #17
Write an exec asking the user to enter a series of numbers, never the same one twice in
a row. Limit the list to 10 numbers.
57
58
Line of program
|
Does REXX understand
|
|
Yes
|
REXX does it
it?
|
|
No
|
|__Pass to TSO
ISPEXEC
ISREDIT
A = B
A = B
YELP Bark
YELP = Bark
/*
/*
/*
/*
understood */
not understood */
not understood */
understood */
58
59
Questions
Will this line of instruction be passed to the environment?
DELETE ABC.DATA
Can you talk to ISPF from any EXEC?
59
60
REXX tries to figure out what kind of command the statement is. It then determines
who should execute the statement. All unknown commands are passed to the
environment. Using quotes tells REXX to send the statement directly to the environment.
60
61
ADDRESS ISPEXEC
DISPLAY PANEL(MEDMENU)
VPUT (DOG CAT) SHARED
ADDRESS TSO
DELETE ABC.DATA
/* Sent to ISPF */
/* Sent to ISPF */
/* Sent to TSO
*/
You cannot address ISPF from READY mode because the ISPF environment isnt
available. In REXX you can find out whether an environment is available using the
SUBCOM command. A return code of 0 means that environment is available.
SUBCOM ISPEXEC
If RC = 0
Then NOP /* In ISPF, so continue */
Else Do
/* Try again, using ISPF */
ISPSTART COMMAND(this command)
Exit
End
Note the EXIT in the ELSE loop. This is needed because otherwise the exec will
continue to execute. Another way to tell if ISPF is active is this code.
61
62
Exercise #18
Write an ISPF edit macro to save and execute the exec youre currently working on. It
must start with the usual comment, and then have ADDRESS ISREDIT MACRO (see
above). The commands to pass to the ISPF editor are:
(CURMBR) = MEMBER
SAVE
The command to be passed to TSO is:
63
Say REVERSE(ABCD)
displays DCBA.
A function may be called like a subroutine. When done in this way, the result of the
function is placed in a special variable called RESULT. For example,
Say TIME()
A complete list of functions can be found in the attachment to this class, and in Book
Manager and other IBM documentation.
A Pitfall
If you leave a space between the function name and its data items you dont get the
function, you get concatenation.
Length ABCDEF
63
64
Say SYSVAR(SYSPREF)
Say SYSVAR(SYSUID)
Say Length(Kitty)
displays 5
Say Left(Kitty,3)
Say Right(Kitty,3)
displays Kit
displays tty
64
65
Say STRIP(FULL.NAME.DSN,L,)
displays FULL.NAME.DSN
WORD(string,n): displays the nth word from string.
displays on
65
66
Say DATATYPE(A12)
Say DATATYPE(123)
Say DATATYPE(123,N)
returns CHAR
returns NUM
returns 1
A
B
L
M
N
S
U
W
X
alphabetic
bits
lower case
mixed case
number
symbol (valid symbol, e. g. $, @)
upper case
whole number
hexadecimal number
DATE([option]):
If option is omitted the format of the date is DD MMM YYYY. Valid types are:
C
D
E
J
O
U
W
66
67
CODE = LISTDSI(ENDN1.A06TIC08.SPROCLIB)
CODE = LISTDSI(MY.COBOL.PDS)
A CODE of 0 means the dataset exists. A CODE of 4 means the directory
information of a PDS is invalid. A 16 is returned if no information is available (e. g. file
not found).
LISTDSI may also be used with a DD name by providing the parameter FILE.
Exercise #19
Write an exec to accept two numbers from the terminal. Verify they are valid
numbers. Subtract one from the other, drop the sign, and display the answer.
Exercise #20
Write an exec see if a dataset called WORKSHOP.TEMP exists. If so, delete it. If
not, allocate a new one like your EXEC library. The TSO command is:
68
The benefit is the ability to use the function internally or externally with minor
change. It also makes the program more modular. That in turn makes the program easier
to debug.
A function/subroutine can be either internal (within the same program) or external (in
a separate file). Internal and external functions are called the same way.
REXX looks for internal functions first. If you use quotes, REXX looks externally.
For example:
Say MYSUBR(123)
You can write traditional subroutines if you want. A traditional subroutine
68
69
69
70
/*
/*
/*
/*
ADDEMUP:
/* share vars */
Arg NUM1,NUM2
ANSWER = NUM1 + NUM2
Return ANSWER /* give answer back on RETURN */
Say ADDEMUP(1,2)
Exit
/* invoke as function
*/
/* dont fall into routine */
ADDEMUP: PROCEDURE
/* dont share vars */
Arg NUM1,NUM2
ANSWER = NUM1 + NUM2
Return ANSWER /* give answer back on RETURN */
/*
/*
/*
/*
ADDEMUP:
/* share certain vars */
PROCEDURE EXPOSE NUM2
Arg NUM1,NUM2
ANSWER = NUM1 + NUM2
Return ANSWER /* give answer back on RETURN */
70
71
Questions
True or false: in REXX, user-written functions / subroutines may be used as either
functions or subroutines.
True or false: if the code is used as a function, you execute it this way:
function_name(data).
True or false: if the code is used as a subroutine, you execute it this way: Call
function_name data and the answer comes back in RESULT.
Exercise #21
Write an exec with an internal function / subroutine to concatenate, without spaces,
two data items passed to it. Invoke it as a function and as a subroutine. Check
automatically within the exec to verify the calls produce the same result.
71
72
Generally, its cleaner to call a user-written function as you would any standard
function. If you do code it as a call, you must quote the function name, and pass the
parameters outside of the parenthesis. For example:
/* REXX */
DSN1 = SR1.CNTL; DSN2 = @TSSQ04.SR1.EXEC
Call $FixDSN DSN1 /* call as subroutine */
Say The fully-qualified DSN is RESULT
/* call external procedure as function */
Say Fully-qualified DSN is $FixDSN(DSN2)
Exit
/* REXX Fix DSN external proc
Arg DSN
USERID = Sysvar(SYSUID)
If Left(DSN,1) = "'"
Then DSN = Strip(DSN,,"'"
Else DSN = USERID"."DSN
Return DSN
*/
72
73
A final note: typically SYSEXEC is searched before SYSPROC. This is not always
true, it is installation-dependent.
73
74
Exercises
You must try Exercises #22 and #25. If you choose, you may do only one of either
Exercise #23 or #24.
Exercise #22
Redo the percent increase exec from Exercise #11 as an external subroutine. Name it
PERCENT. Have it accept two parameters, the old number and the new number. Have it
return the percent increase on the RETURN statement. Make sure both args are numeric.
If either one or both are not valid, display a message and return a 0.
Exercise #23
Using your solution to #21, write your concatenate subroutine as an external function /
subroutine (leave the internal one where it is). Call the external function / subroutine in
such a way as to make sure you invoke the external one and not the internal one. Prove
you made the right call.
Exercise #24
Create a metric conversion external subroutine called METRIC (see Exercise #16).
Also write a main exec calling this function.
Exercise #25
Create an external subroutine called SQRT to compute the square root of a number
passed to it. It accepts one number only. Validate the data item for being a number. If it
is negative, or not numeric, display an appropriate message and return a 0. Set a loop
limit of 50 (close is good enough for the cigar).
Start with a guess of the number. The loop consists of this:
Make new guess = (guess + (number / guess)) / 2
Make guess = new guess
Return the new guess to the caller.
74
75
Heres an example:
WEEKDAY.1 = Sunday
WEEKDAY.2 = Monday
:
WEEKDAY.7 = Saturday
These look a lot like WEEKDAY_1, WEEKDAY_2, and so on. The importance of
the period, and these being stem variables, is simply this: you can substitute a variable
for the number:
A = 1
WEEKDAY.A = Sunday
Say WEEKDAY.1 /* produces Sunday */
Say WEEKDAY.A /* produces Sunday */
You can easily vary the variable with a DO group, and step through a long list of data:
75
76
76
77
Exercise #26
Write an exec with a loop setting NUMBER.1 through NUMBER.10 to the numbers
101 through 110. Then loop through the array, displaying the contents of NUMBER.1
through NUMBER.11, to see what happens.
77
78
TSO Interactions
Command Messages and OUTTRAP
TSO displays messages from most of its commands. To suppress messages use this
statement.
DUMMY = MSG(OFF)
Of course, MSG(ON) resumes displaying these messages.
You can trap most (but not all) of these messages. They are not displayed, but are still
accessible if your REXX wants to use them. To trap displayed TSO messages, use the
OUTTRAP function.
DUMMY = OUTTRAP(LINE.,*)
You can use any variable instead of LINE. Because this variable is a stem variable,
you must include the period.
The * says to capture all lines. This is the default. For the * you can substitute a
number to capture that many lines.
DUMMY = OUTTRAP(LINE.,100)
captures 100 lines.
Using LINE. as our stem variable, the following is true.
1. LINE.0 is the number of lines captured
2. LINE.1 is the first line captured
3. LINE.2 is the second line captured
and so on. To suppress messages and not capture them either, this statement works.
DUMMY = OUTTRAP(LINE.,0)
To turn off line trapping, use this statement.
DUMMY = OUTTRAP(OFF)
78
79
DUMMY = OUTTRAP(LINE.)
LISTC
Say This many lines were trapped: LINE.0
Do I = 1 to LINE.0
Say Line of output was: LINE.I
End
DUMMY = OUTTRAP(OFF)
This example runs the CRJ command against all members of a PDS. The function
STRIP removes spaces from around the member names.
*/
*/
*/
*/
80
PULL;
EXECIO write;
PARSE EXTERNAL;
TSO commands with PROMPTs.
80
81
/\LIFO
commands
here
LIFO commands (e.g. PUSH, EXECIO WRITE) put commands at the start of the
program stack.
The QUEUED() function tells you how many lines are in the stack.
Data is taken from the very start of the stack by PULL, EXECIO WRITE, and several
others.
If the program stack is empty, data comes from the terminal input buffer.
PARSE EXTERNAL takes data from the beginning of the terminal input buffer.
Because that is before the program buffer starts, you can use the command to avoid
getting things from the program buffer.
If the terminal input buffer is empty, the keyboard unlocks and TSO waits for you to
type something.
If you might have something in the program stack to be saved, or as good
programming practice in a new EXEC, issue the NEWSTACK command. NEWSTACK
creates a new program stack and saves the old one. All subsequent commands go to this
new stack until the DELSTACK command is issued.
When your program ends, and all programs executing have ended, control goes back
to TSO (or to the editor if the command was a macro). Anything left over in the stack is
taken as a command by TSO.
81
82
Questions
What will this line of a program do: SAY QUEUED()
There is nothing in either stack. Your program says PULL. What happens?
Your exec does 10 PUSHes and 9 PULLs. What happens?
Your exec does 9 PUSHes and 10 PULLs. What happens?
NEWSTACK
Queue ABC.DATA
DELETE
DELSTACK
82
83
QSTACK
/* queries the stack manager
Stacks = RC
/* Total number of stacks
My_Stacks = Stacks 1
/* These are mine
Say There are Stacks stacks.
Do My-Stacks
DELSTACK
/* delete all my stacks
End
*/
*/
*/
*/
*/
83
84
The variables UID, NewDSN, OldDSN, and KSDS were defined and set before
this set of code.
The SUBMIT command takes everything from the first QUEUE command
through the queued ZZ.
The If KSDS statement is explained below with the IF command details.
84
85
*/
NEWSTACK
%otherpgm /* Accepts two lines of input from
user at terminal and displays them */
DELSTACK
%otherpgm
/* Displays Received Rocky and
Received Bullwinkle */
- - - - - - - - - - - - - - - - - - - - /* REXX OTHERPGM */
Pull data_line
Say Received data_line
Pull data_line
Say Received data_line
85
86
TSO Prompting
TSO prompting uses the same stack as PUSH, PULL, and QUEUE. Prompting in
TSO defaults to ON. Prompting in an Exec defaults to OFF. You can turn prompting on
if your TSO profile allows it (PROFILE PROMPT).
To turn prompting on and save the previous setting:
PROFILE PROMPT
SAVE_PROMPT = PROMPT(ON)
To restore the previous setting:
DUMMY = PROMPT(SAVE_PROMPT)
To find out the current setting:
Say PROMPT()
Question
When and why should you use NEWSTACK?
Exercise #28
Write a REXX to accept a dataset name from the terminal. Verify the DSN is less
than 45 bytes long. Verify it exists. Place the DSN into the stack so the LISTD
command can get at it. Suggestion: use QUEUE.
Turn on prompting. Execute the LISTD command but omit the dataset name so TSO
prompts for it. Since the DSN is in the stack, LISTD should get it from there.
86
87
0
1
2
20
successful action
truncated data written
if end of file
a severe error was encountered
You should always close a file when finished. The FREE command does not close the
file. Use the FINIS option of the EXECIO command to close files.
operation:
o DISKR:
read
o DISKW:
write
o DISKRU: read for update
Seq: sequence number (record number (not used on
a write)). You cant go backwards.
(options:
o none:
use the stack
o STEM:
use an array
o FINIS: close the file
The file can be read from or written to a record at a time or all at once.
87
88
The stack is used to hold the one record retrieved by the EXECIO call.
The RANDOM function generates a random number between the two named limits,
inclusive.
The PARSE PULL instruction gets the one record from storage.
88
89
Writing to a File
You can write to a file allocated as SHR, OLD, NEW, or MOD, but using SHR is not
a good idea. Use MOD if you want to keep the data already in the file.
When reading a file, we used an * to indicate all records. When writing to a file,
EXECIO has no idea when youve run out of records; only you do. Therefore you
always have to specify how many records to write. You can do this with a number, as we
did in previous examples, or with a variable. When you do so you cannot enclose the
variable within the quotes:
FREE F(dd1)
89
90
Updating a File
Lets update a record (say, record 10) in a file. Note this uses the TSO stack; well
revisit this example when we talk about the stack in the advanced course.
*/
*/
*/
*/
*/
Exercise #29
Choose a file you currently have available. Read it into an array, and then display
every other line starting with Line 1.
Exercise #30
Choose a file you currently have available. Read it into an array one record at a time.
Count each line as you read. Keep track of the longest record length. At the end of the
program, display the record count and the length of the longest record.
Exercise #31
Modify the OUTTRAP discussion example above to store the captured lines in the
dataset TEMP.CAPTURE.DATA.
o Use SYSDSN to see if the dataset exists. The syntax is SYSDSN(dsn_var) or
SYSDSN(DSN).
o If the dataset does not exist, allocate it using this command: ALLOC
DA(TEMP.CAPTURE.DATA) F(CAPTURE) NEW SPACE(1 1) TRACKS
LRECL(80) RECFM(F B).
o OUTTRAP loads an array. Use that array to write the lines of the command display.
o The WRITE command should close the file when its done writing.
90
91
References
Here is a list of references Ive found helpful. Most are on the Web.
Mike Cowlishaw, the creator of REXX, wrote a book titled The REXX language:
ISBN 0-13-780735-X Prentice-Hall, 1985
ISBN 0-13-780651-5 2nd edition, 1990
IBMs REXX page: http://www-306.ibm.com/software/awdtools/rexx/language/.
REXX list server: http://www2.marist.edu/htbin/wlvindex?tso-rexx.
REXX Language Association home page: http://www.rexxla.org.
REXX FAQ page: http://www.mindspring.com/%7Edave_martin/RexxFAQ.html. The
character between dave and martin is an underscore, not a blank.
Mark Zeldens home page. Mr. Zelden has created a large number of useful REXX
commands. The ones posted on this site are available for download.
http://home.flash.net/%7Emzelden/mvsutil.html
Doug Nadels home page. Mr. Nadel has been an ISPF developer at IBM for more than
fifteen years. This site has several useful utilities, although not all of them are written in
REXX. http://www.sillysot.com/mvs/
Lionel B. Dycks home page. Mr. Dyck has been a systems programmer since 1972.
This page has a few really useful things. http://www.lbdsoftware.com/
Two pages from Neil Hancock. Mr. Hancock has been a programmer for many years,
formerly for Met Office, and recently for Macro4, in the UK. The first page is a set of
FAQs on REXX; the second is a REXX style guide.
http://www.uberfish.freeserve.co.uk/Computers/rexxfaq.html.
http://www.uberfish.freeserve.co.uk/Computers/RexxStyleGuide.html.
91
92
92
93
/*
fully qualified */
/* NOT fully qualified */
Accept a DSN from the user. Create a second dataset from the first, except change the
third qualifier to todays date. The variable assumed here is INDSN.
Parse Upper Var INDSN SDQ1 "." SDQ2 "." SDQ3 "." SDQ4
UQ3 = JDATE(J)
OUTDSN = SDQ1.SDQ2"."UQ3.SDQ4
Determine if a dataset is not available. The dataset is not quoted, so a kludge is
needed to pass the DSN (the POS function tells whether a quote is present). The
NORECALL option tells LISTDSI not to recall a migrated dataset.
IF POS("'",DSN1) = 0 THEN DSN1 = "'"DSN1"'"
EXIST1 = LISTDSI(DSN1 NORECALL)
IF EXIST1 > 0 THEN SAY "DATASET 1 NOT AVAILABLE"
Get the dataset name of the most recent generation of a GDG.
Arg GDGBASE
If Left(GDGBASE,1) = "'" Then Strip(GDGBASE,,"'")
foo = OutTrap(CMDDATA.)
"LISTC ENT('"GDGBASE"') ALL GDG"
foo = OutTrap(Off)
LINE
= CMDDATA.0
CURGEN = CMDDATA.LINE
OFFSET = Pos("--",CURGEN) + 2
CURGEN = Strip(Substr(CURGEN,OFFSET,45))
If SYSDSN("'"CURGEN"'") <> OK Then CURGEN = "BAD"
Return CURGEN
93
94
94
95
95
96
96
97
REXX
CLIST
SAY
/* REXX Example */
X = 10
Y = 20
Z = Y X
Say "The Answer Is Z
Displays The Answer is 10 on the terminal.
97
98
This is correct.
2 Say Hey;
Say;
Man
This is incorrect. The semicolon after the second Say must be a comma.
If this is run, the result is HEY on one line, a blank line, then either the
TSO command MAN runs (if it exists) or an error message is displayed.
3 - Compute; C = Y - A
True or false: the EXIT statement must always be the very last line in the program.
False. The EXIT statement is optional if it is the last line.
BARK Hello
No, it is passed to TSO.
98
99
/* REXX Try Me
Say Greeting
*/
99
100
1_time_only
ProGramMer_NamE
progame
input-data
SAY
/* REXX */
MESSAGE = MESSAGE
Say MESSAGE
EXIT
Say Elle
||
No.
Woody
When this prints, how many spaces will be between Elle and Woody?
Say Elle
One.
Woody
100
101
/* REXX Runme */
Arg YOUR_NAME ADDRESS / JUNK
Say Your name is YOUR_NAME
Say You live at ADDRESS
%RUNME JOHN 1313-1/2 DEADEND ROAD
Your name is John
You live at 1313-1
101
102
Only if
Yes.
Yes, to catch
Syntax errors.
102
103
5.
Do I = 1 To 4
Say I
End
Say Ending value of I is I
What is the result of running this after 12:00 noon? Run it to find out.
0.
DELETE ABC.DATA
103
104
In the
104
105
There is nothing in either stack. Your program says PULL. What happens?
Keyboard unlocks, waiting for your input.
Your exec does 10 PUSHes, and 9 PULLs. What happens? The last line in the
stack waits for another PULL, write, or TSO command looking for input. If
the exec ends before that happens, the last line in the stack is passed to
TSO to be executed.
Your exec does 9 PUSHes, and 10 PULLs. What happens?
waiting for your input.
Keyboard unlocks,
105
106
106
107
Exercise 1, page 19
Write an exec to execute the following two TSO commands:
TIME
SEND Sample REXX U(*)
Include the comment,
This is a sample REXX program for class
Execute the REXX statement below, but use a continuation character and two lines:
Say TIME() DATE()
107
108
Exercise 2, page 21
Write an exec to display these three lines:
3 + 1 is 4
3 + 1 is 4
OBrien
/* REXX # 2 */
Say "3 + 1 is 4"
Say "'3 + 1 is 4'
Say "O'Brien
Exercise 3, page 24
Write an exec to:
/* REXX */
A = 10
B = 20
Say "A + B is" A + B
108
109
Exercise 4, page 29
Write an exec to:
Exercise 5, page 32
Write an exec to execute the LISTCAT ENTRY(dsn) command. Pass the DSN using
ARG. Make sure it works on your own datasets and datasets not belonging to you.
/* REXX */
Arg DSN
"LISTC ENT("DSN")"
109
110
Exercise 6, page 34
Write an exec to accept three pieces of information and display them in reverse order
of entry. If more than three are entered, display an error message.
*/
Exercise 7, Page 34
Write an exec to examine information passed to it. Perform the following checks:
/* REXX Agenda */
Arg NAME1 NAME2
If NAME1||NAME2 = "ALRUSH",
| NAME1||NAME2 = "RUSHAL"
Then Say "Look out!"
Else Do
If NAME1 = "AL" | NAME2 = "AL"
Then Say "Must be a liberal."
If NAME1 = "RUSH" | NAME2 = "RUSH"
Then Say "Must be a conservative."
If NAME1 <> "RUSH" & NAME2 <> "RUSH",
& NAME1 <> "AL" & NAME2 <> "AL"
Then Say "Oh, a moderate."
End
110
111
Exercise 8, Page 37
Write an exec to accept two args: the day of the week and the weather. If the day is
Friday and the weather is rainy display Head for office!. If the day is Friday and the
weather is not rainy display Head for golf course!.
Exercise 9, Page 39
Write an exec to ask for three, and only three, words, and display them in reversed
order.
/* REXX interact with user */
Say "Enter three words.
Pull VAR1 VAR2 VAR3 .
Say VAR3 VAR2 VAR1
111
112
112
113
*/
ERROR:
Say "Command to TSO did not work on line" SIGL
Say "Command was" SOURCELINE(SIGL)
Say "Abend Code was" RC
Say
Say "The DSN may be wrong. Try again:"
Pull DSN
"LISTD" DSN
Return
113
114
114
115
liter
quart
mile
kilometer
=
=
=
=
1.057 quarts
0.946 liters
1.6 kilometers
0.625 miles
115
116
116
117
117
118
/* Call as subroutine */
/* Call as function
*/
/* Concat compare
*/
118
119
119
120
120
121
ANS
ANS
ANS
ANS
=
=
=
=
AMT*1.057
AMT*.946
AMT*1.6
AMT*.625
RESULT "quart."
RESULT "liter."
RESULT "kilometer."
RESULT "mile."
entered."
121
122
*/
122
123
123
124
124
125
125
126
126
127
Use SYSDSN to see if the dataset exists. If not, allocate it using this command:
ALLOC DA(TEMP.CAPTURE.DATA) F(CAPTURE) NEW SPACE(1 1)
TRACKS LRECL(80) RECFM(F B)
OUTTRAP loads an array. Use that array to write the lines of the commad display.
The write command should close the file when its done writing.
127
KEYWORD
PAGE
HI instruction
8
HT instruction
8
IF instruction
8
INDEX function
32
INSERT function
32
INTERPRET instruct. 10
ITERATE instruction 11
JUSTIFY function
32
LASTPOS function
33
LEAVE instruction
11
LEFT function
33
LENGTH function
33
LINESIZE function
33
LISTDSI function
33
MAKEBUF / DROPBUF
12
MAX function
35
MIN function
35
MSG function
36
MVSVAR function
36
NEWSTACK / DELSTACK 13
NOP instruction
14
NUMERIC instruction 14
OTHERWISE instruct. 14
OUTTRAP function
37
OVERLAY function
37
PARSE instruction
15
POS function
38
PROCEDURE instruct. 17
PROMPT function
38
PULL instruction
17
PUSH instruction
17
QBUF
18
QELEM
18
QSTACK
18
QUEUE instruction
19
QUEUED function
38
RANDOM function
38
RC variable
23
RESULT variable
23
KEYWORD
PAGE
RETURN instruction 19
REVERSE function
38
RIGHT function
39
RT instruction
19
SAY instruction
19
SELECT instruction 20
SIGL variable
28
SIGN function
39
SIGNAL instruction 21
SOURCELINE function 39
SPACE function
39
STORAGE function
39
STRIP function
40
SUBCOM
21
SUBSTR function
40
SUBWORD function
40
SYMBOL function
40
SYSDSN function
41
SYSVAR function
42
TE instruction
21
TIME function
44
TRACE instruction
22
TRACE function
44
TRANSLATE function 44
TRUNC function
44
TS
21
UPPER instruction
21
USERID function
45
VALUE function
45
VERIFY function
45
WORD function
45
WORDINDEX function 45
WORDLENGTH function 45
WORDPOS function
45
WORDS function
46
XRANGE function
46
X2C function
46
X2D function
46
The ARG instruction receives data from a calling program. It is a short form of PARSE
UPPER ARG. In a main program it receives data typed on the command line; in a
function or subroutine it receives data passed to it on the call.
The data may be received in one or more variables separated by a delimiter such as a
space or comma. Fields separated by spaces are considered words; commas are normally
used in function calls. Use a period (.) to drop variables.
ARG FIELD1 FIELD2 FIELD3 places the first word (all characters up to the
first blank) in FIELD1, the second word in FIELD2, and all remaining characters
(spaces and all) in FIELD3.
ARG FIELDS places all data passed into the variable FIELDS.
ARG FIELD1 FIELD2 . places the first word in FIELD1, the second word in
FIELD2, and ignores everything after the second word.
ARG FIELD1,FIELD2 places all data before the first comma into FIELD1 and
the remaining data into FIELD2.
The CALL instruction invokes a subroutine, whether external or internal. The called
routine should end with a RETURN instructor. CALL can also turn on or off an error
trap.
CALL subroutine parameters passes parameters to the subroutine, which picks them up
via the ARG instruction. The subroutine passes the result, if any, in the variable
RESULT.
Example:
CALL LENGTH ABCD
SAY RESULT
/* displays a 4 */
CALL ON condition-name sets up an error trap (see SIGNAL). If the error trap is
entered, a RETURN at the end of the trap sends control back to the instruction after the
failed instruction.
Example:
CALL ON ERROR
CONWAIT is a CMS-only instruction. It waits until all output directed to the terminal
has been displayed. Often used with DESBUF to ensure no terminal output is lost while
clearing the terminal output buffer.
Example:
PUSH CART
CONWAIT
DESBUF
/* CART is lost */
DESBUF is a CMS-only instruction. It clears the stack and both the input and output
terminal buffers. Often used with CONWAIT to ensure no terminal output is lost while
clearing the buffers.
Example:
PUSH CART
CONWAIT
DESBUF
/* CART is lost */
The DO instruction starts a group of instructions to be performed repeatedly. The
number of times the instruction group repeats is controlled by a variable or a REXX
keyword set. Some examples:
DO I = 1 TO 10
SAY I
END
/* Increment a variable */
DO I = 10 TO 1 BY -1
SAY I
END
/* Decrement a variable */
DO FOREVER
/* Loop forever, get out with LEAVE */
IF TIME() > 16:00:00 THEN LEAVE
END
DO UNTIL TIME() > 16:00:00
SAY WORK
END
/* As long as true */
DROP undefines a variable. REXX takes the string as an upper case literal.
Example:
GREETING = HI!
SAY GREETING
/* displays HI! on the screen */
DROP GREETING
SAY GREETING
/* displays GREETING on the screen */
END ends a DO or SELECT structure. If on a counting loop, END can name the
counting variable to ensure the right loop is ending.
Example:
DO I = 1 TO 10
SAY I
END I
/* we know its ending the DO I loop */
The EXECIO TSO/CMS instruction handles dataset I/O for reading, writing, and
updating datasets in a REXX exec. In TSO you must ALLOCATE the dataset before you
can run EXECIO.
CMS examples: note filename, filetype, and filemode stand for the actual file being
read or written.
EXECIO * CARD reads from reader into stack
EXECIO * CARD (STEM RECD. reads from the reader into the variables
RECD.1 through RECD.n where n is the number of cards read. EXECIO
sets RECD.0 to the number of cards read.
EXECIO RECD.0 PRINT writes all records from RECD. to the printer.
EXECIO QUEUED() PUNCH writes all records from the stack to punch.
EXECIO * DISKR filename filetype filemode reads from the
named file into the stack
EXECIO * DISKR filename filetype filemode (STEM RECD.
reads from the named file into the stem variable RECD.
EXECIO QUEUED() DISKW filename filetype filemode
writes all records from the stack to the named file.
The EXECUTIL instruction is valid in TSO only. It may be executed inside an exec or
as a native TSO command. It controls the execution of a REXX exec. Some examples:
EXECUTIL TS turns on interactive debugging with TRACE R.
EXECUTIL TE turns off interactive debugging.
EXECUTIL HT stops display of all SAYs, even in other execs.
EXECUTIL RT resumes display of all SAYs.
EXECUTIL HI stops program execution.
EXECUTIL SEARCHDD(YES) usually executed before the first REXX exec
in a TSO session. It causes TSO to search for REXX execs in the DDname
SYSEXEC (the default is SYSPROC). Not usually found inside REXX
execs.
The EXIT instruction ends the REXX program and returns control to the calling program
or environment. May pass back a return code (numeric only) by coding it after the
instruction (EXIT 8 passes a return code of 8). The return code can be checked as
follows:
The EXPOSE instruction is used with the PROCEDURE instruction to allow the named
variables to be shared with the main program. In effect, EXPOSE makes the named
variables global. This instruction is usually found right after the PROCEDURE
statement; for example:
SUBPGM: PROCEDURE EXPOSE VAR1 shares VAR1 with the main program;
all other variables in the procedure SUBPGM are protected and cannot be
seen or modified by the main program.
The HI instruction stops execution of the program (HI is Halt Immediate). In TSO it
may only be executed after an ATTN interrupt. In CMS, it may be executed only when
the screen displays MORE in the lower right.
The HT instruction stops display to the terminal (HT is Halt Terminal). In TSO it may
only be executed after an ATTN interrupt. In CMS, it may be executed only when the
screen displays MORE in the lower right. See the RT command.
The IF instruction controls conditional execution of one or more instructions. If the
expression is true, the instrruction on the THEN keyword is processed. If the expression
is false, either nothing happens (no ELSE) or the instruction on the ELSE keyword is
executed.
The format of the IF instruction is:
IF expression
THEN instruction
ELSE instruction
The expression may contain one of these comparison operators. Numbers are
compared numerically, characters by the collating sequence. See also the
description under equal and strictly equal.
=
Equal. Numbers are equal numerically, e.g. 001.0 equals 1. Characters are
considered equal ignoring leading or trailing spaces, e.g. DEB is equal to
DEB. Case is significant, so DEB does not equal Deb.
<>
Not equal. The opposite of =. Other ways of writing not equal are ^=, \=,
and =.
>
Greater than.
>=
>
Not greater than. The opposite of >. Other ways of writing not greater than
are ^= and \=.
<
Less than.
<=
>
Not less than. The opposite of <. Other ways of writing not less than are ^=
and \=.
IF expressions continued.
==
Equal in every way, strictly equal. This is a bit comparison rather than a value
comparison.
Examples:
IF A = 1
THEN SAY A IS EQUAL TO 1
ELSE SAY A IS NOT EQUAL TO 1
IF A = 1
THEN DO
SAY A IS EQUAL TO 1
SAY ISNT IT?
END
ELSE SAY A IS NOT EQUAL TO 1
IF examples continued.
IF A = 1 & B = 1
THEN SAY A and B ARE BOTH EQUAL TO 1
ELSE SAY ONE OF A OR B IS NOT EQUAL TO 1
IF A == DATE
THEN SAY TRULY A DATE
ELSE SAY MAYBE A DATE, BUT NOT EXACTLY
IF A = MEAT
THEN SAY I CAN EAT THAT
ELSE DO
SAY SORRY, IM A VEGETARIAN
EXIT
END
IF A <= 3
THEN SELECT
WHEN A = 1 THEN SAY ITS ON!
WHEN A = 3 THEN SAY ITS OFF!
OTHERWISE SAY ITS NOT ON OR OFF.
END
ELSE IF A = 4
THEN SAY SWITCH IS IN MIDDLE.
ELSE SAY INVALID VALUE FOR A.
TRUE = 1
IF TRUE
THEN SAY ITS TRUE!
ELSE SAY DONT LIE TO ME!
The INTERPRET instruction causes REXX to look at data as if it is seeing it for the first
time. The data may be a REXX instruction or a command meant for the command
processor. Two examples:
INTERPRET SAY HI!
PART1 = S
PART2 = AY HI
PART3 = !
INTERPRET PART1||PART2||PART3
The ITERATE instruction sends control to the DO of a DO-END loop. It skips the
instructions between it and the END. In a nested loop, ITERATE works only in its loop.
If ITERATE names a loops variable, REXX iterates within that loop. Three examples:
DO I = 1 TO 20
IF I = 13 THEN ITERATE
SAY I
END
/* SKIP #13 */
DO 20
/* Skips #13 in the inner loop only */
DO I = 1 TO 20
IF I = 13 THEN ITERATE
SAY I
END
END
DO HR = 1 TO 12
DO MM = 1 TO 60
IF MM = 60 THEN ITERATE HR
SAY HR:MM
END
END
/* next hour */
The LEAVE instruction sends control to the instruction after the END of a DO-END
loop. LEAVE ends the loop its in. In a nested loop, LEAVE works only in its oen loop.
If LEAVE names a loops variable, REXX iterates within that loop. Three examples:
DO I = 1 TO 20
IF I = 13 THEN LEAVE
SAY I
END
/* PRINT 1 12 ONLY */
DO 20
/* The process is still done 20 times */
DO I = 1 TO 20
IF I = 13 THEN LEAVE /* PRINT 1 12 ONLY */
SAY I
END
END
DO HR = 1 TO 12
DO MM = 1 TO 60
IF MM = 60 THEN LEAVE HR
SAY HR:MM
END
END
/* next hour */
The MAKEBUF instruction creates a new buffer. This buffer can be used like a stack,
but does not isolate the current stack. The buffers number is returned in the variable RC.
Drop buffers created with DROPBUF. When you delete the buffer, all its data is lost.
Here are two examples.
MAKEBUF
BUFNO = RC
SAY QUEUED()
PUSH CART
SAY QUEUED()
DROPBUF BUFNO
SAY QUEUED()
SAY ENTER NAME
PULL NAME
SAY THANKS, NAME.
PUSH CART
SAY QUEUED()
MAKEBUF
BUFNO = RC
SAY QUEUED()
SAY ENTER NAME
PULL NAME
SAY QUEUED()
SAY THANKS, NAME.
DROPBUF BUFNO
/*
/*
/*
/*
/*
/*
/*
/* NAME = Arthur */
/* place CART in stack */
/* displays 1 */
/* save buffer number */
/* displays 1 */
/* displays 0 */
/* NAME = CART */
/* release MAKEBUF buffer */
The NEWSTACK instruction creates a new program stack. Anything in the old stack is
preserved, but unavailable. Keep track of any new stacks you create. Drop user-created
stacks with the DELSTACK command. When the last user-defined stack is gone, the
original program stack is again available. Here are two examples.
PUSH CART
SAY QUEUED()
/* displays 1 */
NEWSTACK
/* get a new stack */
SAY QUEUED()
/* displays 0 */
SAY ENTER NAME
/* assume Arthur */
PULL NAME
SAY QUEUED()
/* displays 0 */
SAY THANKS, NAME.
/* NAME = Arthur */
DELSTACK
/* return to the old stack */
SAY QUEUED()
/* displays 1 */
SAY ENTER VEHICLE
/* assume TAXI */
PULL VEHICLE
SAY VEHICLE WAS VEHICLE. /* displays CART */
NEWSTACK
PUSH CART
/* place CART in stack */
SAY QUEUED()
/* displays 1 */
DELSTACK
/* Removes stack with CART */
SAY QUEUED()
/* displays 0 */
SAY ENTER NAME
/* assume Arthur */
PULL NAME
SAY QUEUED()
/* displays 0 */
SAY THANKS, NAME.
/* NAME = Arthur */
SAY QUEUED()
/* displays 1 */
SAY ENTER VEHICLE
/* assume TAXI */
PULL VEHICLE
SAY VEHICLE WAS VEHICLE. /* displays TAXI */
SCIENTIFIC
10000000000000
ENGINEERING
10000000000000
/* The default */
/* displays 1.00010000E+9 */
/* displays 100.010000E+7 */
The PARSE instruction does character string functions. The basic syntax for PARSE is:
PARSE (UPPER) origin template
The UPPER is optional. If used, it converts the characters to upper case. If it is not used,
the characters remain in the case they started in.
PARSE takes the data from the origin and processes it using the template. The net result
is that all the variables in the template are set or changed in some way.
The template is just a list of variables. Possible orgins are:
ARG
the stack.
SOURCE
VALUE
VAR
a variable.
VERSION
HELLO!
HEY MOE
HELLO!
Using column delimiters. Data is split at the columns given. The number to the left
of a variable is the starting column; the number to the right of a variable is the
ending column, minus one.
/* REXX ALPA BETTY */
PARSE UPPER ARG 1 VAR1 4 VAR2 8 VAR3 11
SAY VAR1
SAY VAR2
SAY VAR3
> ALPHA ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABC
DEFG
HIJ
/* REXX ALPA BETTY */
PARSE UPPER ARG 1 VAR1 4 6 VAR2 8 5 VAR3 11
SAY VAR1
SAY VAR2
SAY VAR3
> ALPHA ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABC
FG
EFGHIJK
Using a value.
PARSE VALUE TWO WORDS ONLY VAR1 VAR2 .
SAY VAR1
SAY VAR2
TWO
WORDS
Using a variable.
VARSTRING = HELLO ALL YOU PEOPLE
PARSE VAR VARSTRING VAR1 VAR2 VAR3
SAY VAR1
SAY VAR2
SAY VAR3
HELLO
ALL
YOU PEOPLE
The PROCEDURE instruction is used in a subroutine or internal function to protect the
variables from the main programs effects.
Example: SUB1: PROCEDURE
The PULL instruction takes a line from the program stack or, if empty, from the terminal
input buffer. Short form of PARSE UPPER PULL, see PARSE for more information.
The PUSH instruction puts a line into the program stack last in, first out (LIFO) (see the
QUEUE instruction). For example,
PUSH HAS FLEAS
VAR1 = MY DOG
PUSH VAR1
PULL LINE
SAY LINE
PULL LINE
SAY LINE
The resulting output is MY DOG HAS FLEAS.
The QBUF instruction returns the number of buffers created by the MAKEBUF
instruction. The number of buffers is returned in the variable RC. For example,
QBUF
SAY RC
MAKEBUF
QBUF
SAY RC
DROPBUF
QBUF
SAY RC
/* returns 0 */
/* returns 1 */
/* returns 0 */
The QELEM instruction returns the number of elements or lines are available in the
buffer created by MAKEBUF. The number of buffers is returned in the variable RC. For
example,
MAKEBUF
PUSH CART
PUSH CAR
QELEM
SAY RC
/* returns 2 */
DROPBUF
QELEM
SAY RC
/* returns 0 */
The QSTACK instruction is available in TSO only. It returns the number of stacks
created by the NEWSTACK instruction, plus one. The number of stacks is returned in
the variable RC. To drop all the new stacks, use RC 1 to know how many times to run
the DELSTACK command. For example,
QSTACK
HOW_MANY = RC - 1
DO HOW_MANY
DELSTACK
END
The QUEUE instruction puts a line in the program stack. Data is put into the stack first
in, first out (FIFO) (see the PUSH instruction). For example,
PUSH HAS FLEAS
VAR1 = MY DOG
PUSH VAR1
PULL LINE
SAY LINE
PULL LINE
SAY LINE
The resulting output is MY DOG HAS FLEAS.
The RETURN instruction sends control back from a subroutine or internal function to
the instruction just after the call. Except in an error trap, can pass back a single string or
variable to the caller. For example:
SUBR:
ARG NUM1,NUM2
TOTAL = NUM1 + NUM2
RETURN TOTAL
Returns the sum of NUM1 and NUM2 back to the main program.
The RT instruction resumes display to the terminal (RT is Resume Terminal). This is the
opposite of HT. In TSO it may only be executed after an ATTN interrupt. In CMS, it
may be executed only when the screen displays MORE in the lower right.
The SAY instruction displays a line on the terminal. The line may be either a variable, a
literal, a function call, or any combination.
Examples:
SAY
A =
SAY
SAY
SAY
Aaah! /*
1
A
/*
TIME() /*
A is A,
displays Aaah! */
displays 1 */
displays result of the TIME function */
time is TIME().
SAY SUNDAY
SAY MONDAY
SAY TUESDAY
SAY WEDNESDAY
SAY THURSDAY
SAY FRIDAY
SAY SATURDAY
SUCH DAY OF THE WEEK!
The SIGNAL instruction turns on or off a condition trap named by a label. The trap can
interrupt a non-normal condition wherever it occurs after the SIGNAL. The code for the
error trap is found after the end of the main program.
Examples:
SIGNAL ON SYNTAX
SIGNAL ON ERROR
SIGNAL ON FAILURE
SIGNAL ON NOVALUE
SIGNAL ON HALT
:: code
EXIT
/*
/*
/*
/*
/*
syntax error */
command in error */
command doesnt exist */
uninitialized variable */
attention interrupt */
SYNTAX:
SAY SYNTAX ERROR!
EXIT
NOVALUE:
SAY UNINITIALIZED VARIABLE ON SOURCELINE(SIGL)
RETURN
SIGNAL can also be used as a label for a GOTO operation. For example,
SIGNAL DONE
:: code
DONE: A = A + 1
The SUBCOM instruction asks TSO or CMS if a particular environment is available, and
returns the answer in RC. RC is 0 if the environment is available, 1 if not.
Examples:
SUBCOM
SAY RC
SUBCOM
SAY RC
SUBCOM
SAY RC
SUBCOM
SAY RC
SUBCOM
SAY RC
TSO
/*
ISPEXEC
/*
ISPEXEC
/*
XEDIT
/*
USA
/*
The TE instruction is valid for TSO only. It turns interactive debugging off, and may be
run only after an attention interrupt.
The TS instruction turns interactive debugging on. In TSO it may only be executed after
an ATTN interrupt. In CMS, it may be executed only when the screen displays MORE
in the lower right.
The UPPER instruction converts the alphabetic contents of a variable to upper case.
Example:
VAR1 = this, 2, is lower case.
UPPER VAR1
SAY VAR1
/* produces THIS, 2, IS LOWER CASE. */
The TRACE instruction controls tracing and interactive debugging. The TRACE
instruction has the following operands, listed in order from the least things traced to the
most things traced.
TRACE !
TRACE O
Nothing traced.
TRACE N
TRACE F
TRACE E
TRACE !C
TRACE C
TRACE L
Labels only
TRACE A
TRACE S
TRACE !R
TRACE R
TRACE ?R
TRACE !I
TRACE I
REXX functions
The REXX functions listed here are supported under both TSO and CMS unless
otherwise noted. Functions may be used in one of two ways:
Letting REXX substitute the value for the function. For example,
SAY LENGTH(ABCD) becomes SAY 4, which displays 4 on the terminal.
SAVE_LEN = LENGTH(ABCD)
/* assignment */
Using the special variable RESULT to get the value for the function. For
example,
CALL LENGTH ABCD
SAY RESULT
/* displays 4 */
/* assignment */
ABBREV(ALLOCATE,AL,2)
ABBREV(ALLOCATE,AL)
ABBREV(ALLOCATE,ALK,2)
ABBREV(ALLOCATE,ALK)
/*
/*
/*
/*
returns
returns
returns
returns
1
1
0
0
*/
*/
*/
*/
ABS(number). Returns the absolute value (i.e. drops the sign) of a number. Formats the
result using the current NUMERIC setting. For example:
SAY ABS(-12.3)
/* displays 12.3 */
ARG(number,operand). The ARG function has four forms, detailed on this page.
ARG() returns the number of argument strings passed (commas delimit argument
strings). You can pass several to a subroutine or function, but only one to a main
program. Example:
CALL SUBR CINDY,DEB LORI
EXIT
SUBR:
SAY ARG()
/* displays 2 */
ARG(number) returns the argument string of the number passed. Example:
CALL SUBR CINDY,DEB LORI
EXIT
SUBR:
SAY ARG(2)
/* displays DEB LORI */
ARG(number,EXISTS) returns a 1 if the argument numbered number exists, a
0 if it does not. EXISTS may be abbreviated E.
CALL SUBR CINDY,DEB LORI
EXIT
SUBR:
SAY ARG(2,EXISTS) /* displays 1 */
SAY ARG(5,E)
/* displays 0 */
ARG(number,OMITTED) returns a 1 if the argument numbered number does
not exist, a 0 if it does. OMITTED may be abbreviated O.
CALL SUBR CINDY,DEB LORI
EXIT
SUBR:
SAY ARG(2,OMITTED) /* displays 0 (is there) */
SAY ARG(5,O)
/* displays 1 (not there */
/* displays 01X */
BITOR(string1,string2,pad). BITOR logically ORs string1 and string2, with pad used
to fill the shorter string to the right. Each bit in string1 is compared to the corresponding
bit in string2. Each bit in the result is set to 1 if the matching bit in either string is a 1. If
neither bit in the strings are 1, the corresponding bit in the result is set to 0. Examples:
SAY BITOR(01X,0FX)
SAY BITOR(01X,0EX)
/* displays 0FX */
/* displays 0FX */
/* displays 0EX */
/* displays 0FX */
/* returns CENTER */
/* returns --CENTER-- */
/* returns 0 */
/* returns 1 */
Examples:
SIGNAL ON ERROR
LISTCAT NOHLQ
EXIT
ERROR:
SAY COMMAND FAILED!
SAY CONDITION(C)
/* displays ERROR */
SAY CONDITION(D)
/* displays LISTCAT NOHLQ */
SAY CONDITION(I)
/* displays SIGNAL */
EXIT
COPIES(string,how-many). Returns how-many copies of string, one after another.
Examples:
COPIES(MORE,3)
COPIES(LESS,0)
Copies( ,80)
/* returns MOREMOREMORE */
/* returns nothing (no copies) */
/* returns a line of 80 spaces */
C2D(string). Converts string to its binary form, then to a decimal number. Examples:
SAY C2D(B)
SAY C2D(b)
SAY C2D(10X)
/* displays 194 */
/* displays 130 */
/* displays 16 */
C2X(B)
C2X(b)
C2X(16)
C2X(16)
/*
/*
/*
/*
displays
C2 */
displays
82 */
displays F1F6 */
displays F1F6 */
DATATYPE(string)
Returns NUM if string is a number, otherwise it returns CHAR.
SAY DATATYPE(1234)
SAY DATATYPE(Z234)
/* returns NUM */
/* returns CHAR */
DATATYPE(string,type)
Returns 1 if string has the same type as type, otherwise it returns 0. Note you may
need to strip extra spaces to get this to work properly; for example,
SAY DATATYPE(SPACE(ABCD,0),U)
/* returns 1 */
Valid types:
A alphanumeric (A Z, a z, 0 9)
B binary digits 1 and 0
D double-byte characters
L lower-case characters
M mixed-case characters
N valid number
S valid REXX symbol
U upper-case letters
W whole number
X hexadecimal number (0 9, A F)
Examples:
SAY DATATYPE(1234,N)
/* returns
SAY DATATYPE(Z234,N)
/* returns
SAY DATATYPE(AbcD,M)
/* returns
SAY DATATYPE(Z234,A)
/* returns
SAY DATATYPE(ABCD,X)
/* returns
IF DATATYPE(VAR1,N)
THEN SAY VAR1 IS A NUMBER.
ELSE SAY VAR1 IS NOT A NUMBER.
1
0
1
1
1
*/
*/
*/
*/
*/
DATE(B)
DATE(C)
DATE(D)
DATE(E)
DATE(J)
DATE(M)
DATE(O)
DATE(S)
DATE(U)
DATE(W)
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
returns
returns
returns
returns
returns
returns
returns
returns
returns
returns
733209
3091
169
06/17/2008
2008169
June
2008/06/17
20080617
06/17/2008
Tuesday
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
/* returns B */
/* returns 0 */
/* returns F0 */
ERRORTEXT(number). Returns the REXX syntax message for the passed error
number.
SAY ERRORTEXT(16)
EXTERNALS(). Returns the number of elements in the terminal input buffer (how
many lines are there). In VM/CMS, this number can be greater than zero; in TSO,
because there is no type-ahead buffer REXX returns zero..
SAY EXTERNALS()
/* returns 0, usually */
/* returns 1.33 */
/* returns 0.5000 */
/* returns ABCDEF */
/* returns He */
/* returns Hello????? */
/* returns 11 */
LISTDSI (TSO only). Returns information about the dataset in REXX variables. See
the following pages for a list of those variables and for the return codes set by LISTDSI.
It can be used in two ways.
RetCode = LISTDSI(dsn)
or
CALL LISTDSI dsn
RetCode = RESULT
There is an optional argument, DIRECTORY, which tells LISTDSI to provide
information regarding the directory of a PDS (but not of a PDS-E). The syntax is
RetCode = LISTDSI(dsn) DIRECTORY.
RetCode = LISTDSI(dsn) /* sets variables
*/
Say SYSVOLUME
/* displays the VOLSER
*/
Say SYSRECFM
/* displays the record format */
Say SYSLRECL
/* displays the record length */
Variables set by LISTDSI are listed here. Note all dates are returned as Julian
dates using a slash (/). For example, 2006/107 is April 17, 2006.
SYSDSNAME
SYSVOLUME
SYSUNIT
SYSDSORG
SYSRECFM
SYSLRECL
SYSBLKSIZE
SYSKEYLEN
SYSALLOC
SYSUSED
SYSPRIMARY
SYSSECONDS
SYSUNITS
SYSEXTENTS
SYSCREATE
SYSREFDATE
SYSEXDATE
SYSPASSWORD
SYSRACFA
SYSUPDATED
SYSTRKCYL
SYSBLKSTRK
SYSADIRBLK
SYSUDIRBLK
SYSMEMBERS
SYSREASON
Dataset name
VOLSER
Device type of VOLSER
Dataset organization
DA = Direct Access (BDAM)
PO = PDS or PDS-E
PS = sequential
VS = VSAM
Record format
F = Fixed length
V = Variable length
A = contains ASA characters
B = Blocked
Logical record length
Blocksize (VS is VSAM)
Key length or zero
Total space allocated
Total space used
Primary space allocation
Secondary space allocation
Type of space allocation
Cylinders
Tracks
Blocks
Total extents used
Creation date
Last reference date
Expiration date or 0
Password protection
NONE = no password needed
READ = read password needed
WRITE = write password needed
RACF protection status
NONE
= no protection
GENERIC = generic profile
DISCRETE = discrete profile
YES or NO
# of tracks / cylinder on VOLSER
# of blocks / track
on VOLSER
# of directory blocks on a PDS
# of used directory blocks
# of members in the PDS
reason code for command failure
LISTDSI return codes are listed here. The first-level system error message is
in the variable SYSMSGLVL1; the second-level system error message is in the
variable SYSMSGLVL2.
0) Success!
1) REXX had a problem analyzing the statement
2) Dynamic allocation failure
3) Cannot process this type of dataset
4) Error occurred obtaining unit name
5) Dataset is not catalogued
6) Error occurred getting dataset name
7) Error occurred getting unit type
8) Dataset is not on disk
9) Dataset is migrated and cannot be recalled
10) 11) Unauthorized to obtain directory information
12) VSAM dataset
13) Open error
14) Device type not found in MVS
15)
16) Command did not work
17) Some sort of abend
18) Incomplete information obtained
19) Multi-volume dataset
20) Unknown device type
21) Catalog error
22) Volume not mounted
23) I/O error attempting to get dataset information
24) Dataset not on catalogued volume
25) Dataset is migrated and is unavailable
26) Dataset is on a mass storage device
27) Cannot find VOLSER for this dataset
28) DD name specified is not valid
29) Neither dataset name nor DD name was provided
MAX(number1,number2,number20). Returns the maximum number in a string of
numbers. Note the numbers must be provided; variable substitution is not allowed.
Say MAX(5,4,3,2,4,8,2)
/* returns 8 */
/* returns 2 */
MSG(), TSO only. Returns the MSG status of your TSO session. Alternatively, sets the
MSG status of your session. When MSG is on, TSO command messages are displayed;
when MSG is off, those messages are suppressed.
TM = MSG(OFF)
OM = MSG(ON)
Say MSG()
TM = MSG(OM)
Say MSG()
/*
/*
/*
/*
/*
*/
*/
*/
*/
*/
SYSAPPCLU:
SYSDFP
:
SYSMVS
:
SYSNAME :
SYSOPSYS :
SYSSECLAB:
SYSSMFID :
SYSSMS
:
SYSCLONE :
SYSPLEX :
SYMDEF
When using SYMDEF, you must supply both the word SYMDEF and the symbolic
variable name. Variables must be defined in the SYS1.PARMLIB member IEASYMxx.
OUTTRAP, TSO only. Captures the output from most TSO commands into a stem
variable you specify. The first entry of the stem variable, VAR.0, contains the number of
lines of output. You can also specify the number of lines to trap, from none (suppress all
messages) to all lines.
NOTE: some programs, such as the CONCAT command, produce output that cannot
be captured by OUTTRAP.
OUTTRAP syntax is one of the following.
TMP = OUTTRAP(LCDATA.) /* captures output lines from
*/
LISTC
/* the LISTC in the stem variable LCDATA. */
CALL OUTTRAP LINES.
LISTC
*/
/* displays 2007.102 */
/* displays DOT
*/
/*
/*
/*
/*
/*
*/
*/
*/
*/
*/
RANDOM(1,10)
RANDOM(1,10)
RANDOM(1,10,120345)
RANDOM(1,10,120345)
/*
/*
/*
/*
returns
returns
returns
returns
5
8
2
2
/* displays GOD
*/
*/
*/
*/
*/
Say SIGN(-9)
/* returns -1 */
Say STRIP(
LOTS OF
Displays LOTS OF
BLANKS
BLANKS
,T)
Say STRIP(MYUSERID.MY.CNTL,,)
Displays MYUSERID.MY.CNTL
As you can see from that last example, STRIP is useful for removing leading and
trailing quotes from fully-qualified dataset names.
NewString = SUBSTR(string,start,length,pad). Returns a part of string starting at start
for a length of length bytes. The pad character is used if length is longer than the
resulting substring.
Say SUBSTR(BOOKS,1,3)
Say SUBSTR(BOOKS,5,4,S)
/* Displays BOO */
/* Displays SSSS */
Say SYMBOL(BOOKS)
BOOKS = Blink
Say SYMBOL(BOOKS)
Say SYMBOL(.=)
/* Displays LIT
*/
/* Displays VAR
/* Displays BAD
*/
*/
SYSDSN(dataset-name) , TSO only. Tells you if a dataset exists and its current status.
Possible returns include:
OK
MEMBER SPECIFIED BUT DATASET NOT PDS
MEMBER NOT FOUND
DATASET NOT FOUND
ERROR PROCESSING REQUESTED DATASET
PROTECTED DATASET
VOLUME NOT ON SYSTEM
UNAVAILABLE DATASET
INVALID DATASET NAME
MISSING DATASET NAME
A simple example of how SYSDSN might be used.
/* REXX Quick JCL submit */
Arg MEMBER
JCLPDS = MY.JCL.CNTL(MEMBER)
PDSQ = SYSDSN(JCLPDS)
Select
When PDSQ = OK Then SUBMIT JCLPDS
When Left(PDSQ,6) = MEMBER Then Say PDSQ
Otherwise,
Say Some problem with JCLPDS. Error is PDSQ.
End
SYSPREF :
SYSPROC :
SYSUID :
SYSLTERM:
SYSWTERM:
SYSENV :
SYSICMD :
Am I in ISPF?
If SYSVAR(SYSISPF) = NOT ACTIVE Then Exit
TIME(option). Returns the current time in a specific format based on the option below.
TIME()
:
TIME(E):
TIME(E):
E.
TIME(H):
TIME(M):
TIME(R):
TIME(S):
hh:mm:ss
first time, starts the elapsed time counter
second time, displays the number of seconds since the first
hours since midnight
minutes since midnight
Resets elapsed time to zero.
Seconds since midnight
*/
*/
/* displays 12.65
*/
/* displays 12.6540 */
/* displays 12
*/
/* displays ISDODEA */
/* Displays FUN
*/
/* Displays 7 */
/* Displays 3 */
/* displays 4 */
/* displays 3 */
/* displays 17 */
/* displays 284 */