0% found this document useful (0 votes)
33 views

ISPF Programmers Guide

Uploaded by

Vasco Silvestre
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views

ISPF Programmers Guide

Uploaded by

Vasco Silvestre
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 349

Also of Interest

IBM z/OS ISPF Smart Practices, Vol. 1


Franz Lanz, 2015
ISBN 978-3-11-037548-0, e-ISBN (PDF) 978-3-11-037559-6,
e-ISBN (EPUB) 978-3-11-039788-8, Set-ISBN 978-3-11-0

Industrial Software Applications


Rainer Geisler, 2015
ISBN 978-3-11-037098-0, e-ISBN (PDF) 978-3-11-037099-7,
e-ISBN (EPUB) 978-3-11-039678-2

Entrepreneurship for Engineers


Helmut Kohlert, Dawud Fadai, Hans-Ulrich Sachs, 2013
ISBN 978-3-486-73298-6, e-ISBN (PDF) 978-3-486-76972-2

Analog Computing
Bernd Ullman, 2013
ISBN 978-3-486-72897-2, e-ISBN 978-3-486-75518-3
Author
Franz Lanz
Panoramaweg 27
72658 Bempflingen
Germany
ispf@lanz.de

ISBN 978-3-11-040753-2
e-ISBN (PDF) 978-3-11-040761-7
e-ISBN (EPUB) 978-3-11-040765-5
Set-ISBN 978-3-11-040762-4
Library of Congress Cataloging-in-Publication Data
A CIP catalog record for this book has been applied for at the Library of
Congress.
Bibliografische Information der Deutschen Nationalbibliothek
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der
Deutschen Nationalbibliografie;
detailed bibliographic data are available on the Internet
at http://dnb.dnb.de
© 2015 Walter de Gruyter GmbH, Berlin/Boston
Cover illustration: OlgaYakovenko/iStock/thinkstok
Typesetting: PTP-Berlin Protago-TEX-Production GmbH, Berlin
www.degruyter.com
Preface
Since approximately 1980, I worked many times with the Interactive System
Productivity Facility (ISPF) (a subsystem of z/OS driven by TSO) during my
activities as external advisor, programmer and lecturer in the IBM host. As the
name already says, this subsystem is designed to help the users in the IBM
Mainframe host environment to a higher productivity at their work in IBM
z/OS. I can promise you, ISPF fulfils this task very well.
As soon as I was more familiar with ISPF and so had outgrown to the beginners
stage, the desire emerged in me to automate and accelerate some recurring
operational sequences if possible. I have looked around myself on the book
market which book can support me with the realization of the desire on a high
level. However, I found no book, which would be suitable.
Since I developed at home and abroad a set of procedures and programs during
my lecturer, adviser and programming activities in different enterprises, which
brought me often a substantial accelerations of my work in z/OS, I decided to
publish my experiences in developing ISPF applications as well as the
developed programs in this book. This program collection is SMART ISPF
UTILITIES called. The procedures and programs described in this book can be
from internet downloaded.
This book will support you to reach your full potential in using ISPF as an
application programmer, a system programmer or another z/OS-ISPF user. You
will learn how you use the ISPF programming facilities to develop professional
ISPF application programs. Additionally you can enhance your programming
skills by referencing the programs of SMART ISPF UTILITIES available on
internet, in order to become a skillful ISPF application programmer.

Franz Lanz
Bempflingen, Mars 2015
Contents
Preface

1 Introduction
1.1 Users of this book
1.2 The significance of the REXX programming language in z/OS
1.3 Brochures for programming ISPF applications
1.3.1 The REXX programming literature
1.3.2 ISPF reference books
1.3.3 TSO reference books
1.3.4 The ISPF services

2 Introduction to the REXX programming language


2.1 What is REXX?
2.2 Overview of REXX under TSO
2.2.1 Recognizing a REXX procedure by the TSO
2.2.2 Running REXX procedures in the TSO
2.3 Compile REXX procedures
2.4 Performance of REXX procedures
2.5 The syntax of the REXX language
2.6 Variables in REXX
2.7 Data types of REXX variables
2.8 Operators of the REXX language
2.8.1 String operators
2.8.2 Arithmetic Operators
2.8.3 Compare operators
2.8.4 Logical operators
2.9 Stems in REXX
2.9.1 Initialize stems with null string
2.9.2 File processing in connection with stems
2.9.3 Multi-unit Stems

3 The REXX commands


3.1 ADDRESS – Connection to the subsystems
3.1.1 The host command environments
3.1.2 The active host command environment
3.1.3 The temporary addressing of external commands
3.1.4 Special case ISPEXEC and ISREDIT
3.1.5 The main host command environments
3.2 ARG – Retrieve the parameter string
3.3 CALL – Call other programs
3.4 DO groups and DO loops
3.4.1 The DO group
3.4.2 The DO loop
3.5 EXIT and RETURN – leaving the REXX procedure
3.6 IF and WHEN – check conditions
3.7 INTERPRET – generate REXX commands dynamically
3.8 NUMERIC – set computing options
3.9 PARSE – text fragmentation
3.9.1 PARSE ARG
3.9.2 PARSE VALUE WITH
3.9.3 PARSE VAR
3.9.4 PARSE SOURCE
3.10 PROCEDURE – Option for internal subroutines
3.10.1 Internal subroutines with PROCEDURE statement
3.10.2 Internal subroutines without PROCEDURE statement
3.11 QUEUE – Working with the TSO stack
3.11.1 The TSO/E data stack
3.11.2 Use options for the TSO/E Data Stack
3.12 SAY – Print texts
3.13 SELECT – Conditionally call alternative instructions
3.14 NOP – No operation
3.15 PULL – Enter data on the screen
3.16 TRACE – The strong debugging aid
3.17 SIGNAL – Jumping when errors

4 The REXX functions


4.1 General functions
4.1.1 ADDRESS – Get the active host command environment
4.1.2 ARG – Input parameter test or take
4.1.3 DATE – Date functions
4.1.4 TIME – Time functions
4.1.5 QEUED – Number of records in the data stack
4.1.6 SOURCELINE – Return a program line
4.1.7 USERID – Return the TSO user ID
4.1.8 VALUE – Create variable names dynamically
4.2 Arithmetic functions
4.2.1 ABS – absolute value of a number
4.2.2 DIGITS, FORM, FUZZ – Query options for arithmetic operations
4.2.3 MIN, MAX – Minimum and maximum value
4.2.4 RANDOM – Generate random numbers
4.2.5 SIGN – Return of the sign
4.3 Comparison Functions
4.3.1 COMPARE – Compare texts
4.3.2 DATATYPE – Determine data type
4.4 Conversion functions
4.4.1 C2D – Character to decimal
4.4.2 C2X – Character to Hexadecimal
4.4.3 D2C – Decimal to Character
4.4.4 D2X – Decimal to Hexadecimal
4.4.5 X2B – Hexadecimal to Binary
4.4.6 X2C – Hexadecimal to Character
4.4.7 X2D – Hexadecimal to Decimal
4.5 Formatting functions
4.5.1 CENTER – Centering a string
4.5.2 COPIES – Reproduce texts
4.5.3 FORMAT – Format numbers
4.5.4 JUSTIFY – Formatting a string
4.5.5 LEFT – Rearrange text left-justified
4.5.6 RIGHT – Arrange text right- justified
4.6 String functions
4.6.1 DELSTR – Delete substrings
4.6.2 INSERT – Insert text
4.6.3 SCHANGE – Change of texts
4.6.4 LENGTH – Length of a text
4.6.5 OVERLAY – Superimpose text
4.6.6 POS – Search for text
4.6.7 STRIP – remove border characters
4.6.8 SUBSTR – Extract part of a text
4.6.9 TRANSLATE – translate characters
4.6.10 VERIFY – verify text
4.7 Word functions
4.7.1 WORD – return of a word
4.7.2 WORDINDEX – return the starting position of a word
4.7.3 WORDLENGTH – return the length of a word
4.7.4 WORDPOS – search for a word
4.7.5 WORDS – number of words in a string
4.8System functions
4.8.1 LISTDSI – List data set information
4.8.2 MSG – control of the TSO messages
4.8.3 MVSVAR – Return z/OS system information
4.8.4 OUTTRAP – take TSO messages
4.8.5 SYSDSN – check data set status
4.8.6 SYSVAR – get system Information
4.8.7 STORAGE – read and write memory contents
5 The TSO/E REXX commands
5.1 EXECIO – Read and write data sets
5.2 DELSTACK – delete data stack contents
5.3 DROPBUF – Delete data stack buffers
5.4 TSO Commands

6 Execute REXX programs


6.1 Execution of programs in a TSO/ISPF environment
6.1.1 Online execution
6.1.2 Batch execution

7Introduction to ISPF programming


7.1 Programming languages useable in ISPF
7.2 ISPF programming objects
7.3 Some typical examples
7.3.1 Example for use of ISPF panels
7.3.2 Example for use of skeletons
7.3.3 Example for use of tables
7.3.4 Example for use of ISPF variables
7.3.5 Example for data processing with TSO and ISPF
7.3.6 Output of messages with ISPF
7.4 LIBDEF – Dynamic linking of ISPF libraries
7.5 ALTLIB – Dynamic linking of EXEC libraries
7.5.1 Search sequence in the procedures libraries
7.5.2 The ALTLIB command in ISPF
7.5.3 Stacking of the APPLICATION level ALTLIBs
7.5.4 The QUIET operand of the ALTLIB DISPLAY command

8 Data set processing using ISPF


8.1 The LM services
8.1.1 Grouping of LM services
8.1.2 LMINIT – Start of the data set processing
8.1.3 LMFREE – Free a data set
8.1.4 LMOPEN – Open a data set for processing
8.1.5 LMCLOSE – Close a data set
8.1.6 LMMFIND – Localize a member
8.1.7 LMMREP – Replace a member
8.1.8 LMMADD – Add a member
8.1.9 LMGET – Read a data records
8.1.10 LMPUT – Output data records
8.1.11 LMCOPY – Copy data
8.1.12 LMMOVE – Move data
8.1.13 LMMDEL – Delete members
8.1.14 LMMREN – Rename members
8.1.15 LMMSTATS – Display or change member statistics
8.1.16 LMCOMP – Compress a PDS
8.1.17 LMMLIST – Display a member list
8.1.18 LMMDISP – Display and edit a member list
8.1.19 LMDINIT – Initialize the LMDDISP service
8.1.20 LMDDISP – Data set list service
8.1.21 LMDLIST – List of data sets
8.1.22 LMDFREE – Free a LISTID
8.1.23 MEMLIST – member list dialog service
8.2 Data set query services
8.2.1 LMDLIST – Data set list service
8.2.2 DSINFO – ISPF service which provides data set information
8.2.3 LISTDSI – REXX function to list data set information
8.2.4 QBASELIB – Query DSN information
8.2.5 QLIBDEF – Query LIBDEF Information
8.2.6 QUERYENQ – ENQs determination

9 Messages – Definition, setting, output


9.1 Error handling in ISPF
9.1.1 Returning error messages
9.1.2 Output of error messages
9.1.3 SETMSG – Set next message
9.1.4 Definition of ISPF messages
9.1.5 Naming convention of the ISPF message IDs
9.1.6 Definition of messages
9.1.7 The standard message member ISRZ00

10 Panels – create and use


10.1 The Dynamic Tag Language (DTL)
10.2 Panel types in ISPF
10.3 Definition of panels
10.3.1 The structure of a panel
10.3.2 Creation of panels and their call
10.3.3 The panel definition sections
10.3.4 Variables in panel definitions
10.3.5 Panel processing
10.3.6 Help panels
10.3.7 Panels to display ISPF tables

11 Skeletons – Design and use


11.1 Creating skeletons
11.2 Steps to use the file-tailoring service

12 Tables – Create and edit


12.1 Locations for tables
12.2 Reading ISPF tables
12.3 Writing ISPF tables
12.4 Commands of the table services
12.5 Example of working with tables

13 Variables – Definition and using


13.1 Variables pools
13.1.1 Function pool
13.1.2 Shared pool
13.1.3 Profile pool
13.2 Saving the profile members
13.3 Creating profile members
13.4 Display of actually used profile member
13.5 The System Profile Pool
13.5.1 Frequently used ISPF variables
13.5.2 Process ISPF variables

14Edit macros – Create and apply


14.1 What is an edit macro?
14.1.1 Naming conventions for edit macros
14.1.2 Example of two very useful edit macros
14.2 Table of edit macro commands
14.3 Operands and abbreviations used in the edit macro
commands
14.4 Test aids in the creating macros
14.4.1 Prototyping
14.4.2 The REXX TRACE command as developing aid
14.4.3 The program ISREMSPY
14.5 System variables of the ISPF editor
14.6 Passing parameters to macros
14.7 Examples for editing and SUBMIT batch jobs
14.8 Mnemonics for macro programming

15The SMART ISPF utilities


15.1 Naming conventions
15.2 The dynamic panel concept
15.3 List of executable programs
15.4 Program descriptions
15.4.1 Edit macro ## – Execute a currently edited REXX procedure
15.4.2 Edit macro #ALTXT – Realign line parts
15.4.3 Edit macro #EDMEM – Edit of a member
15.4.4 Edit macro #IMACROA – General ISPF edit macro
15.4.5 Edit macro #IMACRO1 – Initial edit macro
15.4.6 Edit macro #IMACRO2 – Edit session end macro
15.4.7 Edit macro #ISPFB – Submit an ISPF batch job
15.4.8 Edit macro #LCH – Perform long edit change commands
15.4.9 Edit macro #SPLJ – SPLIT and JOIN lines
15.4.10 Edit macro #SSS – Clear SCHFOR lists
15.4.11 Edit macro #SSSCH – Mass update of members
15.4.12 Edit macro #SU – Submit JCL without a JOB statement
15.4.13 Edit macro #TSOB – Submit a TSO batch job
15.4.14 Edit macro #VERASE – Erase ISPF profile variables
15.4.15 Program SCURSOR – Calling a data set from an ISPF screen
15.4.16 Program SDOC – Produce documentation members
15.4.17 Program SLE – Display last edited data sets
15.4.18 SLOGDSN – Data member containing DSNs for logon
15.4.19 Program SLOGON – Personal logon procedure
15.4.20 Program SPROFEDT – Store users ISPF profile variables
15.4.21 SPROFVAR – Load user ISPF variables
15.4.22 Program SSC – Super clone for data sets
15.4.23 Program SSS – Perform a Super-Search
15.5 Programming aids
15.5.1 Edit macro #C – Compile and execute a REXX program
15.5.2 Edit macro #RO – Online compile of a REXX program
15.5.3 Edit macro #RC – Compile a REXX procedure with a batch job
15.5.4 Edit macro #RCLOAD – Produce a load or a call module
15.5.5 Edit macro #IE – Insert a call to ISPF_ERROR
15.5.6 Subroutine ISPF_ERROR – Display ISPF error messages
15.5.7 Edit macro #PAN – Execute a panel source code
15.5.8 Subroutine DAYDIFF – Calculate number of days
15.5.9 Subroutine ENDDAY – Calculate a target date
15.5.10 Subroutine JULDATE – Translate a date to Julian and vise versa
15.5.11 Subroutine LEAPYEAR – Return the leap year information
15.5.12 REXX subroutine SCHANGE – REXX change function
15.5.13 Program SDYNPAN – Convert a panel source code
15.6 Installation of SMART ISPF utilities
15.6.1 Download and unzip
15.6.2 Installation
15.6.3 ALTLIB command
15.6.4 Make the SMART ISPF utilities ready to run

List of programs

List of tables

List of screens

Bibliography

Index
1-Introduction
1.1-USERS OF THIS BOOK
This book has been comprised for ISPF users with programming skills. You will
learn how to insert and use your own functions in the ISPF using the procedure
language REXX together with ISPF programming facilities.

1.2-THE SIGNIFICANCE OF THE REXX


PROGRAMMING LANGUAGE IN Z/OS
Michael Cowlishaw and his team developed REXX in 1979 at the IBM laboratory
in Hursley GB for the mainframe operating system MVS. Since this time many
z/OS applications using the programming language REXX have been developed
in IBM labs worldwide. Almost all of these applications run under the control
of ISPF. This shows that IBM to the programming language REXX attaches great
importance.

Other REXX implementations:

REXX is now available on all major computer platforms. I would particularly


like to mention The REXX Language Association here. This association
develops and maintains the object-oriented REXX version OOREXX. Use the
internet link www.rexxla.org to get more information. I use OOREXX on my
own Windows PC for many tasks, e.g., control of backups, printing of a list for
all my stored movies.

1.3-BROCHURES FOR PROGRAMMING ISPF


APPLICATIONS
The following subchapters describe which brochures are needed for
programming ISPF applications.

The required books are divided into following groups.


–Books that describe the REXX language.
–Books that describe the ISPF programming facility enhancements.
–One book that describes the TSO/E commands usable in REXX programs.
1.3.1- The REXX programming literature
There are many books on the market describing the REXX language. Now there
are several implementations of the REXX language in a variety of computer
systems available. For the use of REXX under TSO-E and ISPF, the official
brochure of IBM is the most important one. I use for my REXX programming in
ISPF the following two books:

1.3.1.1- TSO-E REXX Reference


IBM form number SA22-7790.

This book is the official REXX language publication of IBM. It contains


descriptions of all aspects how REXX can be in the TSO-E environment used.
First, this brochure contains the description of the REXX commands. In
addition, the following topics are discussed in detail:
–Debug aids.
–TSO/E REXX programming services
–TSO/E REXX customizing services
–Language Processor Environments
–Initialization and termination routines
–Replaceable routines and exits

These chapters are only of interest to programmers who want to use REXX
programs under special conditions as there are:
–Calling subroutines written in Assembler language.
–Calling REXX programs by programs that are written in other languages.
–Writing REXX execs to perform MVS operator activities.

1.3.1.2- The REXX Language


Published 1990 by Prentice-Hall Inc. ISBN 0-13-780651-5.

The father of the REXX programming language Michael Cowlishaw wrote this
book. It contains descriptions of all elements of the language without describing
implementations in single carrier systems. I use this book often for creating
REXX programs, because it is also helpful to create REXX programs under MS
Windows just because it only contains the description of the REXX language and
nothing else.
1.3.2- ISPF reference books
Of course, for such a big subsystem as the ISPF many reference books are
available. You can find these books free of charge in IBMs internet book
libraries. They are available in two types:
1.As PDF books for downloading to your PC.
2.For direct display with an internet browser.

In the following chapter, I will show you where you can find all information to
develop ISPF applications. Unfortunately, IBM changes methods from time to
time to find a certain type of reference book. You can use the following steps:
1.With the following URL you reach the general z/OS literature frame:
2.http://www-03.ibm.com/systems/z/os/zos/library/bkserv/
3.You can click on the line z/OS V2R1 documentation in PDF format. This
action leads you to z/OS V2R1 Elements and Features selection menu. When
a new release of z/OS appears, the text V2R1 may change.
4.Now press Cntrl+F and enter the search text ISPF. The browser positions the
cursor on z/OS ISPF.
5.Click on this line and see the group of available ISPF publications.
6.Click on the book you want and the book is opened in your PDF reader. You
can now save it on your PC for later use.

There is a direct link to the ISPF Library


http://www-01.ibm.com/software/awdtools/ispf/library/

Under this link, you will find ONLY ISPF reference books. However, also earlier
releases are listed.

The IBM form number:


All books within the IBM z/OS library have a dedicated Form Number. The
IBM form number consists of three blocks of information each separated by a
hyphen:
1.The first part is a four-character item: two alpha characters and a two-digit
number. e.g., SC19 stands for all ISPF books.
2.The second part is a four-digit number defining the book within its group.
3.The third part is a two-digit number continuously counted upward for this
book.

Table 1.1 on page 4 shows the ISPF reference books designed for ISPF
programming purposes and their form numbers for z/OS release V2R1:
Table 1.1: Reference books for the programming of ISPF applications

Title Form number

z/OS ISPF Dialog Developer’s Guide and Reference SC19-3619-00

z/OS ISPF Dialog Tag Language Guide and Reference SC19-3620-00

z/OS ISPF Edit and Edit Macros SC19-3621-00

z/OS ISPF Messages and Codes SC19-3622-00

z/OS ISPF Reference Summary SC19-3624-00

z/OS ISPF Services Guide SC19-3626-00

Hint:
If you are searching for a book using the form number, then you should use only
the basic number without the release appendix. The system then shows all
available titles and you can choose the proper exemplar.

The following listing shows such manuals you should have as an ISPF
programmer:

1.3.2.1- Books for ISPF application programmers


SC19-3621 → ISPF Edit and Edit Macros
This book contains the normal handling procedures for the ISPF editor as well
as the programming commands and rules for the development of Edit
Macros. As you will see later, many edit macros are included in the SMART ISPF
utilities.

SC19-3624 → ISPF Reference Summary


This manual contains short references for all commands and their parameters.
This is the right book if a programmer is familiar in developing ISPF
applications.

SC19-3619 → ISPF Dialog Developer's Guide and Reference


This manual describes the development of applications in an ISPF environment.
The description for producing panels does not contain the use of the Dialog Tag
Language.

SC19-3626 → ISPF Services Guide


This manual contains descriptions of all facilities, rules and techniques used for
ISPF programming.

1.3.3- TSO reference books


As I mentioned above, ISPF is running under control of TSO. Sometimes you
need the assistance of TSO, e.g. for data set access. Therefore, it is necessary to
know where you can find information concerning TSO commands. You need
only one book from the wide range of available TSO reference books:

TSO/E Command Reference Form Number: SA22-7782

1.3.4- The ISPF services


ISPF offers many services to program ISPF applications. To use these services
in REXX application programs, ISPF offers dedicated commands for each
service. Table 1.2 on page 5 shows the ISPF service groups and their usage:
Table 1.2:- ISPF service groups

Service Group Used for

Display Service display of panels and tables

LM Service working with libraries (LM stands for Library Management)

Table Service working with ISPF tables

FT Service dynamic production of JCL by using skeletons

Q Service query services

V Service handling of ISPF variables


Commands to use these services in a REXX program are described in later
chapters.
Conclusion concerning the theme ISPF literature released by IBM:
I would first like to emphasize that the IBM literature for the entire z/OS system
is very good. However, as always in the IBM brochures, all aspects of commands
are explained in detail and for the beginner it is sometimes difficult in the
application of commands to apply a command properly for the achievement of
a specific purpose. One aspect of this book is to explain readers the commands
always in connection with a specific goal. Finally, yet very important, this is a
major reason why I have written this book.

2-Introduction to the REXX


programming language
2.1 - WHAT IS REXX?
The IBM brochure TSO-E REXX Reference, form number SA22-7790 contains
the following short description:

The REstructured extended eXecutor (REXX) language is particularly suitable for:


–Command procedures
–Application front ends
–User-defined macros (such as editor subcommands)
–Prototyping
–Personal computing.

Individual users can write programs for their own needs.


REXX is a general-purpose programming language like PL/I. REXX has the usual
structured-programming instructions – IF, SELECT, DO WHILE, LEAVE, and so on
– and a number of useful built-in functions.
The language imposes no restrictions on program format. There can be more than
one clause on a line, or a single clause can occupy more than one line. Indentation
is allowed. You can, therefore, code programs in a format that emphasizes their
structure, making them easier to read.
There is no limit to the length of the values of variables, as long as all variables fit
into the storage available.
So far the short description contained in the official publication concerning the
REXX language under z/OS.
The following excerpt contained in the preface of Michael Cowlishaw's book
explains his basic ideas for developing REXX. See section 1.3.1.2 The REXX
Language on page 2.

The REXX programming language has been designed with just one objective. It
has been designed to make programming easier than it was before, in the belief
that the best way to foster high quality programs is to make writing them as
simple and as enjoyable as possible. Each part of the language has been devised
with this in mind; getting the design right for people to use is more important
than providing for easy implementation.
A programming language is a complex structure, typically characterized by its
most visible aspect – its syntax. Of equal importance is its semantics, the meaning
behind the instructions. But perhaps most important of all is the philosophy
behind the language – the guiding principles that governed the decisions made as
the language was designed.
Guideline for the development of REXX
I met Michael Cowlishaw at the 25th anniversary of REXX and he told me that
during the development of REXX in the following sentence hung on the wall his
office:

Keep the language small!

Mike Cowlishaw gave us with REXX a language that really of a minimal


vocabulary consists. The programs developed with REXX are indeed small.

2.2 - OVERVIEW OF REXX UNDER TSO


REXX is a procedural language. This means that you need an interpreter to
execute a REXX procedure. The TSO contains a REXX procedure interpreter.
That is, REXX programs runs in TSO like a TSO command. Before the REXX
procedure language interpreter was integrated in the TSO, there was already
the CLIST interpreter available. Therefore, a method had to be introduced
where the TSO can be see that a program contains REXX code and it is not a
CLIST.
2.2.1- Recognizing a REXX procedure by the TSO
The TSO Command Processor interprets a procedure as a REXX program if the
first line of the program contains the text REXX or rexx. When the first line
misses one of the words REXX or rexx, then the TSO command processor
assumes that it is a procedure of type CLIST and passes the procedure to the
CLIST procedure processor. This requirement means that the first line of a
REXX program executed in the z/OS TSO must always be a comment line
containing the text REXX or rexx. As an example, here the program head of one
of my REXX procedures:

2.2.2- Running REXX procedures in the TSO


Call and execute REXX procedures as follows in the TSO:

1. Explicitly by the TSO EXEC command.


When using the TSO command EXEC to execute a REXX program member, it is
determined directly in the EXEC command operands. This means that a
member that contains a REXX procedure is executable from each PDS.

Example:
TSO EXEC 'dsn(member)’

The EXEC command still knows a number of options that are only interesting
for special cases. See the command description in the manual TSO-E
Reference in chapter EXEC Command.

2. Implicitly by calling up as a TSO command.


In this case, there are several possibilities to call up a REXX program:
–Only the name of the REXX procedure as a TSO command is entered. E.g .: TSO
pgm. In this case all allocated system and user load libraries are searched for
this program name. If the name is not found there, then the SYSEXEC and
SYSPROC libraries are scanned.
–To call a REXX program you can alternatively use the command TSO
%name. In this case only the SYSEXEC and SYSPROC libraries are scanned for
the program.
–When a REXX program to be executed is not found in any of the existing
allocated libraries, you can use the command ALTLIB to allocate the required
library temporarily and then use one of the two methods mentioned above for
calling. See chapter 7.5 ALTLIB – Dynamic linking of EXEC libraries on page
126.

3. Implicitly by calling up as an ISPF command in a DSLIST display


panel.
To execute this type of call see the following panel:
Screen 2.1: Example of a command call in a DSLIST display panel

In this case, the following will happen:


The program compdate is searched in all allocated LOAD and EXEC libraries. If
it is found, it is executed and the DSN standing in this line and the
text april are passed as parameters to the program. For this type of call, a slash
(/) represents the DSN standing in this line. Depending on the position where
the program expects the DSN in the takeover of the parameters, the slash is to
be in accordance with the position.

4. Implicitly invoked using the ISPF SELECT service


The following example shows the execution of a small REXX program using the
ISPF SELECT service from a data set, which is temporary allocated by the TSO
ALTLIB command.

This is the same execution of the program compdate as shown in Screen 2.1 on
page 10.
For information about ISPF SELECT service, refer to the IBM ISPF Services
Guide. Information on the use of ALTLIB command, see section 7.5 ALTLIB –
Dynamic linking of EXEC libraries on page 126. The ALTLIB command also has
a display option. I once had the above program executed without the ALTLIB
DEACTIVATE command and then ran the command ALTLIB DISPLAY manually.
I received the following display:

2. - COMPILE REXX PROCEDURES


In some z/OS systems, a REXX compiler is available. Therefore, you can compile
REXX procedures before executing them. The REXX compiler is also able to
produce genuine z/OS load modules. These load modules can be executed in a
batch job using the JCL statement EXEC PGM=NAME. Since the focus of this
book is the ISPF and the REXX, compiler topics would go beyond the scope of
this book too far, unfortunately I have to refrain from treating the REXX
compiler. However, you can find in the SMART ISPF utilities procedures to
generate cexec and load modules using the REXX compiler. See section:
15.5 Programming aids on page 273 and the subsequent pages.

2.4 - PERFORMANCE OF REXX PROCEDURES


When running REXX procedures, each statement must be interpreted by the
system. This, of course, requires computing time, which is added to the time of
execution of the REXX commands. The currently available host processors are
so fast that in practice hardly an execution time difference between an
interpreted REXX procedure and a compiled program are detectable. If there is
concern about the performance of REXX procedures, you should first take a
closer look at the greatest performance brakes. The following operations
normally slow down the execution of a REXX program the most:
–I/O operations.
–Loading of external procedures and load modules.
–Calling external system functions.

Therefore, it is advisable to always start first at these points with actions for
performance improvement. You should not expect too much of compiled REXX
procedures because of the following reasons:

Performance tips:

1. Compiled programs:
The time needed to perform the called ISPF and TSO functions is usually much
higher than the execution time required for the pure REXX code. Thus, it is
usually not advisable to use compiled REXX procedures. I have gained this
knowledge from working in a very large project with hundreds of compiled
REXX programs.

2. Functions and subroutines


Functions and subroutines that do not belong to the scope of functions of REXX
are loaded every time when they are called from the external data set. It is
obvious that this can be a significant performance brake. I strongly recommend
investigating your programs for such performance brakes and if necessary,
copying the source code of these programs into the main program. The fastest
way to detect such a speed brake is the execution of this program in a batch job.
After the program execution, you can check the SDSF as to how many EXCPs the
program has consumed. If the EXCP count is exorbitantly high, then it is obvious
that a function or subprogram was continuously loaded.

2.5 - THE SYNTAX OF THE REXX LANGUAGE


The syntax of the REXX language is very simple and strongly influenced by PL/I:
–A statement is normally always in a row. A semicolon normally terminates it.
However, it does not have to be explicitly completed!
–Multiple statements on one line must each be terminated with a semicolon
except the last one. The last statement can of course also terminated with a
semicolon.
–If a statement is continued on the next line, then the preceding line must end
with a comma (,). This also applies to literals. The continuation comma itself is
always replaced by a blank. If this blank should be avoided, then the two literal
parts must be concatenated with the concatenation operator (||).
–Blank lines are allowed in the program code.
–Comments always begin with /* and end always with */. All texts between
these two limits belong to the comment even if they span multiple lines and
contain REXX commands. Comments can be wherever a blank is allowed be
placed within a statement and they can be nested. Note: When the pairing of
the comments is interrupted, it may happen that the rest of the program
remains as a comment.
–Literals are put in paired quotation marks or apostrophes. There are three
types of literals:
–Text literals. These literals can contain any text, and it can be defined over
several lines. One literal must not exceed 250 characters.
–Hexadecimal literals. They can only contain hexadecimal digits and must be
completed by the letter x or X. The individual bytes can be, separated by blanks,
entered.
–Binary literals. These can only contain 0 and 1 and must be completed by the
letter b or B respectively. The individual bytes and half-bytes can be separated
by blanks.

Examples of correct REXX statements:

Here you see an example of continuation lines in the definition of text literals.
Keep in mind that the continuation character in the resulting text appears as
blank. Therefore, you should always define continuation lines of literals so that
the resulting text contains a blank at this point anyway.

Rules for inserting comments and blanks in REXX statements.


After defining the rules, you will see a sample program that shows the
applications of the rules. In the description of each rule there is always
reference to the program line to which this rule applies.
–In general, comments that are inserted in a statement will be removed before
executing the statement. Lines 06, 07, 08.
–If the statement after the removal of the comments is executable, it is executed.
–If multiple blanks between the elements of a statement are present, they will
be removed down to a single blank. Line 05.
–For functions that contain parameters in a pair of parentheses, a blank is never
allowed between the function name and the opening parenthesis. Line 10: The
blank in column 30 that remains when the comment is removed, is not allowed.
Program 2.1: Example for handling blanks and comments in REXX programs
If this program is running, the following output is displayed:

2.6 - VARIABLES IN REXX


Rules:
–REXX variables cannot be explicitly defined before use.
–The type of a variable can only be CHAR or NUM. It is always defined by the
content of the variable. The type is determined after each assignment of a value.
This means that, REXX variable can continuously change their data type
between CHAR and NUM depending on which data was assigned last.
–The length of the variable name can have a maximum of 250 characters.
–If a variable is used without a previously assigned value, then its content is
always equal with the name in uppercase letters.
–A variable that is not the type NUM by functions or external input assigned
must be explicitly assigned a numerical value before it can be used in an
arithmetic operation.
–The length of a character string variable must not exceed 16MB.
Remark:
One of the most elegant facilities in REXX is that variables do not need to be
defined prior to use. I remember that using other programming languages, I
very often got the error message Undefined variable during program
execution. Sometimes I needed several test runs until I found all the missing
variables.

Example:
When you perform the statement:

The display is:


When execute the following statement.

and you perform the above say statement again

The display is now: fred

2.7 - DATA TYPES OF REXX VARIABLES


As mentioned above in REXX knows only two data types of variables. These
are NUM for a numerical content and CHAR for all other contents. As
explained above, the data type is determined internally on each assignment
of a value to a variable. It cannot be explicitly specified in the program, but
the function DATATYPE(var) can used to query the data type of a variable.
Here is a short list showing the data types of the variable HUGO after an
appropriate assignment of values:

Rule:
The resulting data type is only NUM when an admissible number in the sense
of REXX is assigned to it. Permissible blanks in HEX and BIN strings are
removed by the REXX assignment command.

Null strings:
A special type of data is the null string. This type of data is often assigned to
variables if no result of an executed command is present. The null string is
determined as a literal by two consecutive apostrophes. Null strings are of data
type CHAR and have a data length of 0 (zero). Examples of definition and query
of null strings:
2.8 - OPERATORS OF THE REXX LANGUAGE
The operators define the operations which with variables and constants are to
be performed. Types of operators:
–String operators
–Arithmetic operators
–Comparison operators
–Logical operators

2.8.1- String operators


Here we meet one of the greatest strengths of REXX. To merge text, you simply
write the various constants and variables in one statement. The following rules
apply:

Rules:
–If in a statement between the constants and variables there is more than one
blank, the result is at this point only a single blank.
–If you want to prevent the automatic insertion of blanks, elements with the
concatenation operator (||) need to be connected. Blanks that stand on the left
or right of the concatenation operator are ignored in this c5ase.
–If you want to insert multiple blanks, they must be defined as a literal in
quotation marks.
–The concatenation operator is not necessary when individual elements of the
statements can be clearly recognized by the interpreter.

Examples:
This program example shows how texts can be assembled.

When executed, the program produces the following list output:


2.8.2- Arithmetic Operators
The following table lists the arithmetic operators:
Table 2.1: Arithmetic REXX operators

Operator Function

+ Addition

- subtraction

* multiplication

/ Division

% Integer division. The rest is suppressed, the result is not rounded.

// Integer division with return of the rest.

** Potentiation. Only integers are as powers allowed.

The + and – signs can be set as a sign in front of variables and constants.

Example:

When executed, the program produces the following list output: 3 1 -3 4 1 30%
2.8.3- Compare operators
Table 2.2: Compare operators

Operator Description

= Simple equal

> Greater than

< Less than

>< Not equal

<> Not equal

>= Greater than or equal

\<, ¬< Not less than

<= Less than or equal

\>, ¬> Not greater than

== Strictly equal

\= =, ¬= =, /= = Strictly not equal

>> Strictly greater than

<< Strictly less than

>>= Strictly greater than or equal

\<<, ¬<< Strictly not less than


<<= Strictly less than or equal

\>>, ¬>> Strictly not greater than

Note:
The result of a comparison is always 0 or 1 and of type NUM.
Therefore, the result of a comparative operation is usable in arithmetic
operations.

What is the difference between the strictly and the normal comparison?

In normal comparison:
–If at least one of the compared values is of type CHAR then both leading and
trailing blanks are removed. Then the shorter value is padded with blanks until
it has the length of the other value. Then the comparison is performed.
–If both comparative values are of type NUM, one value is subtracted from the
other one. The result is then greater than zero, equal to zero or less than zero.

In strictly comparison:
–No padding of CHAR type values take place.
–Values of type NUM are compared character by character from left to right
rather than with a subtraction.
–Values of different lengths are always NOT equal.

The following example shows how to use comparison operators in arithmetic


instructions. This subroutine calculates the “Julian Day” within a year in a
singlestatement:
Screentext 2.1: Example for using combinations of arithmetic and
comparative operators
This program produces the following printout:

See also Program 15.6: Subroutine JULDATE on page 282.

2.8.4- Logical operators


The logical operators are usually only used in logical statements, such as IF,
WHEN etc. The following table shows the logical operators:
Table 2.3: Logical operators

Operator Description

& Returns 1 if both expressions are true.

! Returns 1 if at least one of two expressions is true.

&& Returns 1 if one of two expressions is true, but not both.

Prefix \¬ Negates a logical expression.

2.9 - STEMS IN REXX


Stem are something similar to dimensioned arrays in other programming
languages. STEMS start with a variable name followed by a dot. The values
behind the point are something similar indices. These indices can
be numbers and any text.
In the REXX literature, stems are also referred to as Compound Variables. This
means that a variable hugo.1 as long as the content HUGO.1 has until it is be
assigned a different value. In simpler terms: Each stem variable per se is a
normal variable; it is only written differently. In addition, you can work based
on composition by the details behind the points easier with a whole set of
variables each with an own name.
My experience is for understanding the stems, beginners in REXX are faced with
greater difficulties. The following small examples show how this technology
works.

Example program for using stems:

Task:
The dataset user001.flight.data(flights) contains the flight log of the performed
flights. I wanted to know how many flights I have on the individual aircraft
types carried out and how many hours with each type. I did not know
beforehand how many aircraft types were used in total. During the program
run, the types must be successively detected and stored
Program 2.2: Program FLIGHTS to explain the using stems and EXECIO

See the output of the program:


Explanation:
There are three stems used in this program:
flights. This stem is of type CHAR and is filled by the EXECIO TSO command. It is
used in the DO loop by addressing the single data records by the DO loop
variable i. The variable flights.0 contains the number of read records. The
EXECIO command fills this variable.

ft_nbr. Due to the pre-definition statement ft_nbr. = 0 is this stem of type NUM. This
allows that 1 can added continuously to count the number of flights. The index
is always the name of an aircraft type.

ft_std. Due to the pre-definition statement ft_std. = 0 is this stem of type NUM. This
allows that the time of a single flight can be added continuously. The index is
always the name of an aircraft type.

This example also shows how stems are used for data set processing!

2.9.1- Initialize stems with null string


The following program example illustrates the effect of stems null string
assignments:

The program prints the following lines:


As you can see, not all explicitly value assigned positions of the stem hugo. are
as null strings printed.

2.9.2- File processing in connection with stems


In the Program 2.2: Program FLIGHTS to explain the using stems and EXECIO
on page 20, shows an example how stems are used in the file processing. I will
now explain this topic in principle.
When processing data sets, REXX can read all records of a file with a single
command in a stem or write all elements of a stem to a data set. Let us look at
an example of data set processing:

The EXECIO command reads all the records of the file in the stem save.. You
will now ask: Where is the information about how many records are read?
Rule:
All functions that populate a REXX stem from the outside with a variable
number of records, write the number of records in the index 0 (zero) of the
stem. In the above example, after the EXECIO command has been executed
contains save.0 the number of records read.

2.9.3- Multi-unit Stems


You can also create stems, which are not only divided by one point, but also by
several ones. The assignments look like this:

The SAY output is then:

Advice:
If you are using texts in indices of stems, of course, you must be sure that you
address these variables properly. As an example, see Program 2.2: Program
FLIGHTS to explain the using stems and EXECIO on page 20.
As for all variables in REXX, also applies for STEMS the rule, that a stem variable
as long their own name in uppercase letters as content has until it gets explicitly
another content. This rule applies only when the stem was by a general null
string assignment not predefined. For clarification, we look at the following
examples:

The gray stem variables were not assigned to a value, so their names appear as
the content. When I initialize hugo. with null string the result looks like this:

The result is then:

See also the Remark in section 2.6 Variables in REXX on page 14.

3-The REXX commands


In the following chapters, I would like to present the key REXX commands as
they are available under TSO. In addition, I will be less responsive to the formal
syntax. You can always read this in the brochure. Rather more, I will make you
acquainted with the aid of examples of the application of the REXX commands.
I programmed these examples separately for illustrating the application of
them, but sometimes I also use examples from my programs used in practice.
3.1 - ADDRESS – CONNECTION TO THE SUBSYSTEMS
If you are concerned about the practical usability of a programming language,
you will very quickly recognize that in the practical operation of the IT you
cannot do very much with the functions of the language alone. You could write
a program to calculate prime numbers or to issue a winning lottery numbers.
However, when you want to expand the view of your program, e.g. to read a file
or display a panel, you need the help of ministering angels, namely the support
of the subsystems of the z/OS in general and of the TSO/ISPF in particular.
Generally, there are several ways to use services from environmental systems:
–By the use of subroutine calls, such as for GDDM (Graphical Data Display
Manager).
–Due to special instructions that are included in the source code of a program
but not directly understood by the language. A pre-compiler that converts the
special instructions in subroutine calling for the subsystems must process these
programs. For example, EXEC SQL, EXEC CICS.

In REXX a method was developed that is unrivaled and best in my opinion. You
can call this method a window or channel method. In order to understand this
method, we first need to look at a concept that plays a decisive role. These are
the external system environments. The correct name is Host Command
Environment.

3.1.1- The host command environments


The host command environments are nothing more than subsystems within
our TSO/ISPF environment that allow us to provide services available and to
which we can establish a connection from the REXX to use these services. These
include the TSO, the ISPF, the ISPF editor, MVS, the LINK service etc.
The ADDRESS command establishes the connection. This command has the
following form:

subsys SUBSYS is the name of a host command environment. This name has a maximum of 8
characters and must designate a host command environment which is addressable in our
TSO/ISPF environment. SUBSYS can be specified as either a literal as well as just a name.

variable This variable contains the name of a host command environment.


Note:
If the ADDRESS command is specified without operands, the system returns to
the one host command environment which was active before the ADDRESS
command. However, this command cannot switch back by several steps; it only
works like a FLIP FLOP process. The following example demonstrates this effect
in the rows 13 and 15.

Example:
The following sample program shows a comprehensive application of the
ADDRESS command.
Program 3.1: Examples of ADDRESS command

The SAY commands in the above program produced the following output:

I hope that this example can answer all questions related to the application of
the ADDRESS command exhaustive. Now the question arises: How the
commands come to the right subsystems. The following chapter explains this.

3.1.2- The active host command environment


Rules:
–Whenever in a REXX program sequence a command appears that consists only
of a literal, this text is passed to the active host command environment.
Whether the currently active host command environment can do something
with the text will be decided by itself.
–A specific host command environment is activated with the
command ADDRESS subsys which shall be a single command in REXX. This
selected host command environment remains active until another individual
ADDRESS command is executed to another environment. Nesting of host
command environments is not possible. There is also no redemption command.
This means that when you run REXX procedures under TSO/ISPF one host
command environment is always active.
–If a REXX program starts under TSO/E, the TSO host command environment
is always automatically active. This means that all external commands, which
are not explicitly directly addressed to another subsystem are passed to the
TSO for execution.

3.1.3- The temporary addressing of external commands


Whichever host command environment is currently active, with an ADDRESS
subsys command immediately followed by the external command, an external
command can be sent to each other host command environment. However, the
active host command environment is not changed in this case.

Example:
The program section shown below indicates the beginning of one of my
programs. The special feature of this is that the program can be online directly
under ISPF or in TSO batch and without ISPF run. Since when running in batch
the STEPLIB DD statement for the load library is contained in the job, the ISPF
command LIBDEF ISPLLIB is not necessary in this case. Therefore, I use a
temporary ADDRESS command to run each LIBDEF ISPLLIB. Note the
continuation comma that is behind each address “ISPEXEC”, characterizing
the next line is still part of the address ISPEXEC and forms a complete REXX
command. I deliberately chose this example to make you familiar with the
intricacies of continuation lines related to ADDRESS.

The commands in lines 9 to 12 only apply when the program runs online
executed in ISPF. Lines 17 through 19 are TSO commands. Because I have not
changed the active host command environment since starting the program, TSO
is still active. Therefore, these external commands are sent to TSO. For
description of the LIBDEF command, see section 7.4 LIBDEF – Dynamic linking
of ISPF libraries on page 123.
Remark:
In many REXX program examples, you can see the following use of the ADDRESS
commands:

The value after address is a fixed value, not a variable. When you assign the
variables TSO or ISPEXEC a value, then has this no effect on the execution of
ADDRESS commands. You can put the name of the environment in quotes.
However, this is not required! If one has an environment using the ADDRESS ()
function stored in a variable, then you have to use the version address
(remaddr) to restore the environment. remaddr is the variable that was
assigned by the function ADDRESS().

Here is another example from one of my programs:

The program sends its external commands up to line 84 to TSO. If OUTIND is


then = 1, the two commands TSO ALLOC and EXECIO are performed initially.
Thereafter, the environment is switched to the ISPF as recipients for external
commands. Lines 88 to 91 contain only ISPF commands. In line, 92 the active
environment is switched back to the TSO. Thus, the FREE command in line 95
is executable.
Rule:
When you want to execute the instruction address “TSO” “alloc ...” then you
must not write “TSO alloc ...”. Because in this case, the text “TSO alloc ...” would
be understood by the REXX interpreter as a name for a host command
environment. This name must not be longer than 8 characters. The REXX
interpreter then responds with the error message: “Environment name too
long”. Therefore, you must always disconnect the name of the host command
environment from the text to be passed to the environment by typing both texts
as individual one or put the name of the environment in quotation marks and
put the literal behind with the external command.

3.1.4- Special case ISPEXEC and ISREDIT


If the active host command environment is TSO, you can issue commands to the
ISPF with the prefix “ISPEXEC and enter those to the ISPF editor when
executing edit macros with the prefix “ISREDIT without a corresponding
ADDRESS. Note that behind the environment name, no quotation mark may be
set and the command to be sent to the host command environment follows
immediately.

Examples:

Note:
This technique works only if the actual host command environment
is TSO. Within all other permanently active host command environments, you
cannot work with this method.
Tip:
I have been accustomed for a long time, in principle; always keep in REXX
programs in which I use the three host command environments TSO, ISPEXEC
and ISREDIT the TSO as an active environment. In addition, use for the two
environments ISPEXEC and IRSEDIT the corresponding prefix. That makes a
little more work on the keyboard, but it makes me free from the obligation of
constantly having to remember the currently active environment. However,
this procedure is a matter of taste. Look for your own style!

3.1.5- The main host command environments


The following table shows the most important host command environments
that are usable under TSO/E. I copied this table from the IBM z/OS TSO/E
REXX User's Guide.
Table 3.1: REXX host command environments

Environment Function

TSO the environment in which TSO/E commands and TSO/E REXX commands
execute in the TSO/E address space.

MVS the environment in which TSO/E REXX commands execute in a non-TSO/E


address space.

LINK an environment that links to modules on the same task level.

LINKMVS an environment that links to modules on the same task level. This
environment allows you to pass multiple parameters to an invoked module,
and allows the invoked module to update the parameters. The parameters
you pass to the module include a length identifier.

LINKPGM an environment that links to modules on the same task level. This
environment allows you to pass multiple parameters to an invoked module,
and allows the invoked module to update the parameters. The parameters
you pass to the module do not include a length identifier.

ATTACH an environment that attaches modules on a different task level.

ATTCHMVS an environment that attaches modules on a different task lev l. This


environment allows you to pass multiple parameters to an invoked module,
and allows the invoked module to update the parameters. The parameters
you pass to the module include a length identifier.

ATTCHPGM an environment that attaches modules on a different task level. This


environment allows you to pass multiple parameters to an invoked module,
and allows the invoked module to update the parameters. The parameters
you pass to the module do not include a length identifier.

ISPEXEC the environment in which ISPF commands execute.

ISREDIT the environment in which ISPF/PDF EDIT commands execute.

CONSOLE the environment in which MVS system and subsystem commands execute.
To use the CONSOLE environment, you must have TSO/E CONSOLE
command authority and an extended MCS console session must be active.
You use the TSO/E CONSOLE command to activate an extended MCS
console session. See z/OS TSO/E System Programming Command
Reference, for more information about using the CONSOLE command.

CPICOMM the environment that allows you to invoke the SAA common programming
interface (CPI) Communications calls.

LU62 the environment that allows you to invoke the APPC/MVS calls that are
based on the SNA LU 6.2 architecture. These calls are referred to as
APPC/MVS calls throughout the book.

APPCMVS the environment that allows you to access MVS/APPC callable services
related to server facilities and for the testing of transaction programs.

Notes:
I will cover only the grey marked environments in this book. There are many
other host command environments available. One example is the environment
to DB2. You find information on this environment at the following
URL: http://mainframe-tips-and-tricks.blogspot.de/2011/12/sample-db2-
rexx-program.html.

3.2 - ARG – RETRIEVE THE PARAMETER STRING


Tip:
If you want to pass multiple parameters to REXX programs at their call,
separate them with BLANKS. Of course, this is only good if in the individual
parameter values themselves no blanks must be included. It does not matter
how many blanks are between the individual parameter values.
The following program contains several examples of how you can pass in and
take over the parameters:
Program 3.2: ARGTEST – Example of the parameter handling in REXX
This program contains two internal procedures. These fulfill the following
tasks:
Procedure Task

SUBR Acquisition of call parameters and disassemble them with different methods. Calling the
subprogram OUT to show the results of decompositions.

OUT Outputting the results by SAY

Here is a brief description of the important lines of ARGTEST program:


Line Description

5 Zeroing the line counter for outputting the results

8 CALL of subroutine SUBR with one parameter

11 FUNCTION call of subroutine SUBR with two parameters.


17 Label and entry point of subroutine SUBR.

18 Print the number of parameters entered by using the ARG function.

19 Take the first parameter in the variable IP1. In this type of taking over, the parameter values
are translated in upper case.

23 This statement divides the text of the first parameter into up to four parts when at least four
terms separated by blank are present in the text. The dot at the end means that all parts of
the text that lie behind the four words are ignored. During the transfer, with “PARSE ARG”
the texts are not set in upper case.

27 Here IP1 is divided so that all the texts that are between commas are written in the
corresponding tags. If no comma is found in IP1, the entire contents of IP1 is contained in
variable A1.

29 Asks whether more than one parameter is passed. If so, then a PARSE ARG executes
processing two parameters.

31 Separation of two parameters into five variables. The comma between the variables x2 and
x3 signals the PARSE command that two parameters are passed.

I admit that this example is somewhat complicated and complex. However, it


also contains all types of variations on the topic parameter passing in REXX
programs.
Remark:
The number of parameters passed is determined by the number of commas in
the transferred parameters that are included in the CALL instruction. When
transferring the parameters, you can query the number of incoming
parameters using the function ARG(). If the parameter values do not contain
blanks, you can always work with only one parameter text and disassemble this
in the subroutine using PARSE ARG.

Example for the takeover of keyword parameters


The following example shows how to take over keyword parameters. This type
of parameters is wise if you want to keep order of the parameters in the transfer
variable and if not all parameters must be entered or some parameters may be
specified alternatively. For a better understand, you should look at the
comments at the beginning of the procedure.
Program 3.3: LMGREAD read a data set using ISPF LM functions
Remarks:
The host command environment is at the beginning of LMGREAD set to
ISPEXEC because the whole procedure exclusively uses the ISPEXEC
environment. In the SELECT group immediately after the takeover of the
parameters, the plausibility check of parameters takes place. The parameter
name DD and DSN must alternatively be used. This is queried in the plausibility
check. The STEM parameter is mandatory.

3.3 - CALL – CALL OTHER PROGRAMS


The CALL instruction calls internal subroutines and external programs. The
syntax is as follows:

name Specifies the name of the internal or external program which is called. If the name
is literally specified, then the program is only externally searched.

parameter This information includes the transfer parameters. Commas must separate several
parameters. The parameters must not be in brackets.

Example:

Active:
When the name SUB is in apostrophes, the system searches SUB in external
libraries only.
Rules:
–Internal subroutines must use RETURN to jump back to the command after
the CALL statement. With EXIT, the main program would leave.
–In external REXX subroutines is the command EXIT usable for return.
–If a subroutine is called with CALL and this program returns a value using the
command RETURN(value), this value is stored in the REXX special variable
RESULT. The calling program can use the variable RESULT to take over the
return value.
–When calling external programs no stems are transferrable. To solve this
problem, take advantage of the data stack of the TSO. See section 3.11 QUEUE –
Working with the TSO stack on page 53.
For examples of calling subroutines, See Program 3.2: ARGTEST – Example of
the parameter handling in REXX on page 31.
Functions
Internal and external programs can also be executed using a function call. This
happens because you use instead of the CALL statement the function call as
follows:

Name is the name of an internal or external program. In principle, you can call
any program as a function. Of course, this only makes sense for such a program,
which also returns a value. Note that this also may be a text string. This return
value can contain many different parts because it may be up to 16MB long! For
a technique how to divide the individual values of a return text that you can
easily determine this in the calling program, REXX provides elegant ways.

3.4 - DO GROUPS AND DO LOOPS


The DO command is one of the most important commands in REXX. In
connection with this command there are the commands END, ITERATE and
LEAVE. This is considered in this context as well. A program sequence that
started with a DO command must always be terminated with an END command.
The nesting of DO commands is not limited to my knowledge. As the title
suggests, there is the DO command in two basic versions:

3.4.1- The DO group


The DO group occurs most often in connection with the commands IF and
WHEN to execute a series of commands when the requested condition is met.
When used as a DO group the DO command has no further operands.

Example:

Notes:
The command LEAVE is not usable to leave a DO group! Note also that for each
DO, an END must belong. This means: DO and END must always occur in pairs.
This pairing is easy to control with the editors Colored Code facility (HILITE
command!).
3.4.2- The DO loop
The DO loop has a very wide scope for design. I would like to present some basic
examples here:

3.4.2.1- DO FOREVER
Here a never-ending loop is started. This variant is rare. The risk of program
loops is relatively high, because you have to safely exit the loop. You can leave
this DO loop using LEAVE or link them to a WHILE or UNTIL condition to leave
them in this way.

3.4.2.2 DO I = A TO B BY C
Explanation of values:
I is the loop index
A is the start value
B is the end value
C is the incremental step value

All these four values must be of type NUM. The values A, B and C can be the
result of a calculation expression.

Variations:
a) With a loop index without increment and end value

This version is strongly preferred to against the version with DO FOREVER. It


has two advantages:
–You can use the loop index I for indexing.
–Due to the designation of a loop index, this loop can be specifically exited
with LEAVE I. This is especially important for nested DO loops and DO groups.

b) With a loop index, negative initial value, increment and end value

c) With a loop index and UNTIL or WHILE condition


This loop is exited at the END I command when during the processing the
variable INPUT is set to the text END.

3.4.2.3- DO WHILE and DO UNTIL Rules:


–The WHILE condition is checked when a new loop iteration is started. Thus, if
the WHILE condition is not met at the beginning of the DO sequence already,
the sequence is not run through.
–The UNTIL condition is checked when the END command is reached and
before the loop index is recalculated. This means that the DO sequence runs at
least once.
WHILE example of a program to issue system information:

Example of UNTIL from a program to print error text:

Mnemonics to the DO command


–The loop index, the incremental value and the final value can have negative
contents and decimal numbers such as 0.3, 12.5 and so on.
–The LEAVE command is not applicable within DO groups. Therefore, if you
want to leave a DO group with LEAVE, you should then create it as a DO loop,
even if you do not need the loop index.
–You should get into the habit to always specify the loop index name in the END
statement of a DO loop. This increases the overview immensely.
–The ITERATE command jumps to the end of the loop, calculates a new value
for the loop index and then continues the DO loop. This makes it possible to
jump from an inner level nested loop directly to the end of an outer level.
–Depending on the manner in which the loop is exited, the content of the loop
index is as follows:
–If the loop ends normally by reaching the final value and the calculation of the
loop index variable has exactly the final value, the loop index contains the value:
end value + increment. In all other cases, the loop index contains the value:
Content on the last run + increment.
–If the loop is exited due to the WHILE condition, the loop index contains the
value: Content on the last run + increment.
–If the loop is exited due to the UNTIL condition or a LEAVE statement, the loop
index contains the current value.

3.5 - EXIT AND RETURN – LEAVING THE REXX


PROCEDURE
Command syntax:
EXIT expression

Use EXIT to leave a main program. If the EXIT command used is in an internal
subroutine, the main program is exited. If there is an external procedure
called, then only this will exited, but not the calling program.
expression This value is returned to the calling program. If the
calling program is the TSO, then this value must be
an integer number in the range of -2**31 to 2**31-1,
because in this case the value is set in the register 15
and then to the TSO returned. If the REXX program
was called in a TSO batch job, this return code is by
the TSO as a step return code returned to the MVS.

Example:
The following example illustrates this technique: I have written an external
subroutine called TEXIT, which consists only of the EXIT 999 command. In the
following program, this routine is once as a function and once called with CALL:

When called, the program prints the following lines:

As you can see when TEXIT is called as a function, the return value is returned
in XXX and when called using CALL the return value is returned in the special
variable RESULT.

Command syntax:
RETURN expression

If one wants to jump out of an internal subprogram to the parent program,


RETURN must be used. The handling of the return code is the same as the EXIT
command.

Example
The following internal procedure returns a 1 if the YEAR variable contains the
number of a leap year. Otherwise, 0 is returned.
Program 3.4: Function LEAPYEAR

Return codes at program start under ISPF batch:


When you invoke a REXX program under ISPF batch, then the return code from
the RETURN or EXIT command is not returned to the operating system. In this
case, you have to use a special technique to make the ISPF return the desired
return code to the TSO and so to the calling operating system. This technique is
to store the return code into the ISPF variable ZISPFRC and write this variable
in the ISPF function pool before leaving the REXX program.

Program example statements:

In this case, the ISPF step ends in a batch job with the RC = 16. See also section
6.1 Execution of programs in a TSO/ISPF environment on page 105.

3.6 - IF AND WHEN – CHECK CONDITIONS


The commands IF and WHEN have the same structure. The WHEN command,
however, can only within a SELECT sequence used. The basic structure of these
commands is:

expression Any numeric or logical expression whose result can only be 0 or 1.


instruction Each REXX command.

The operation and diversity of IF commands can best explained with examples.
So here are some examples of IF queries from some of my programs:

First example

Second example

Third example

In this example, you can see that in an IF command not only a DO group, but
also a DO loop can start.

3.7 - INTERPRET – GENERATE REXX COMMANDS


DYNAMICALLY
The INTERPRET command generates a REXX command using constants and
variables and executes it immediately. This allows you to generate and execute
REXX commands dynamically.

Command syntax
INTERPRETexpression
expression The content of expression dissolves and the resulting REXX command executes
immediately. The expression is usually composed of literals and variables that
make up the command to execute.

Note:
A beginner in REXX programming may have some difficulties in defining
INTERPRET commands correctly. So I am going to show the operation of the
INTERPRET instruction using a few examples. As usual in this book, I take these
examples from some of my practice programs.

First example for the INTERPRET command:


The SMART ISPF utilities contain the edit macro #IMACRO1. For control
purposes, some variables must be dynamically assembled to contain in its name
the number of the logical ISPF screen where the program is running. This
technique assures that the program can run parallel in some logical screens.
The following statements show how this is realizable using the INTERPRET
command:

As you can see, original REXX commands as well as ISPF commands are
assembled. Since the latter have to be set in single quotes, the two delimiters (')
and (") are alternately used for literals so that useful statements are developed.
When the INTERPRET command translates and we assume that the ZSCREEN
variable has the value 4, then the following command sequence would run:

Second example for the INTERPRET command:


This example also comes from one of my applications. It is somewhat complex.
Therefore, it is so beautiful! To help you understand the following example, I
will explain the environment under which the program is running. This REXX
program reads DB2 tables using an assembler subroutine and prints them. The
operator enters the necessary SQL statements using an ISPF panel. These
statements are passed to the assembler program. The assembler program
stores the DB2 read results into stems that are in the REXX at return from the
assembler program known.
Explanation:
Suppose, the loop index ROW is 5 and the loop index COL is 3. Then the
following situation arises after the replacement of the control variables COL
and ROW:

SQL_CN.3 contains the text PRI_DATE. Thus, the following statement executes:

PRI_DATE.5 contains, as shown in the printout below, the text: 20040421.

I hope I have been successful inspiring you for the INTERPRET instruction! You
can use it when necessary to produce very elegant solutions. In addition, in
some cases it is simply essential! You can find such a solution in the REXX
program SPROFVAR – Load user ISPF variables on page 270.

3.8 - NUMERIC – SET COMPUTING OPTIONS


In this chapter, I deal will with the following two commands:

Before I turn to this issue, I have to tell you how the REXX data and here
especially figures are internally stored. If you have ever programmed in a
programming language other than REXX, you know the effort you have to do
there to define your variables containing figures. Since there is binary data
which may be stored in fields of 16, 32 or 64 bits, there is decimal data with up
to 31 decimal digits. Add the different variants of the floating point data. Let
alone the different variants of the floating-point numbers. Fortunately, you can
forget it all in REXX.
How REXX figures internally stores:
REXX puts all the data in EBCDIC text strings. So also the data that contain
numbers. The numbers before they participate in arithmetic operations are
converted to an appropriate format that the underlying system can handle
and are converted back into text strings after completion of the arithmetic
operation. This happens for each arithmetic operation within a command.

For this very simple rule, of course there must be a defined width for the figures
so that the numerical representation remains manageable.

Example:
If the command X = 2/3 is executed then an infinite fraction occurs.

As in the REXX fractional numbers are not stored in words such as Short
Floating Point or Long Floating Point, where the number automatically by the
word length is limited, but as unpacked figures in EBCDIC format, an infinitely
long number would need to be stored here. This means, it must be set
somewhere how many significant digits are to be stored in such a number. If
the default width of NUMERIC DIGITS 9 were active, the number X would be
stored as EBCDIC characters in: 0.666666667. That is, for the storage of X, 11
bytes are occupied internally. The NUMERIC command is available with three
main functions, of which I will discuss only two.

number specifies how many significant digits are used to store


numbers. This definition is always immediately active
until a change with a new NUMERIC DIGITS is made
or the program ends. Number must be a whole number.
Of course, the specification using a variable is possible.
The default value is. 9

Note:
As long as the numbers remain in a program below ABS(999999999), you do
not need to change the value of NUMERIC DIGITS. However, as soon as a
number generated during the program runs and goes beyond this number
space, you have the NUMERIC DIGITS to increase accordingly, or you get a
program abort. If you read all of this, one might be tempted, at the beginning of
each REXX program simply to enter the command NUMERIC DIGITS 50. This
would be likely to be on the safe side. However, here we must remember that
then all fractional numbers that have as many places stored after the decimal
point with 50 significant digits, and even worse, of course, also be calculated
using this width.
Example:
The following commands produce this result:

number determines how many digits of a number to be rounded


by decimal from the right before a comparison operation
performs. This definition is always performed
immediately and valid until a change with a new
NUMERIC FUZZ statement is or the program ends. This
must be a whole number. Of course, the specification
using a variable is possible. The default value is 0. The
number must always be less than the current number
value of the NUMERIC DIGITS command.

The impact of NUMERIC FUZZ on the logical operations is better understand


when we look at an example:

In order to understand this example, you have to realize that REXX normal
comparison operations (not the exact with the double operator symbol)
between two is performed such a way that first the second number is
subtracted from the first and then the result is compared with zero. If we view
the results shown in the above IF statements that are behind the NUMERIC
FUZZ 1, then this is due to the following effect: Because FUZZ is less than
DIGITS, the takes place before subtraction. From 4.9999 the integer is 5.
Tip:
If you ever need to perform extensive calculations with REXX for which
comparisons of fractional numbers happen to fail due to differences in the rear
decimal places that you do not expect, then you remember NUMERIC FUZZ.
The currently active values for NUMERIC can be displayed as follows:

The display of these two commands is here:


3.9 - PARSE – TEXT FRAGMENTATION
The PARSE command is one of the strongest commands of the REXX language.
You can use it to perform in an elegant way decompositions of texts, data read
from the stack or from the terminal and get information about the currently
running program. You have one of its variants already in the discussion of the
ARG instruction in the section 3.2 ARG – Retrieve the parameter string seen on
page 31. We will now look at other forms. Again, I would like to present a few
examples from practice. First, here is an overview of the different variants of
the parse command in the following table:
Table 3.2: Table of PARSE types

PARSE type Functions

PARSE ARG Disassembles transfer input parameters at program calls.

PARSE Reads data from the terminal when programs execute online. In batch
EXTERNAL processing data are from DD SYSTSIN. If no data is available, then a null-string
will be returned.

ARSE NUMERIC Returns the currently active values for the three NUMERIC options DIGITS,
FUZZ and FORM.

PARSE PULL Reads the TSO data stack. If it is empty, this command works like PARSE
EXTERNAL.

PARSE SOURCE Returns information about the source code of the currently running program.

PARSE VALUE Parses an expression.

PARSE VAR Parses a variable.

PARSE Returns information about the REXX interpreter, under which the program is
VERSION running.

Rules:
–In all PARSE commands, UPPER can be specified as the second word. Thus, the
results are returned in uppercase. Just like the ARG instruction, too.
–In the data to be fractionized, the blank plays a special role: If no separator or
placement points are given in the variable list, the separation is on the blanks
in the performed text.
–In the variable list, the point (dot) can be as placeholders for variables used.
For safety reasons, I always use the dot as the last variable position. This
collects everything possibly in the text that is still behind the positions I need.
Otherwise, this part would additionally be in the last assigned variable.
–Variables that have no values could be assigned during the fractionizing
contain null strings.

Design possibilities of parse templates:


There are several ways to control the fractionize process in PARSE commands.
Use the following templates to control the fractionizing process of the PARSE
command:
–The Blank.
–A string.
–Variables containing delimiters.
–Numbers that indicate the absolute or relative character position in the text.

Let us now look at the different variants of the PARSE command in detail:

3.9.1- PARSE ARG


I have already dealt with this command in the ARG command. See section
3.2 ARG – Retrieve the parameter string on page 31. The PARSE ARG command
is the only PARSE command, wherein a plurality of input variables can be
resolved. This is necessary to permit the transfer of parameters to single
variables in a subroutine or function.

3.9.2- PARSE VALUE.... WITH


The fractionized text can be an expression here. The default separator is a
blank. Several blanks can stand between the individual words.

Example:

The results of this command are:


Now the question comes up: Why does the variable W4 not only contain the
word Hugo, but one blank before and four blanks behind while W3 includes
only the text is, but also the three blanks before the word is? To answer this
question we have to look at a special rule in the application of PARSE command
now:
Rule:
The last variable in the template of a PARSE command contains all characters
that are still present after the assignment of the value of the penultimate
variable. This rule applies to all versions of the parse command.

Why we have this rule?

Based on the realization that you should have the opportunity in fractionizing
texts, this rule has been created to proceed in several steps in order to
completely fraction- ize differently structured texts. As a consequence, it may
be well useful to always assign the last variable throughout the rest of the text
without any compromises. You can then decompose this last variable in the
next PARSE step.

How do you get around this rule?


This rule can be bypassed by inserting a dot as a dummy variable after the last
regular variable. This would look like this:

The value in v4 is then only Hugo without the trailing blanks.

Example of the use of PARSE VALUE .... WITH


This example shows different variations for the dissection of DATA and TIME
values.
Program 3.5: Example showing variations for the dissection of DATA and
TIME values
Here, the printout of the above program:

The numbers in the left column on the list refer to the respective PARSE
command line in the program. In the following text, I will explain the
functioning of each PARSE command of the program in detail

The function DATE provides the expression 28 Mar 2015. Here, since the
individual values are separated by a single space, you can use the blank as a
delimiter. This frac- tionizing would produce the same results if several blanks
were between the values
The command DATE("S") returns a value of the form YYYYMMDD. From this
expression, the values YYYY, MM and DD should separate. The touchdown 5
means that from there the allocation for the MM variable begins and 7 defines
the position where DD begins.

The value to be resolved is the same as in statement 12. The positioning of the
variables are with relative positions. The counting of the relative positions
starts at one. The touchdown +4 means that from there the allocation for the
MM variable begins. Because before no touchdown was defined, the characters
1 to 4 are to the variable YYYY assigned. +2 means that it is incremented to the
previously mentioned setting position, namely +4 to two positions, to
determine the variable dd.

The parsed value is in the form HH:MM:SS. The hours, minutes and seconds
shall be separated. In this example, I will use the specification of an absolute
position for the three values. This results in a kind of SUBSTRING selection.
Here, the start and end are specified for each variable. The definition for the
extraction is as follows: <start> variable name. The second value always
addresses the position behind the extracted value.

The parsed value is in the form HH:MM:SS. I work with absolute start positions
for the individual values. Dummy points (:) eliminate the colons.

The parsed value is in the form HH:MM:SS. Here the colons are as separators
used.

The parsed value is in the form HH:MM:SS. This is where the colons are used as
separators, wherein the separator is in a variable (assignment in line 34).
3.9.3- PARSE VAR
This type of Parse command is most often used. It differs from the PARSE
VALUE type where the parsed text needs to be in a variable. The PARSE VALUE
command from above now can be done like this:

3.9.4- PARSE SOURCE


The PARSE SOURCE command is to get information on the currently running
program used. It returns up to nine values. To illustrate this command, I wrote
the following procedure. The meanings of the individual values are included as
comments in the program.
Program 3.6: PARSE2 – Example for PARSE SOURCE

When running this program, the following list is printed:

3.10-PROCEDURE – OPTION FOR INTERNAL SUBROUTINES


Internal subprograms can be set up in two kinds:
–With a PROCEDURE statement
–Without a PROCEDURE statement
3.10.1- Internal subroutines with PROCEDURE statement
In this type of subroutines, the option PROCEDURE must be inserted after the
subroutine name. This option makes all variables that occur in the subroutine
segregate from those of the main program and even those with the same name.
This means that the variables between the two programs are
mutually unknown. If you want to make some variables in both programs still
known, you have to use the EXPOSE option. Variables listed behind EXPOSE are
then known all in both programs.

Advantage of this method:


You do not have to worry about whether the same variable when contained in
both program parts are accidentally overwritten in the subprogram. Unless this
is intentional.

Disadvantage of this method:


You have all the variables that are needed in the main program and the
subprogram, specify either using the EXPOSE option, or make the contents thru
parameter passing known.

Example of EXPOSE:

As you can see in this example from practice, not only simple variables are
contained in the EXPOSE option but also stems.

3.10.2- Internal subroutines without PROCEDURE statement


When the input point of a program contains no PROCEDURE option, all
variables used in this subroutine are in all program parts known except such,
which have a PROCEDURE option.

Advantage of this method:


There are all the variables available in both parts of the program. If you define
a new variable in the subroutine, this is in the main program after return
known.

Disadvantage of this method:


You must take care that you do not accidentally change main program variables
in the subroutine. Very dramatic effects may arise when using the control
variable of a DO loop in both the main and the subprogram and carry out the
subroutine call from the corresponding DO loop of the main program.

Rule:
In external subprograms, the option PROCEDURE is unusable, because the
variables are in the calling program anyway not known. If you copy an external
subprogram in a main program to improve the performance, you must always
make sure that the variables does not overwrite each other. In this case, you
should insert the PROCEDURE option behind the name of the inserted
subroutine.

3.11 - QUEUE – WORKING WITH THE TSO STACK


In this chapter, I will show you how to elegantly store data in an internal buffer
and read again. The area of the DATA STACKS is very extensive. I will describe
here only the part that deals with the QUEUE command.

3.11.1- The TSO/E data stack


Before I turn to the QUEUE command, I will introduce the technique of TSO/E
data Stack:
The TSO/E data stack is an area in virtual memory which you could use for
temporary storage of any kind of data. All REXX programs that run in a task
have access to the data stack. As a result, the data stack is ideal for exchanging
data between internal and external REXX subroutines. The data are written into
the data stack record by record. A single record can be up to 16 MB long. The
brochure TSO/E REXX Reference mentions that an entry in the stack can be up
to 16 MB in length. The brochure TSO/E REXX User's Guide says that only the
amount of available memory sets the length limit of an entry (data item). I have
checked the matter. The brochure TSO/EREXX Reference is right: 16 MB is the
maximum length of one entry! There are two commands available that write
data into the TSO/E data stack:

This command always writes the records to the end of the stack. This means
that the last written record will also read as the last one when the stack is read
completely. This technique is referred to as first in first out (FIFO). If you
create a stack to create a file, then FIFO is always right. Namely, when a data set
is read, it is normally expected that the first read data record is the first in the
data set. A QUEUE command with no expression produces a blank entry in the
stack. This empty entry is required for various commands (e.g. the EXECIO
command) to recognize the end of data in the stack.

This command always writes the records before the first record in stack. This
means that the last written record is read first on reading. This technique is also
referred to as last in, first out (LIFO).
The following commands can read data from the stack:
–PULL
–EXECIO
–SUBMIT
–DSN (for execution of DB2 utility functions)

There are probably many more programs and systems that can be read from
the stack data. However, I have even used these.

3.11.2- Use options for the TSO/E Data Stack


In REXX, you can use the TSO/E data stack for the following purposes:
–Dynamically create a batch job with subsequent SUBMIT.
–Sending and reading files using EXECIO.
–Exchange of large amounts of data between internal and external programs.

Example 1: Submit a batch job.


The procedure COMPRESS submits a job to compress a partitioned data set. Call
the COMPRESS procedure by entering its name in menu 3.4 in front of the DSN
of the data set to be compressed.
Program 3.7: Assemble and submit a COMPRESS job
Example 2: Exchange of data with an external subroutine
In the following example, a file containing names will be read in a REXX main
program. These names will be sorted in an external subprogram. The sorted
names are returned to the main program. Here the main program is NAMSORT.
The greyed lines are important:
Program 3.8: Program NAMESORT to sort names

Here the subroutine NSORT:


Program 3.9: Subroutine NSORT
Tips:
–If the data stack is to be read by a command that expects this null string, never
forget the final QUEUE command with no operands. See the last QUEUE
command in Program 3.7: Assemble and submit a COMPRESS job on page 55.
This error can make very unpleasantly: If you run the procedure online and an
EXECIO or SUBMIT command reads the data stack, then the attempt to read the
appropriate command terminates only upon reaching a null string entry. If this
null entry is not found, then the command tries to read more data from the
terminal, namely your screen. You realize this because that on the screen
nothing moves anymore after you have invoked the procedure which is a
surprise. In this case, your screen will just stand and wait for an input. Because
you do not know what is going on, you think that the system hangs. Only when
you press ENTER, the read command gets its long-awaited null string and it
continues.
–In the EXECIO command, you can omit the terminating null string if you write
the command like this:
–This trick does not work on the SUBMIT command, because there is only the
asterisk (*) specified in that command indicating that the data are read from
the stack. However, you can mark the end of the data stream with a special end
line that contains exactly two characters when using the SUBMIT command.
The two characters in the last row are then specified when running the SUBMIT
command:
3.12 - SAY – PRINT TEXTS
With the SAY command, you can output any text from a REXX program. This
command is very well suited as a debugging aid and for the issue of control
information. If a REXX program runs in a batch job, the output of SAY messages
happens via the DD statement SYSTSPRT. In the previous shown programs a
number of SAY commands are contained. Therefore, I will refrain from giving
more SAY examples.

3.13 - SELECT – CONDITIONALLY CALL


ALTERNATIVE INSTRUCTIONS
The SELECT statement can build very efficient condition controls. This
command executes program parts selectively under certain conditions. In
addition to the DO group, the SELECT statement is the most important element
to generate GOTO free REXX code.

Rules:
–The SELECT statement opens a set of condition queries. It must be terminated
with an END.
–The condition queries can consist of any number of WHEN statements that run
from top to bottom in sequence until one of the WHEN conditions is true.
–If the first WHEN condition is detected as true, then the following REXX
command will be executed. The SELECT sequence is at the END left belonging
to the SELECT statement.
–If none of the WHEN conditions are true, then the REXX command in the
OTHERWISE statements is executed.
–The OTHERWISE statement is mandatory. It must be inserted immediately
before the END statement belonging to the SELECT.
–Behind OTHERWISE any number of statements can follow without requiring
them to be included in a DO group.
–The interpreter only notices the absence of the OTHERWISE condition, if for
any current program run none of the WHEN conditions is true. In this case, a
program termination occurs. This means on this way you can install a time
bomb in your program. Therefore, you should never forget the OTHERWISE
statement before the END of a SELECT sequence.
–Once one of the WHEN conditions meets, then the following conditions are
ignored and their program code will no longer go through. If these skipped
commands errors contain such as wrong contents in numerical operations,
these errors are only recognized when these commands are actually be
executed.
–Behind the WHEN keyword all possibilities that the IF statement knows can
be used.

Example 1: Simple SELECT structure


This example shows a simple SELECT structure.

Example 2: A slightly more complex SELECT structure:


Here are the commands to execute in DO groups arranged.

Example 3: A complex SELECT sequence:


Depending on the result of the SYSDSN function, various actions will be
performed.
Tip:
I set behind END of the SELECT structure always the comment /* Select */.
Sometimes I number the SELECT – END sequences within a program. This
increases the overview in very long and nested sequences. Never forget the
OTHERWISE statement!

3.14 - NOP – NO OPERATION


This is a very simple statement. NOP stands for “NO OPERATION”, meaning that
nothing is running. NOP is very often in OTHERWISE statements used. See the
example in the previous tip.

3.15 - PULL – ENTER DATA ON THE SCREEN


The only reason why I am mentioning this command here is to warn you of the
pitfalls of this command. This is a very rarely needed command in fact. The
command operates as follows:
–If the data stack contains data, then the PULL reads from the data stack.
–Only when there is nothing in the data stack, then PULL reads from the
terminal.

If you want to read something from the terminal, you have two options:
–You can define a small panel for the input of data. I always use this way when
I want to enter the user data on the screen. This offers much better ways of
setting of texts and the plausibility check of the entered values.
–You tell the user using the command SAY what to enter now and then issue the
command PULL.

Tip:
If you believe that you must always use the PULL command, then I urge you to
insert a query previously that determines whether the data stack is actually
empty. If necessary, you can clear the data stack before you use the PULL
command. It could look like this:

3.16 - TRACE – THE STRONG DEBUGGING AID


If you are involved in application development, you certainly know the various
debugging aids. As REXX is an interpreted language, of course, the test aids can
be very elegantly defined and used here. For a detailed description of the
TRACE command, refer to the brochure TSO/E REXX Reference. I use in
practice mostly the commands trace?i and trace ?r. By specifying the question
mark (?), the interpreter stops after each executed command and you can then
enter your own commands manually. These commands will be executed
immediately. The possibility of direct entry of commands can also be used to
disable a running TRACE with TRACE O. The program runs then so long
without TRACE until another TRACE statement is executed in the program, or
until the program ends.
Program 3.10: POWER2 – Trace example

When I run this procedure online, I get the following messages on the screen:

I turned off tracing by the direct input of the command TRACE O. Thereafter,
the program runs normally to the end. How you see the VALUE = ... TRACE from
the calculation in the line, the individual calculation steps are listed in detail.

Tip:
I strongly recommend to practice intensively the TRACE command, because it
is a powerful aid in creating REXX applications.
3.17 - SIGNAL – JUMPING WHEN ERRORS
There are three main forms of the SIGNAL command:
SIGNAL label
SIGNAL ON errortype NAME label
SIGNAL VALUE expression

Using the first way you can jump directly to a label in the program. This use of
the SIGNAL instruction corresponds to a GOTO in other programming
languages.

Note:
I cannot remember having ever used the SIGNAL command to jump to another
location in the program, because I develop in REXX just GOTO free program
code.

With the second type, at the beginning of the program traps can be set to cause
the interpreter to jump there in the event of an error. The third type of
command can be specified as an internal branch address of a program in
expression. There is then jumped after EXPRESSION is resolved.

4-The REXX functions


Functions play an important role in REXX. In particular, the functions for word
and string processing. When you have worked through the next chapter, you
might be amazed about what you can do with the REXX functions. So, have fun
reading about the REXX functions! The REXX language we can use on z/OS
TSO/E consists of two blocks of language elements:
–The REXX commands, as we learned in chapter 3 The REXX commands on page
25.
–The large stock of standard functions that belong to the REXX language and
which we will discuss in this chapter.

We now turn to the second part, the REXX functions. I will not discuss any
function that is described in the brochure TSO/E REXX reference, but only those
that are in my opinion often needed in practice. How functions are called, I have
explained already in the section 3.3 CALL – Call other programs on page 35.
There we already talked about the topics parameter input and return of the
results.
The REXX functions can be divided into groups by application area. I have made
the following division into groups for the presentation of the REXX functions in
this book.
Table 4.1: REXX function groups

Function group On page

General Functions 64.

Arithmetic Functions 72.

Comparison Functions 74.

Conversion Functions 77.

Formatting Functions 82.

String Functions 85.

Word Functions 90.

System Functions 92.

The number of available standard functions is larger than the number of


instructions in the REXX language. This lets you know how important the
knowledge of the functions in REXX is. Through internal and external programs,
you can easily create your own, new features and thereby extend your pool of
available functions arbitrarily.

General rules for the use of functions:


–The REXX interpreter recognizes a function call when parentheses follow the
function name.
–The functions are usually called with parameters which are written in the
parentheses.
–Some functions return a value even if no parameters have been entered. In this
case, the parentheses must still be set. Then they remain empty.
–The left parenthesis must always follow immediately the function name
without any blanks, otherwise the function name will be assumed as REXX
command. If this rule is not adhered, then a program abort occurs.

In the headings of the following functional descriptions, I will omit the


parentheses respectively.

4.1 - GENERAL FUNCTIONS


4.1.1- ADDRESS – Get the active host command environment
This function returns the name of the current host command environment. No
parameters can be entered.

Function:
Returns the currently active host command environment.

Format:
name = address()

A host command environment, whose name was written by the ADDRESS


function to a variable, can only be restored by using the following commands.
–By setting the variable in surrounding parentheses.
–By using the REXX VALUE function.

The following example shows the two variants:

HCE → Host Command Environment


See also the section 3.1 ADDRESS – Connection to the subsystems on page 25.

4.1.2- ARG – Input parameter test or take


The ARG function has three application forms:
–Determining the number of input parameters.
–Testing for the presence of certain input parameters.
–Taking single or all the parameters.
Format:
ARG (n,option)
n Means the nth parameter. If specifying this option, the contents of the nth parameter will
returned. If this parameter is not set, a null string will be returned.

option eReturns 1 if the nth parameter is available. Otherwise, 0 is returned.


oReturns 1 if the nth parameter is not available. Otherwise, 0 is returned.

4.1.3- DATE – Date functions


The DATE function returns the current date in many different forms. Moreover,
you can perform with the DATE function also date calculations.

Function:
The DATE function is applicable for two purposes:
–Return of the current date in different forms.
–Calculation of date values.
On the following pages, I will explain these two variants in detail.

1.Return the current date


Returns today’s date back in different forms.

Format:
today_date = DATE(format)
It returns the current date in the notation defined in the format. The possible
entries for format and the resulting return values are summarized in the
following table. Only the first letter is entered to define the format.
Table 4.2: Parameters of the DATE function

Format Returned value

Base Days since January 1, 0001 without the present day. The format wd = date("B") // 7

can be used to determine the current day of the week. 0 is Monday and 6 is Sunday.

Century Days since January 1 of the current century, including today.

Days Days since January 1 of the current year, including today.

European Date in European format: DD/MM/YY

Julian Date in the form: YYDDD this means Julian Day.

Month English name of the month in upper and lower case. For example, January.

Normal Date in the format: DD Mon YYYY. Mon is the short form of month: Jan, Feb, Mar, etc.
This is the default setting, if no parameter is entered.

Ordered Date in the format: YY/MM/DD.

Standard Date in the format: YYYYMMDD.

Usa Date in the American format: MM/DD/YY.

Weekday English weekday. Monday, Tuesday, etc.


Example DATE output:

2.Date calculations using the DATE function


With the DATE function, you can perform some date conversion to another
format and date calculations.

Format:
result = DATE(format1,input,format2) Rule:

Rule:
The date specified in input is converted to the format specified in format1.
Format2 is mandatory; it defines the format of input. Input can also be a DATE
function.

To demonstrate these capabilities of the DATE function, I wrote and performed


a small REXX procedure. See the result here:
Note:
For conversions and calculations, formats C and J cannot be used as a result.
This is a shame, because conversions into the J format are often necessary in
practice.

4.1.4- TIME – Time functions


The TIME function returns the current date in many different forms. Moreover,
you can perform with the TIME function also date calculations.

Function:
The TIME function provides two ways to use it:
–Returns the current time of day.
–Starting and stopping the difference timing measurement.
Format:
Time = TIME (format)

The following table shows which options can be set with format and which
results TIME then provides.
Table 4.3:Options of the TIME function

Format Return value

Civil Time of day in the form HH:MMxx, where xx can be either am or pm. This is for American
time information.

Elapsed Result is the time in the form SSSSSSSSS.UUUUUU, where seconds are before the decimal
point and the decimals of seconds behind. With this form, the stopwatch is started. Each
subsequent call with this form gives the elapsed time back since the first call.

Hours Returns the hour of day in one or two digits.

Long Returns the time in the format HH:MM:SS.UUUUUU. The digits after the decimal point are
microseconds.

Minutes Returns the minutes that have elapsed since midnight.

Normal Returns the time in the form HH:MM:SS. This is the default.

Reset Specifies the time back since the start or the last reset of the timer and resets the stopwatch
to zero.

Seconds Returns the seconds that have elapsed since midnight.

Examples of the return time of day

Examples of the time measurement


Between the call with the format E and the call with the format R 530
microseconds have elapsed.

4.1.5- QEUED – Number of records in the data stack Function:


Function:
Returns the number of records in the TSO data stack.

Format:
Number = QUEUED()

Returns the number of records currently contained in the data stack. No


parameters can be entered. A return value of zero indicates an empty data
stack.

4.1.6- SOURCELINE – Return a program line


Function:
–Returns the number of lines of source code.
–Returns the text of a line from the source code of the program.

Format:
Number = SOURCELINE()

Returns the number of lines of the source code.


Text = SOURCELINE(n)

Returns the contents of the nth row. n must be entered.

Example:
With the following DO loop, you can run through all lines of program code:

4.1.7- USERID – Return the TSO user ID


Function:
Return of the TSO user ID.

Format:
user = userid()

4.1.8- VALUE – Create variable names dynamically Function:


Function:
Generating a value, which consists of a combination of variables and constants.

Format:
value = VALUE("XYZ"var)

The VALUE function dynamically generates a value consisting of constant and


variable parts. The variables are replaced by their contents. This command
works similarly to the INTERPRET instruction. However, while INTERPRET
always constitutes the entire command and then executes it, returns VALUE
only the assembled value.

Example:
The edit macro #TSOB from the SMART ISPF utilities submits REXX procedures
currently being edited to run in a batch. In this batch job either a variable
number of STEPLIB DSNs and a variable number of SYSEXEC DSNs can occur.
The SMART ISPF utilities program SPROFVAR stores this information into the
ISPF user profiles. The organization of the variable is as follows:
The profile variables SYSEXEC and STEPLIB each contains the number of
existing DSNs for this type that are to be included in the batch job. The
corresponding DSNs are then in the variables SYSEXECn and STEPLIBn, where
n is from 1 to content of SYSEXEC and STEPLIB respectively.
The following commands define the variables. That is their content in the
profile pool.

Subsequently, the program section from the edit macro #TSOB that reads the
variables from the profile and includes them in the JCL:
The rest of the procedure is suppressed.

4.2 - ARITHMETIC FUNCTIONS


In the following sections, I will discuss functions relating to various ways of
treatment and control of arithmetic operations.

4.2.1- ABS – absolute value of a number


Function:
Returns the absolute value of a number.

Format:
result = ABS(number)
This function returns the unsigned absolute value of a number. The format of
the returned number is obtained from the currently valid NUMERIC options.

Examples:

4.2.2-DIGITS, FORM, FUZZ – Query options for arithmetic operations


These three functions query the values that apply just for performing
arithmetic expressions. This information can also be obtained by the PARSE
NUMERIC var command.

Example:

Here the results when calling this procedure:

4.2.3- MIN, MAX – Minimum and maximum value


These functions return the minimum or maximum value of a set of numbers
that are entered as a single parameter. In a parameter list, a maximum of 20
values can be entered. However, since these functions could be interleaved, a
maximum of 20 x 20 = 400 numbers are possible in one function call.

4.2.4- RANDOM – Generate random numbers


Function:
This function generates a random number within a lower and an upper limit.
Format:
number = random(start,end[,ind])
start

end

ind

Example:
In this example, it is shown that with repeated calls always the same random
numbers are received when using the same number for option ind.
Program 4.1: RAMDOM – Generate random numbers

This is the printout of the above program:

As you can see, in rows 2 and 4 plus 3 and 5 respectively appear the same
numbers, because in the corresponding RANDOM calls a base number was
specified. It is irrelevant what base number you choose.

4.2.5- SIGN – Return of the sign


Function:
Returns the sign of a number.
Format:
value = sign(number)

SIGN returns the sign of the number specified by the following rules:

4.3 - COMPARISON FUNCTIONS


Besides the possibility of comparisons using the IF command, there are some
functions that you can use to perform comparisons in REXX. The most
important function is DATATYPE, because without this function plausibility
checks of numerical data could not be performed.

4.3.1- COMPARE – Compare texts


Function:
This function returns a zero if the two texts are equal. If the texts are not equal,
the position of the character returns from where on the texts are not equal.

Format:
result = COMPARE(text1,text2[,filler])
text1,text2 The texts to compare.

filler The shorter of the two texts is expanded with the filler before comparison. The default
character is a blank.

Note:
I have never needed this feature because this function can be carried out with
the normal logical text comparisons operands, too. However, if you want to find
the position from which the inequality begins, COMPARE is very useful.

4.3.2- DATATYPE – Determine data type


Function:
This is a very important function. It is always required to make sure before an
arithmetic operation that all participating operands are of type NUM.
Format:
result = datatype(text,[type])
result It is NUM if text contains a number that can be used in arithmetic operations.

It is CHAR in all other cases

text This is the text, which shall be examined. When only this parameter is specified, then the
function returns the values NUM or CHAR.

type When type is specified, then the function returns 1 if the text contains only elements of the
entered type property, otherwise 0.

With type, the following properties can be queried:


Table 4.4: DATATYPE type options

Type Properties

A Text consists entirely of alphanumeric characters (a-z, A-Z, 0-9).

B Text consists entirely of binary digits (0-1)

L Text contains only lowercase letters (a-z)

M Text contains only letters (a-z, A-Z)

N Text is a valid REXX number

S Text is a valid symbol in REXX (e.g. a variable name)

U Text contains only uppercase letters (A-Z)

W Text contains an integer

X Text contains only hexadecimal digits (a-z, A-Z, 0-9) and blanks can stand between hex pairs.
Null string is also a hexadecimal character.
Example:
The following program lines come from a program that performs date
conversions of the format YYYY/MM/DD in the format YYYY/DDD (Julian date)
and vice versa. Before in the program any arithmetic operations are be
executed check whether all input values are numeric. See the following
statements:

The PARSE command in line 24 parses the number entered in the variables
YYYY, MM and DD. The IF statement in line 25 checks whether all three values
are numeric. It works like this:
The DATATYPE function returns for all tests in which a correct number is found
1, otherwise 0. If only one of the tests provides 0, then the multiplication of all
three tests is 0. This means that at least one value is not numeric.

Caution trap:
If anyone thinks now "You can do this much better by contracting the two IF
statements in lines 25 and 27 into one IF statement." Then I can only say, "You
have traded with lemons!" Why does this not work properly? This does not lead
until then to an error if the program is actually called with wrong input values.
Because then the following happens: All arithmetic operations of IF statements
are executed to determine the result. This means in our case that the multiply
operation yyyy*mm*dd is executed to complete the IF statement. Therefore, if
one of the values contains a nonnumeric character, the program will cancel.
Therefore, if someone should resist the temptation to contract these two IFs in
one thing, he has built a classic time bomb here. The issue works until an
incorrect value actually appears.
So, remember the following rule:

Rule:
Before you perform any arithmetic operations in a statement, you must
previously perform tests in which no arithmetic operations occur, to ensure
that all involved values are numerical!
By the way, what is the most embarrassing error in the programming?
The most embarrassing programming error:
Suppose you installed an extensive plausibility test in your program and this
breaks in the reasonableness test without reporting the user’s error. Then it is
a bad thing for the user, because he does not know what he did wrong.

4.4 - CONVERSION FUNCTIONS


With these functions, you can convert texts and numbers in other internal
representations. Normally, you do not really need these features since in the
TSO/REXX environment everything is very simple: All internal data
representations are essentially stored in EBCDIC format. This means that:
–The number 1234567 is internally stored in seven bytes, with the following
hexadecimal representation: “F1 F2 F3 F4 F5 F6 F7” X. In general, this
representation is called the unpacked format.
–The text “I am happy!” has internal a length of 11 bytes and consists of the
following hexadecimal characters: “ C9 40 81 94 40 88 81 97 97 A8 5A” X.

The conversion functions are always very useful when values have to be
converted into other forms of representation.

Example:
This small REXX program determines the job name directly from the system
tables of z/OS.
Screen 4.1: Read the job name from CVT

If you have the necessary knowledge of the z/OS operating system, try to
decipher the REXX commands. Find the necessary knowledge about the
conversion instructions in the following subsections. Of course, here all people
who have ever programmed in assembler have an advantage. This applies to all
conversion functions.
4.4.1- C2D – Character to decimal
Function:
This function returns the decimal value of a text. By specifying a length,
negative numbers can be converted.
Format
number = C2D(text,[n])
text This text is as binary text considered whose decimal value returned is.

n If specified, this number indicates how many bytes are converted from text from the right. Is the
first (i.e. the leftmost) bit of that number 1, then the number is output as a negative number in
the two's complement.

Advice:
When using this function, it is important to ensure that NUMERIC DIGITS are
set large enough. Otherwise, the call to C2D ends with an error.

In the following small program, I have compiled several calls to the C2D
function. I think that you can understand the operation of C2D well.
Program 4.2: Program to show C2D functionality

I have run the program. See the results below:


4.4.2- C2X – Character to Hexadecimal
Function:
This function returns the entered text in its hexadecimal notation. The output
is then twice as long as the text entered.

Format:
number = C2X(text)
text This text is an EBCDIC string, which is returned in hexadecimal
representation.

Examples:

4.4.3- D2C – Decimal to Character


Function:
With this function, you can convert a decimal number to the EBCDIC character
format.
Format:
chars = D2C(number,[n])
number This is a decimal number whose content is returned in EBCDIC characters.

n If specified, this number indicates how many bytes are returned after the conversion of
number. If n is greater than the number has digits, then is left-padded with spaces. If in
converting, more characters emerge as defined by n, characters are truncated on the left.

Example:

4.4.4- D2X – Decimal to Hexadecimal


Function:
With this function, you can convert a decimal number to its hexadecimal format.

Format:
hexchar = D2X(number,[n])
number This is a decimal number whose content is returned in hexadecimal notation.

n If specified, this number indicates how many bytes are returned after the conversion of
number. If n is greater than the output length resulting from the conversion, the result is
left-padded with 00 if it is a positive number, it is filled with hex FF, if it is a negative
number. If in converting, more characters emerge as defined by n, left standing characters
are truncated.

Examples:

Due to specifying the length of 20, the shaded places were prefixed on the left
4.4.5- X2B – Hexadecimal to Binary
Function
Convert a hexadecimal number into a binary string in text format.

Format:
bintext = X2B(hexnumber)
hexnumber The hexadecimal string is converted into a binary string. The output is four
times as long as the input.

Examples:

4.4.6- X2C – Hexadecimal to Character


Function
Convert a hexadecimal number to a string.

Format:
text = X2C(hexnumber)
hexnumber This hexadecimal number is converted to its decimal
representation.

Examples:

4.4.7- X2D – Hexadecimal to Decimal


Function
Convert a hexadecimal number to decimal.
Format:
decnum = X2D(hexnumber,[n])
hexnumber This hexadecimal number is to its decimal representation converted.

n If entered, this number indicates how many bytes are converted from hexadecimal
value from the right. When the first (i.e. the left- most) bit of number is 1, then the
number is returned as a negative number in the two's complement. If this number is
zero, then the returned value will be a positive number.

Note:
When using this function, it is important to ensure that NUMERIC DIGITS are
set large enough. Otherwise, the call to X2D ends with an error.

Program 4.3: Program to show X2D functionality

I have run the program. See the result here:

4.5 - FORMATTING FUNCTIONS


These functions formatting data for output.
4.5.1- CENTER – Centering a string
Function
With this function, a string can be arranged so that the string is in the middle
and on the left and right with the pad character padded.

Format:
result = CENTER(intext,length,[pad])
intext Input text, extended or shortened as defined by the length parameter.

length Number of characters of the result text. Is length less than the length of intext, then the input
text is equally shortened on both sides.

pad Here, a fill character to specify which of the left and right of intext is added for an
enlargement. Standard for the pad character is a blank.

4.5.2- COPIES – Reproduce texts


Function:
With this function a string can be duplicated n times.

Format:
text = COPIES(intext,n)
intext Input text that is n times duplicated.

n Number of copies.

Example:

4.5.3- FORMAT – Format numbers


Format numbers for output, as you like.

Format:
Text = FORMAT(number,before,after,expp,expt)

Table 4.5: Description of parameters for the FORMAT function


Parameter Meaning

number Expression or number, which will be formatted.

before Number of digits before the decimal point.

after Number of digits after the decimal point.

expp Number of digits in the exponent.

expt Limit of digits of number when the output is automatically switched to exponential
representation.

4.5.4- JUSTIFY – Formatting a string


Function
Block formatting of a string consisting of words by adding padding characters
between the words.

Format:
text = JUSTIFY(intext,length[,pad])
intext Input text that normally consists of words, each separated by one or more blanks.

length Length of the result text.

pad Character to be inserted between the words. Default is a blank.

Example:

These commands give the following texts:


This---------is---------a-----------Text
Wort------------------------------------
4.5.5- LEFT – Rearrange text left-justified
Function
Left-align the input text and pad it on the right side with padding character.
Default padding character is blank.

Format:
text = LEFT(intext,length[,pad])
intext Input text.

length Length of the resulting text.

pad Padding character. Default is the blank.

4.5.6- RIGHT – Arrange text right- justified


Function
Right-align the input text and pad it on the left side with padding character.
Default padding character is blank.

Format:
text = RIGHT(intext,length[,pad])
intext Input text.

length Length of the resulting text.

pad Padding character. Default is the blank.

4.6 - STRING FUNCTIONS


The string functions form a powerful group of agents in the REXX programming.
Except for a CHANGE function, I have yet to miss any string function. Therefore,
I have written a long time ago a CHANGE function using REXX. The REXX source
code of this CHANGE function is in the SMART ISPF utilities. The CHANGE
function is described in section 4.6.3 SCHANGE – Change of texts on page 86.
4.6.1- DELSTR – Delete substrings
Function:
With this function, you can remove a portion of a text. The text will shortened
by the deleted part.

Format:
text = DELSTR(intext,start[,number])
intext Input text.

start Starting position of the text to be deleted in intext. When the starting position is greater
than the length of the intext then intext is returned unchanged.

number Number of characters, which are deleted. The text will be deleted up to the end when this
parameter is not specified.

4.6.2- INSERT – Insert text


Function:
With INSERT, you can insert a text in another text. This is in a sense the inverse
function of DELSTR.

Format:
text = INSERT(intext,text[,start][,length][,pad])
intext Inserted text.

text Text to which intext is inserted.

start Start position in text after the insertion is to occur. When the starting position is omitted or
zero, then intext is inserted at the beginning of text.

length Number of characters which are inserted. When this parameter is not specified then the
current length of intext is automatically used.

pad If the entered length is greater than the current length of intext then this character expands
intext on the right as defined in length.
Example
See next function CHANGE.

4.6.3- SCHANGE – Change of texts


This function is not part of TSO/E REXX. Rather more, I developed it because a
change function in the daily work with REXX in the TSO/ISPF environment in
my opinion is essential. This function is part of the SMART ISPF utilities.
See section 15.5.12 REXX subroutine SCHANGE – REXX change function on
page 283.

Function:
Change of texts.

Format:
text = SCHANGE(intext,searchtext[,replacement][,testtext])
intext Text to be changed.

searchtext Search text. Change replaces all texts that are found with searchtext with the
replacement text in a single call.

replacement This text should replace the search text. When the replacement text is omitted or
contains a null string, then searchtext is only removed from intext.

testtext The CHANGE shall only take place if this text is included in the intext. Of course, it
does not make sense when searchtext and testtext are equal. However, the function
still runs properly.

4.6.4- LENGTH – Length of a text


Function
With this function, the length of a text is determined.

Format:
n = LENGTH(text)

N is the length of a text. If a text is a null string, then is n = 0.


4.6.5- OVERLAY – Superimpose text
Function:
With OVERLAY, you can insert a text into another text after the specified
location.

Format:
text = OVERLAY(intext,text[,start][,length][,pad])
intext Text inserted by overlay.

text Text to overlie beginning at start.

start Start position in text from which the insertion is to occur. When the starting position is
missing, 1 is assumed. When the parameter start is specified, it must contain a positive
integer.

length Number of characters to be overlaid. When this parameter is not specified, the current length
of intext will automatically be used.

pad If length is greater than the current length of intext, then this character will extend intext
before the overlay is performed.

4.6.6- POS – Search for text


Function:
Search for a text within another text. The starting position of the found text
within the input text will be returned. This function provides the same
functionality as the INDEX function. According to literature, however, you
should use POS.

Format:
n = POS(needle,haystack[,start])
needle This text is searched for in the haystack

haystack Scanned text.

start From this position in the haystack, the search is started.


4.6.7- STRIP – remove border characters
Function:
When passing parameters and texts it often happens that these texts are
featured at the front and at the rear with blanks or other characters which must
be removed. This function removes leading and trailing (same) characters from
a text. All same leading and trailing characters will removed. Since many
operations, especially when passing parameters with leading and trailing
blanks, STRIP is often used to remove these blanks. This function is often used
just for precaution.

Format:
text = STRIP(intext[,option][,char])
intext This text will be stripped.

option This option specifies whether only leading, trailing, or characters from both ends should be
removed from text. Both Removes the characters at both ends. This is the default
value. Leading Removes leading characters only. Trailing Removes trailing characters only.

char These are the removed characters. Default is blank.

1 Tip:
The STRIP function is often required in order to free DSNs from the
surrounding single quotes ('). Sometimes it happens that a DSN is entered once
with and once without the quotes. It often happens that you have to insert the
DSN in a function that absolutely needs quotation marks. In such cases, I use
the following statement:

What does this statement?


First, any existing single quotes will be removed. Thereafter, any existing
blanks will be removed and finally the DSN will set back in quotes.
Now it does not matter in which form the DSNs parameters are passed. With or
without quotation marks and blanks. The result is always a DSN with quotation
marks and without blanks.

4.6.8- SUBSTR – Extract part of a text


Function
This function extracts a text part of a text.
Format:
teil = SUBSTR(text,n[,length][,pad])
text Text from which the substring is taken.

n Starting position for extraction.

length Number of characters, which are extracted. When length is not specified, all characters will
be taken up to the end of text.

pad If length is greater than the available text, then the resulting text is extended with the padding
character. The default pad is the blank.

4.6.9- TRANSLATE – translate characters


Function:
This function translates individual characters of a text to other characters.
Translation is done in such a way that the same characters in the translation
table replace the characters found in the search table.

Format:
text = translate(intext[,replacetab][,searchtab][,pad])
intext This is the text that will be translated. If only intext is specified,then this is translated
to uppercase.

replacetab This text contains characters that are replaced in intext if these characters are found
in the search table.

searchtab This text contains characters sought in intext.

pad The fill character replaces such positions in intext where characters were found using
the search table, but do not have a corresponding position in the replace table.

Examples:

This command first replaces all apostrophes in orgdsn by blanks and then
removes all surrounding blanks from orgdsn.
argl = translate(arg(1))

With this command, the first argument that was passed by a calling program is
set to uppercase.

This command replaces the characters dot, apostrophe, left and right brackets
by blanks. The resulting string contains all qualifiers of the DSN and an
eventually contained member name as single words. To get the member name,
the following command can be used:
meml = word(dsn1,words(dsn1))

4.6.1- 0VERIFY – verify text


Function:
VERIFY checks whether a text only consists of characters of a second text or
not. This function is very good to use for validation of texts such as DSNs.

Format:
n = VERIFY(text,checktext[,option][,start])
text This is the text which is to be checked.

checktext These characters are sought in TEXT.

option Here you can specify how to perform the check:

Nomatch
When specifying N, the function returns zero when ALL of the characters of text are also included in check
text. Otherwise, the position of the first character that is not contained will be given back.

Match
When specifying M, the position of the first character in the text, which is also included in test text will back
given. If no character from check text is found in text, then zero will be given back.
start Start position in text where the search begins.
4.7 - WORD FUNCTIONS
One of the greatest strengths of REXX are the word functions. This is therefore
so useful because just in the z/OS world very many terms appear in ISPF,
programs, JCL, etc., as by blanks or special characters separated texts. From a
text such as a DSN, you can very quickly use TRANSLATE to remove the special
characters and you have a text that consists only of words.
Definition of a word in REXX sense:
–A word is a coherent text that does not contain blanks.
–Words in a string are separated from each other by one or more blanks.

4.7.1- WORD – return of a word


Function
WORD returns the nth word back from a string.

Format
ywort = WORD(intext,position)
intext String from which the addressed word is extracted by position.

position Position number of word to be returned. If position is greater than the number of words in
intext then a null-string will be returned.

4.7.2- WORDINDEX – return the starting position of a word


Function:
WORDINDEX returns the position of the first character of the nth word of a
string.

Format:
pos = WORDINDEX(intext,position)
intext String in which the selected word is addressed by position.

position Number of the word within intext, of which the position of the first character is
returned.

Examples are at the end of the section Word Functions found.


4.7.3- WORDLENGTH – return the length of a word
Function:
WORDLENGTH returns the length of the nth word in a string.

Format:
length = WORDLENGTH(intext,position)
intext String in which the by position selected word is addressed.

position Number of the word whose length will be returned.

4.7.4- WORDPOS – search for a word


Function:
WORDPOS searches a word in a string and returns its position.

Format
pos = WORDPOS(word,string[,start])
word Searched word. If the word is not found in the string, zero will be returned

string String composed of several words.

start Word position where search starts.

4.7.5- WORDS – number of words in a string


Function
WORDS returns the number of words contained in a string.

Format:
number = WORDS(intext)
intext String whose number of contained words are to be given back.

Program 4.4: WORDFUNC – Examples of WORD function


This program produces the following list:

4.8 - SYSTEM FUNCTIONS


The system functions return information about the z/OS system and its
resources under which control a REXX program is currently running. These
functions are described in the literature as TSO/E External Functions. They can
be found under this heading in the brochure TSO/E REXX Reference.

4.8.1- LISTDSI – List data set information


Function:
This function returns a wealth of information concerning a data set. A detailed
description of this function is found in section 4.8.1 LISTDSI – List data set
information on page 93. If you need any information about a file, you must call
up three functions. These are the functions LISTDSI, DSINFO and LMDLIST.
Practical examples of all three functions can be found in the source code of the
SMART ISPF utility SSC, in the section 15.4.23 Program SSS – Perform a Super-
Search on page 271. See also section 8.2.2 DSINFO – ISPF service which
provides data set information on page 162 and 8.2.1 LMDLIST – Data set list
service on page 161.

4.8.2- MSG – control of the TSO messages


Function:
With MSG, you can specify whether the possibly during the program run
occurring TSO messages are outputted directly or not. This is sometimes very
helpful when you get TSO messages at a point in the program where you would
like to suppress them.

Format:
msgstat = MSG("ON"|"OFF")

This call returns the status of MSG, which can be ON or OFF. This function is
very useful when you wonder why TSO messages do not appear.
x = msg("ON") This call switches the display of the TSO messages to ON.

x = msg("OFF") This call switches the display of the TSO messages to OFF.

Example:

Note:
The TSO DELETE command always produces a message. In this case, the active
ISPF panel disappears and the delete message will be displayed. Since this is
very annoying and I do not want to see the message from TSO DELETE, here I
suppress the output of the message by setting x = msg("OFF").

4.8.3- MVSVAR – Return z/OS system information


MVSVAR returns various information about the z/OS system. A parameter
keyword is mandatory defining the value you wish to receive. I have often used
only one of these values. This is the name of the z/OS LPAR. That is the four-
character logical partition name where my program is running. You get this
value as follows:
lpar = MVSVAR(SYSNAME)

If you need more information about this feature, view the detailed description
of this function in the brochure TSO/E REXX Reference.

4.8.4- OUTTRAP – take TSO messages


Function:
OUTTRAP is a very frequently used function. REXX programs use OUTTRAP to
store TSO outputted messages in a stem. You can use these TSO messages in
your REXX as you like.

Format:
x = outtrap(name.)

This call ensures that from now on all TSO messages are written in the
stem name.
x = outtrap("OFF")

This call finishes writing of TSO messages in the stem name. TSO stores the
number of rows of the stem in name.0.

Example 1: Intercepting the messages of the SUBMIT command.

Explanation of the REXX statements:


Lines Explanation

1 With this statement, the TSO is informed that from now messages are no longer sent to
SYSTSPRT, but instead written into the stem text.

2 TSO executes the SUBMIT command and writes the resulting messages in the stem text.

3 The trapping of the TSO messages will be switched off. The variable text.0 now contains the
number of the TSO message lines in the stem text.

4 The messages from row two will be outputted. Since SUBMIT usually produces only two lines
and the text that interests us is always in the second line, we only print this line. The output
line might be:
JOB LANZT373(JOB06586) SUBMITTED

Example 2: Outputting the file information and members list of a PDS.

Program 4.5:Example of calling the TSO function LISTDS


Printed output:

Remark:
I will not describe the LISTDS function here in detail. The above example may
suffice as information. The description of the TSO function LISTDS is contained
in the brochure TSO-E Command Reference.

4.8.5- SYSDSN – check data set status


Function
Use SYSDSN to determine whether a file exists and that you can access it.

Format:
text = SYSDSN(DSN)

DSN must appoint a cataloged file.

The SYSDSN function returns ONE of the following texts, which are self-
explanatory:
Example:
The following program part allocates a data set. If the data set already exists, it
is only allocated. If it does not exist, it will be created.

4.8.6- SYSVAR – get system Information


Function
With SYSVAR, similar to MVSVAR, some system information can be retrieved.
Here only two information points at run around procedures are of interest:

Example 1: Does a program run in foreground or in background.


foreground means: The program runs in the ISPF online.
background means: The program runs under ISPF that is started as a batch job.
Remark:
It is important to know this operating mode, because maybe files are be
assigned in a batch job via DD statement in the JCL, while in foreground mode
the TSO alloc command must be used. On the other hand, any error messages
in background mode differently than in foreground mode are outputted. For the
query where the program runs, you can use the following statement:
runenv = SYSVAR(SYSENV).

After this call, runenv contains FORE or BACK.

FORE → The REXX program runs in foreground.

BACK → The program runs in background in a batch job.


Example:
Program 4.6: Control messages display ONLINE and in BATCH

If the procedure is running in the foreground, the error message is displayed in


an online window using SETMSG. Otherwise, the error message is sent via SAY
to the SYSTSPRT DD in the batch job.

Example 2: Does the program run in the ISPF environment runs


If you execute REXX procedures, which need ISPF services in batch jobs, then
you should definitely check whether the ISPF is also available in the batch job.
If not, you have to abort the procedure with an appropriate error message. If
the procedure continues, there may be inexplicable crashes.
For this query, you can use SYSVAR(SYSISPF). This call returns ACTIVE when
the procedure is running under ISPF. It returns NOT ACTIVE when the
procedure only runs under TSO.

Example:

4.8.7- STORAGE – read and write memory contents


Function:
With this function, you can read out memory contents and overwrite them. The
possibility of overwriting should be handled with caution. This function is
normally to read memory contents, which contain interesting information
used.

Format:
value = STORAGE(address,length,text)
value Result.

address Specifies the memory address from which the data are collected in length. This address
must be specified directly in the form of hexadecimal digits.

length Specifies how many bytes are to be read or written at the starting address.

text If anything is specified here, this text replaces the memory contents beginning with address
in the length of text. Before replacing the contents starting at the addressed memory
location, the previous contents are stored in the variable value.

Note:
The replacement of memory locations should be handled very carefully. You
can shoot down your own address space. However, you do not need to worry,
because with the security rights that you have as a normal user, you cannot
override system areas.

Example 1:
The Common Vector Table (CVT) contains pointers to other tables in the z/OS
system. Therefore, if you want to read data from these tables, such as the job
name, then you first have to read the contents of the CVT . This address is
common in all z/OS systems at the memory location 16. The number 16
expressed as a hexadecimal number is 10. The pointer to the CVT is always four
bytes long.

The result of the command say c2x(storage(10,4)) is in my currently being


running system → hex 00FCBE18.
Starting from this address, you can now point through all control blocks until
you have found the information you need. You can find an example in Screen
4.1 Read the job name from CVT on page 77.

Example 2
I found another example of the application of the STORAGE function on the
Internet. It gets the name of the program that is currently executing.
Program 4.7: PROGNAME examples for using STORAGE function
Note:
If this program is executed online under ISPF, the displayed name is always
IKJEFT01. This is the TSO processor.

5-The TSO/E REXX commands


In addition to the normal TSO commands, there are some commands that
execute the TSO/E specifically for REXX. These commands are like all TSO
commands, using literals to send them to the TSO. Some of these commands are
only executable when called up from a REXX procedure. I would like to present
the most important commands here.
Note
In REXX on other platforms, these commands are not available. For example,
the EXECIO command is not available in OOREXX. This is really a deficit of
OOREXX!

5.1 - EXECIO – READ AND WRITE DATA SETS


This is the most widely used TSO/E REXX command. EXECIO uses the QSAM
method of z/OS. This means that all advantages and disadvantages of this
access method are also applicable for EXECIO.

Remarks:
–To run an EXECIO command, a DD name must exist that is named in the
EXECIO command. When running a REXX procedure in a batch job, this can also
be done by a DD statement in the JCL.
–The EXECIO command can read data from the data stack as well as write data
to the data stack.
–The EXECIO command can read the data into a stem as well as write data from
a stem. In this case, the name of the stem must be specified in the parameter
field.
–The file specified with the DD statement can also be a member of a PDS or
PDSE.
–When writing data records that are longer than the LRECL of the file, the
records will be truncated and EXCECIO completes the operation without an
error being ex- plicitly reported. However, in this case, the return code 1 is
returned by the command EXECIO.
–Records can be individually read and written. However, this is rather rare in
practice, as this would slow down the process.

Format:
"EXECIO lines iotyp ddname (parms"
lines Specifies the number of records to be read or written:

0 → no records are written or read.

* → all records are written or read.

n → number of records that are written or read.

iotyp DISKRRead operation.


DISKW Write operation.

ddname This is the name of an already allocated DD.

parms STEM name. Is the name of a stem from which is written or into which is read.
OPEN The data set shall be opened. OPEN will automatically be performed when records
are read or written. Normally, this option is never used.

FINIS The file will be closed when the I/O operation ends.
Program 5.1: EXECIOT – Example for the TSO function EXECIO

The following table contains descriptions of the statements of this small test
program:
Lines Explanation

05 Allocation of member PROX.BOOK.REXX(EXECIOD) as a sequential file named DD


OUT.

06 Empty the file without deleting it.

07-14 Assigning lines to Stem A. The line A.1 is much longer than the LRECL 80 of the data set.

15 Store the number of records in stem A.

16 Write stem A. into member EXECIOD and CLOSE the data set.

17 Set A.0 to zero.

18 Read all records of the file. A.0 now contains the number of records, namely 8

19-20 Change records 5 and 6 in stem A.


21 Write stem A. again into member EXECIOD and CLOSE the data set.

22 Free the DD name OUT. The data set PROX.BOOK.REXX(EXECIOD) is also freed.

Here you can now see the contents of the member EXECIOD after the above
program is running:

As you can see, the first record was shortened to LRECL=80 when writing the
member EXECIOD.

5.2 - DELSTACK – DELETE DATA STACK CONTENTS


Function:
This command will delete data stacks.
–Deletes the last opened data stack.
–If no data stack was open then the original data stack will be deleted.

This command is mainly used to delete the current data stack.

5.3 - DROPBUF – DELETE DATA STACK BUFFERS


Function:
Use this command to delete data stack buffers that were previously created.
The command has one operand. This indicates what number of the buffer was
cleared. If no operand is specified, the last with MAKEBUF created buffer will
be cleared.

5.4 - TSO COMMANDS


All TSO commands are usable in REXX programs. In addition to the TSO
commands discussed so far, I will now explain some more TSO commands that
are very useful for programming REXX applications. Important commands are
ALLOC, FREE, LISTDS, SUBMIT, EXEC.

Rules:
–As discussed above, all strings which are found in REXX programs and are not
recognized by the REXX interpreter, will passed to the currently active host
command environment for execution.
–When a REXX program starts, then the host command environment for TSO is
active. Therefore, an ADDRESS TSO command is not necessary in this case. As
long as you do not switch the host command environment to another
subsystem, can you execute TSO commands simply by writing them in a
program line surrounded by apostrophes.

Example 1: Simple allocation of an existing data set.


Example 3: The TSO command LISTCAT is used to print a
catalog extract.

If this small program is executed, the following list will appear:


I truncated some lines on the right.

Remark:
Generally, all commands of the Access Method Services are usable as TSO
commands and thus also with REXX.

See manual: z/OS DFSMS Access Method Services for Catalogs

6-Execute REXX programs


The REXX programming language would be very limited in its application if
REXX programs could only run online in the TSO/ISPF environment. In this
chapter, you will learn how REXX procedures under TSO and ISPF can run using
a batch job. The execution of REXX procedures in batch jobs have the following
advantages:

6.1 - EXECUTION OF PROGRAMS IN A TSO/ISPF


ENVIRONMENT
Any programs that are available in a z/OS system are executable in a TSO/ISPF
environment. There are two types of programs:
–Programs are executable directly in z/OS without any additional support.
These are all compiled programs and z/OS utilities.
–Programs needing the assistance of an interpreter are all programs written in
REXX or CLIST.

The latter are divided into two groups:


–REXX and CLIST programs that only need the TSO interpreter environment.
–REXX and CLIST programs that additionally need the ISPF environment.
All programs are executable online and in batch. Programs written in REXX or
CLIST need for an execution in batch, of course, the appropriate interpreter.
When these programs use ISPF services, the ISPF environment must also be
available. For means of explaining the entire complex of program execution
under a number of conditions, I have developed two REXX programs. Both are
very small. They take a parameter and print its content.

TEST1: This program only needs the TSO environment.


TEST2: This program additionally needs the ISPF environment.

Here the source code lists of both programs:

Program 6.1: TEST1: Simple program using the TSO environment only

Program 6.2: TEST2: Simple program using the ISPF environment

Note:
If this program is running online, then the message is printed using the SETMSG
service of ISPF. When it runs in batch, the message uses the SAY command of
REXX.

6.1.1 Online execution


For the online calling of a program, you do not know whether this is a procedure
or a compiled program. Moreover, you do not have to worry about the program
requiring ISPF services, because you are already working in ISPF. Nevertheless,
you have to know if there are parameters needed for the correct execution.
Programs can be executed online as follows.
–You can execute a REXX program by using the edit macro ## contained in the
SMART ISPF utilities when the program is currently being edited. This means
simply enter in the command line of the editor “## testl This is a text”.
–Type in the command line “tso testl This is a text”.
–Enter in a DSLIST display panel TEST1 in front of a DSN. In this case, the DSN
will be passed to the program as a parameter.
–Select the ISPF menu 6 Command and enter in the = = = > line “testl This is a
text”.
–Insert a CMD command entry in the ISPF command table to execute the
program. In this case, you can start the program by entering the command
name in the command line of each ISPF panel. See the information to insert a
command table entry in the chapter below. The SMART ISPF utility program
SLE is a typical candidate for this type of call. See the following command table
entry example:

I will not demonstrate the online execution of the above program here. This is
so simple that I really do not have to show it.

6.1.2 Batch execution


Executing a REXX program in a batch job is not as easy as in the online
environment because an appropriate JCL program is required which is
submitted to the batch system environment for execution. This is initially a
difficult thing, because you need to know how the JCL must be designed to
operate properly. In my work in the TSO / ISPF, this problem occurred earlier
repeatedly. Therefore, long time ago I developed two EDIT macros that relieve
me of creating each required JCL. These two edit macros are:
–#TSOB to submit and execute REXX programs which only need the TSO
environment.
–#ISPFB to submit and execute REXX programs which additionally need the
ISPF environment.

If a program requires input parameters, these can entered when calling. I


executed the two programs TEST1 and TEST2 each with the correct edit macro.
I have added the resulted JCL programs below.
JCL 6.1: JCL to execute TEST1 in a native TSO environment

When running this program, the following list is printed. It can be found in
SDSF.
JCL 6.2: JCL to execute TEST2 in a TSO/ISPF environment

When running this program, the following list is printed. It can be found in
SDSF.

I think you now have the necessary knowledge to understand the following
chapters.
7 Introduction to ISPF programming
In the preceding chapters, I you with the operation of ISPF. Likewise, I
familiarized you with the programming language REXX. Now that you have the
necessary knowledge in REXX programming, I will show you how to create ISPF
applications.

7.1 PROGRAMMING LANGUAGES USEABLE IN


ISPF
The following programming languages can be used to create ISPF applications:
– Assembler
– REXX
– CLIST
– PL/I
– COBOL
– VS FORTRAN
–C
– PASCAL
– APL2

I marked REXX in the above table. In this book, I will only use REXX as
programming language to develop ISPF applications. From the above
mentioned languages, REXX is the easiest to use, the fastest and most elegant
language. REXX requires the least effort to create ISPF applications.

7.27
ISPF is a dialog-oriented online system while CICS and IMS are transaction-
oriented online systems in z/OS MVS. Dialogue oriented means in this context
that an online program remains in memory as long as the user works in
dialogue with it. This has the advantage that you as a programmer of online
applications in ISPF do not have to worry about subsequent transactions,
storage of data between transactions, etc. At delivery, a toolbox with all the
tools needed for programming applications running in ISPF is already included.
These tools are described in the following IBM brochures:
ISPF Dialog Developer's Guide and Reference

and

ISPF Services Guide


There are essentially tools for creating or editing the following items:
– Data sets
– Panels
– Messages
– Skeletons
– Tables
– Variables

We will discuss in detail all of these elements during the further course of the
book. For each of the above elements I will give you below a brief introduction
followed by examples for each element.

Data sets

REXX normally processes only sequential data sets. This may also involve
members of a PDS. There are also functions for editing directories of PDS. VSAM
and other types of data sets can be processed with special access programs. For
processing DB2 tables See following URL: http://mainframe-tips-and-
tricks.blogspot.de/2011/12/sample-db2-rexx-rogram.html and http://www-
01.ibm.com/support/knowledgecenter/SSEPEK_11.0.0/com.ibm.db2z11.doc.
apsg/src/tpc/db2z_codesqlstaterexx.dita

Panels
Panels are created using the ISPF editor. They consists of two parts: The first
part defines the representation on the screen. The other part performs a certain
plausibility check and defines for which fields help panels are available.

Messages
ISPF provides a very simple and user-friendly way to define messages and
output them as required. The messages can be outputted from programs and
from panels.

Skeletons
Skeletons define a mask for creating data sets, where the variables which are
defined in the skeletons will be replaced automatically by the contents of the
variables of the same name in the REXX procedure. Skeletons are mostly used
for creating JCL lines. The ISPF editor is used to generate skeletons. When a
REXX program calls a skeleton, then all variables in the skeleton are replaced
by the values that are defined in the REXX program with the same name.

Tables
Tables are by programs created and edited using appropriate ISPF functions.
Tables consists of a special ISPF data type. They can only be stored as members
in special ISPF table datasets of type PDS. Since they are interspersed with ISPF
control data, their content can be viewed with edit and browse.

Variables
Variables play a major role in ISPF. ISPF itself contains a large amount of
variables that can be used in some ISPF elements such as panels, messages and
programs. ISPF differentiates between system variables, normally starting with
Z and user variables that can be anything called. The name must not be longer
than eight characters. A table of system variables is found in Appendix D of the
IBM manual ISPF Dialog Developer's Guide and Reference found.

Conclusion
Now having introduced you to the theoretical programming elements, I want to
look at some examples from my practice. The examples are purposely from
practice, because I do not want to bore you with simple things. I ask for your
understanding that I cannot explain the commands and procedures for each
example in detail as this go too far. All the different elements in the examples
are anyway discussed in more detail later in the book.

7.37
7.3.1 Example for use of ISPF panels
The program SSS belongs to the SMART ISPF utilities. It is called in front of the
name of a data set to perform a SUPER SEARCH in a DSLIST panel. The panel
SSSP1 shown below is used by the REXX procedure SSS to read in the text to be
searched for.
Program 7.1: Panel definition of panel SSSpl

The variables SSP1 to SSp14 that contain the search texts are written into the
ISPF profile and are again read before the panel is recalled. Therefore, I do not
have to reenter the search text on every call to SSS. Reading and writing of the
variables using VGET and VPUT could also be performed in the panel, but I
decided to do this in the SSS procedure. Here is the excerpt from the REXX
procedure SSS which calls the panel SSSP1:
7.3.2 Example for use of skeletons
Skeletons are mostly used to assemble extensive job streams. For such an
application, I have taken the following example.

Function:
In a large job step must be commands inserted which perform BIND PACKAGE
for DB2. Since this job must be created for different LPARs, all values that relate
to the individual LPARs are kept variable.

Here first the skeleton member. The variables in skeletons always begin with
an ampersand (&) character. The association of variables with text or other
variables will done by a period (.). Since points must separate the individual
qualifiers of DSNs, you will have to use two points when creating DSNs by
linking variables in skeletons.

JCL 7.3: Skeleton VINTPAC


In the following part of the program variables are defined that are needed in
the skeleton VINTPAC to produce the job step. When the statement ISPEXEC
FTINCL VINTPAC is executed, the skeleton variables are replaced by the actual
values.

Note:
Some variables containing in the skeleton are set already earlier in the
program. Therefore, they do not appear in this part of the program.

Here is the created step in which the variables with real values have been
replaced:
JCL 7.4: Job step build by skeleton VINTPAC
This is a complex example from practice. Try to understand the process. All
important places are grayed out. We will deal in a later chapter in detail
concerning the use of skeletons.

7.3.3 Example for use of tables


ISPF tables are data objects that are normally processed within programs using
ISPF. ISPF tables can be viewed and manipulated directly using the ISPF option
7.4. This tool is actually only useful for testing purposes.

Example:
As an example, I want to take the table that is used in the program SLE of the
SMART ISPF utilities. It contains the names of the recently edited data sets,
along with other information such as date and time of use. First, here is the
program section of the edit macro #IMACRO2 that is called when an edit
session ends. Here, the Table $SLETAB is opened and the DSN of recently edited
data set is inserted in the table. When a member of a PDS was edited the
member name will be inserted in the DSN. If the table does not exist, it is created
and written after processing into the ISPF library ISPPROF. The following part
of the program SLE shows the insertion of a DSN in the table $SLETAB.
Screentext 7.1: Program part from SLE – Insert a DSN into table $SLETAB

Here is the part in the program SLE which displays the panel SLEP1 containing
the contents of table $SLETAB.

Moreover, here the panel:


Screen 7.1: Panel SLEP1 displayed by the program SLE
When I put the cursor in front of a DSN positioned in this display, I can enter
selections for edit, view, browse etc. This panel appears again at the end of each
action and I can make a new selection. A detailed description of the application
is in section 12.5 Example of working with tables on page 218.

7.3.4 Example for use of ISPF variables


There are two types of ISPF variables:
– System variables
– User variables

System variables are, as its name implies, created and managed by ISPF. You
can use them in all ISPF functions. In some, you can change the content. See
ZEDLMSG above. Some system variables are assigned to specific ISPF services.
Since I have used in the shown examples so far some variables of both types, I
will refrain from further examples. However, I want to show you how you can
view the currently defined variables and their contents in your ISPF. To do this,
I proceed as follows: I choose the ISPF option 7.3 and get the following panel,
which is showed shortened below:
Screen 7.2: ISPF variables display using ISPF menu 7.3
If permitted by ISPF, you can change the contents of variables, delete them
entirely or create new variables in this panel. I grayed some of the Z-variable.
These contain values that are often needed in daily operations. To get the
contents of ISPF variables, read them using the command:

"ISPEXEC VGET (ZDATESTD ZACCTNUM ZAPPLID ZDAY ZDAYOFWK


ZJDATE ZJ4DATE", "ZDATE ZDATEF ZTIME ZTIMEL)"

7.3.5Example for data processing with TSO and ISPF


For the processing of data sets, you have two options in an ISPF environment
and in the use of the language REXX:
– Use the REXX command EXECIO that only needs the support of TSO.
– Use ISPF data set management services. Then you additionally need ISPF data
set services.

This distinction is important because it decides whether the procedure to


perform I/O operations requires only the TSO level or additionally the ISPF
level. This definition is particularly important too, when the intention is to use
the procedure in batch jobs. The ISPF environment is in the first case not
required but always in the second. This is important for preparation of the
batch jobs, as we can see in the chapter 6 Execute REXX programs on page 105.

Example of data set processing with TSO and ISPF:


To explain the difference between I/O operations using the TSO command
EXECIO and the ISPF LM services I wrote two programs, which each perform
the same work. They read a flight log and summarize the number of flights
conducted and hours of flight time for each aircraft type found in the records.
Here the source code of both programs:
Program 7.2: IOEXMPL1 – Read records using EXECIO of TSO
Program 7.3: IOEXMPL2 – Read records using LM services of ISPF
These both programs produce exactly the same result. I have grayed the
statements used for each I/O method. It is obvious that the method with EXECIO
by far requires the lower programming costs. The actually necessary error
query and error analysis after each ISPF command has been deliberately
omitted to improve clarity of the code.
Notes:
The processing of data sets using ISPF LM services is much faster than the
method using TSO EXECIO. In addition the error checking and error analysis
that ISPF provides is much better than TSO offers. Sometimes the higher
programming costs are worth.

7.3.6 Output of messages with ISPF


For the issuance of messages in the ISPF, a standard procedure is available. In
its use, ISPF system variables will be filled with contents. A standard ISPF
service dis- plays these special variables on the screen. This service is only
usable for outputting messages online on a screen. It is not usable to print the
messages in a batch job. If a REXX procedure shall be run online as well as in
batch the output of messages must be controlled accordingly. See section
9.1.2 Output of error messages on page 178. The following excerpt from
the Appendix D Dialog variables of the IBM manual ISPF Dialog Developer's
Guide and Reference shows the ISPF system variables concerning error
messages:
Table 7.1: ISPF system variables concerning error messages

Variable Length Description

ZERRALRM Char 3 The value is set to YES if an alarm was specified in the message definition
otherwise, the value NO. Set when ISPF services issue a return code of 8 or
greater.

ZERRHM Char 8 The name of a Help panel, if one was specified in the message definition.
Set when ISPF services issue a return code of 8 or greater.

ZERRLM Char Long-message text in which variables have been resolved. Set when ISPF
512 services issue a return code of 8 or greater.

ZERRMSG Char 8 Message ID. Set when ISPF services issue a return code of 8 or greater.
ZERRSM Char 24 Short-message text in which variables have been resolved. Set when ISPF
services issue a return code of 8 or greater.

How messages are displayed?


ISPF offers a standard method to display messages when a program runs
online. These messages are displayed on the ISPF screen. The ISPF
service SETMSG is used to display the messages. The SETMSG service expects
the error messages in the two special variables:

ZEDSMSG

ZEDLMSG
S and L stand for SHORT and LONG. This means that you can put a message up
to 24 characters in ZEDSMSG and in ZEDLMSG a long message up
to 512 characters. See Screentext 7.1: Program part from SLE – Insert a DSN
into table $SLETAB on page 115.
The ISPF service SETMSG writes the error message texts contained in ZEDSMSG
and ZEDLMSG on the currently displayed screen. However, the following rules
are to be considered:
– If the variable ZEDSMSG contains a text, then initially only this text is
displayed on the right top corner of the screen and nothing else happens. First,
when the user presses PF1, then the related ZEDLMSG message will also be
displayed on the bottom of the screen.
– If the variable ZEDSMSG contains nothing, only the ZEDLMSG message is
immediately displayed on the bottom of the screen.

Example:

Notes:
The SETMSG service is usable for every display of messages. You can generate
an error message in ZEDLMSG by combining the content of ZERRLM together
with your own texts. You can fill the variables with a text of your choice and
display them. It is not necessary that a program error situation is present.
Program example:
The following program shows two typical applications of the ISPF message
services:
– In the first use of the service are the names of data sets, which have an ENQ
reservation displayed. The function QUERYENQ detects such ENQs. These are
the statements 202 to 212.
– The second application displays an error message when a data set should be
edited for which the editor is unable to edit.
Screentext 7.2: Example of the ISPF messages service

There are two possible messages displayed:


1. An attempt was made to edit an ENQUED data set.

2. This error message is self-explanatory.

7.4 LIBDEF – DYNAMIC LINKING OF ISPF LIBRARIES


We have already discussed the ISPF libraries earlier in this book. And we have
also seen that some library chains must be assigned before ISPF starts.
However, if you want to run an application of ISPF objects stored in own ISPF
libraries; you have to copy all these objects in the appropriate permanently
assigned libraries. As this would be very costly and impractical, ISPF contains a
command to allocate additional libraries dynamically before the existing
permanently allocated libraries. This is the LIBDEF service.

Function:
Allocate additional data sets to the existing ISPF libraries dynamically and
remove such assignments again.
With these options, you can define how the LIBDEF chains shall be arranged.
Advice:
Always use the STACK option. If this option is missing when creating the
LIBDEF and you reset this LIBDEF assignment, then all pre-existing LIBDEFs
also cancels. If you have called a new application from another application
which also has LIBDEFs, their LIBDEFs are also withdrawn. This means that you
can no longer work with the previous application after return.
Program 7.4: LIBDEF example

Use the ISPF command ISPLIBD to display the current LIBDEF assignment. See
the following screen. It shows the currently assigned LIBDEFs within this
logical ISPF screen.
Screen 7.3: ISPLIBD – Display the current active LIBDEF assignment
Advice:
The LIBDEF definitions apply only to the logical ISPF screen in which they are
executed. This is necessary because otherwise you could not even run different
ISPF applications simultaneously on several logical ISPF screens.

7.5 ALTLIB – DYNAMIC LINKING OF EXEC LIBRARIES


With LIBDEF, only ISPF libraries can be set before the default associated
libraries. However, when a REXX program executes, the system searches for the
program only in the libraries that are allocated under SYSEXEC or SYSPROC.
With the ALTLIB command other data sets can dynamically be assigned before
the SYSEXEC and SYSPROC libraries. The ALTLIB command has to be executed
as a TSO command. As we will see below, the ALTLIB command works slightly
different in an ISPF environment as in a pure TSO environment.
The ALTLIB command can achieve the following:
– Define alternative libraries for procedures calls.
– Define the user, application and system-level libraries that are used for
searching programs.
– Exclude one or more libraries level from the search.
– Reset the search order to the system level.
– View the current search order.

Normally, the TSO is set so that when a procedure is called, then the SYSEXEC
library is first searched and afterwards the program is searched in the SYSPROC
library. This is of course only valid if both library types are assigned.
The command TSO ALTLIB DISPLAY displays the current ALTLIB setting:

Example:
Current search order (by DDNAME) is:
System-level EXE CDDNAME=SYSEXEC
System-level CLIST DDNAME=SYSPROC

7.5.1 Search sequence in the procedures libraries


The following table shows the search order for procedures libraries. The
corresponding DD names will also displayed. These DD names can either be
created dynamically with the ALLOCATE command or have been created even
by the login procedure.
Table 7.2: Search sequence in the procedures libraries
Example 1:
Temporary activation of a library for executing a REXX procedure from that
data set.
"ALTLIB ACTIVATE APPLICATION(EXEC) DDNAME(##DD)"
"ISPEXEC SELECT CMD(%"mem strip(pp)")"
"ALTLIB RESET"

Here is the data set that is already allocated under the DD


name ##DD, provided for the call of the procedure named in the SELECT
statement.

Example 2:
Disable the CLIST system level.

TSO ALTLIB DEACTIVATE SYSTEM(CLIST)

When I now execute the command TSO ALTLIB DISPLAY, the following display
occurs:

Current search order (by DDNAME) is: System-level


EXECDDNAME=SYSEXEC

This means that procedures in the SYSPROC allocation will not be found
regardless whether the allocation exists or not.

Example 3:
I have written a small REXX procedure that executes some ALTLIB commands.
Program 7.5: ALTLIB1: Example of the application of the command ALTLIB
When the procedure executes, the following display appears:

7.5.2 The ALTLIB command in ISPF


As long as ALTLIB commands are used only under TSO, the once by ALTLIB set
search sequences remain active until they are changed with another ALTLIB
command. On the other hand, when the ALTLIB command is called under the
ISPF environment, this rule changes as follows:

Rules when ALTLIB is used in the ISPF environment:


– If you use ALTLIB while ISPF is active, you can issue this command on the
application level. Libraries that are allocated by a running application remain
active as long as this application is running. When the application ends, the
state is the same as before calling the application.
– When an application is started in the ISPF split screen mode which settles
ALTLIB commands, then their defined search order applies only to this split
screen panel.
– Libraries that are allocated at the start of an application in the ISPF will not
be deactivated by the NEWAPPL and PASSLIB parameters in the SELECT
command.
– If an application is launched while NEWAPPL is specified, but not PASSLIB,
you will not have all LIBDEF and ALTLIB pre-allocated libraries in this
application available. They are only available again when this application ends.
– If an application is started using NEWAPPL and PASSLIB, then all library
allocations previously created with LIBDEF and ALTLIB remain active.
However, LIBDEF and ALTLIB allocations that are made in this application are
only active as long as the application is running.
– If neither NEWAPPL nor PASSLIB are specified when starting an application,
then all previously with LIBDEF and ALTLIB created allocations are active in
this application. Any changes made using LIBDEF and ALTLIB in this
application remain active even after the end of the application.
– ALTLIB allocations that were made before starting of ISPF are unknown after
the call to ISPF.
Conclusion:
I freely admit that these rules are somewhat complex and confusing. Therefore,
I recommend that you familiarize yourself with the topics ALTLIB and LIBDEF
by performing own tests.

7.5.3 Stacking of the APPLICATION level ALTLIBs


If multiple ALTLIB commands are issued on the APPLICATION level within an
ap- plication, they will be stacked up to a depth of eight levels. This stacking
takes place so that always the last created allocation is at the top.
Example: stacking APPLICATION Level ALTLIBs.
Program 7.6: Stacking ALTLIB commands
Here is the output that generates the above procedure:
As you can see, only the DD names of allocated data sets are displayed. If you
want to see the associated DSNs, you can view them using the ISPF command
DDLIST.

7.5.4 The QUIET operand of the ALTLIB DISPLAY command


If you use the ALTLIB DISPLAY command in ISPF, you can specify the QUIET
option. This option ensures that the ALTLIB DISPLAY command output
information will not be outputted via SYSTSPRT but rather written in ISPF
variables in the SHARED pool. You can then use these ISPF variables to use the
information contained therein in the program.
The following ISPF variables will be filled:
– IKJADM contains the number of rows that were written in ISPF variables.
– The variables IKJADM1 to IKJADM99 contain the individual lines. The
following example shows how you can use these service in a program:
Program 7.7: ALTLIB3 – Using of ALTLIB DISPLAY QUIET command

I ran the program. It produces the following output:


8 Data set processing using ISPF
ISPF offers a wide range of services for processing data sets. Except for a few
special commands, all dataset services in ISPF begin with the prefix LM. This
prefix stands for: Library Management. All together, I counted 25 services that
are currently available. If you are concerned for the first time with the LM
services, immediately the question arises: What do I need for a specific project?
A first example is shown in the Program 7.3: IOEXMPL2 – Read records using
LM services of ISPF on page 120.
Note:
The commands that I describe in the following chapters, usually know many
more parameters than I will discuss. I explain only parameters I have already
used during my practical work in ISPF.

8.1 THE LM SERVICES


When using the LM Services several service calls in the correct order are always
required.

8.1.1 Grouping of LM services


Whenever I need to accomplish something with data sets in a REXX program, I
am faced with the question: With or without ISPF services? One thing is
immediately clear. The use of ISPF Services requires a higher programming
effort than simply the EXECIO command from the supply of TSO REXX
commands to use. See Program 7.3: IOEXMPL2 – Read records using LM
services of ISPF on page 120. So, what are the reasons to take ISPF services for
data set processing anyway? The reasons may be:
–File processing with ISPF services have a much better performance.
–Error control and error analysis is much better.
–There are extensive opportunities with members and member lists to work.

While only a TSO ALLOC command must be executed before using the EXECIO
command, a whole series of commands is necessary to use the ISPF services for
data set processing. Moreover, these commands must run in the right sequence.
I would like to provide guidance to use the right services for a particular task in
the table below. In the right column, you will see the commands that are
necessary to perform a complete service process. The one or more nucleus
commands for performing a service project are displayed in gray. I added
options that must be necessarily set for certain tasks. I also added notes behind
individual commands that are important when using this service.
Attention:
Never forget to execute the final commands LMCLOSE and LMFREE so that the
used resources are completely free after the action. If these two commands are
not executed, the resources remain locked for further editing. There is no way
to subsequently execute the two commands when the program has ended. In
this case, the blocking of resources can only be lifted by LOGOFF and LOGON.

Table 8.1: Grouping of LM commands necessary for a particular type of


data processing

Processing type Necessary services sequence

Read a sequential data set LMINIT

LMOPEN

LMGET (in a DO loop)

LMCLOSE

LMFREE
Read a member sequential LMINIT

LMOPEN

LMMFIND (localize a member) LMGET (in a DO loop)

LMCLOSE LMFREE

Write a sequential data set LMINIT

LMOPEN

LMPUT (in A DO loop)

LMCLOSE

LMFREE

Write a member sequential LMINIT

LMOPEN ... OPTION(OUTPUT)

LMPUT (in A DO loop)


LMMREP (write a member)

LMCLOSE

LMFREE

Copy a member LMINIT (Input)

LMINIT ... ENQ(SHR) (Output)

LMCOPY
LMFREE (Input)

LMFREE (Output)

Move members LMINIT (Input)

LMINIT ... ENQ(SHR) (Output)

LMMOVE

LMFREE (Input)

LMFREE (Output)

Delete members LMINIT ... ENQ(EXCLU)

LMOPEN ... OPTION(OUTPUT)

LMMDEL

LMCLOSE

LMFREE

Rename members LMINIT ... ENQ(EXCLU)

LMOPEN ... OPTION(OUTPUT)

LMMREN

LMCLOSE

LMFREE

Display or change member LMINIT


statistics

LMMSTATS
LMFREE

Compress a PDS LMINIT ... ENQ(EXCLU) LMCOMP LMFREE

Read the member list of a LMINIT


PDS

LMOPEN

LMMLIST (in A DO loop)

MLCLOSE

LMFREE

Display the member list of a LMINIT ... ENQ(EXCLU)


PDS in a panel.

Members can be selected. LMOPEN ... OPTION(OUTPUT)


The selected

member name is returned. LMMDISP

LMCLOSE

LMFREE

View member list of several address TSO “alloc ...dsn(dsnlist)”


concatenated

data sets for editing. LMINIT

MEMLIST

LMFREE

address TSO “free ...”

Display DSLISTs like in the lvl = “PROX.LANZ.**”


ISPF menu 3.4
LMDINIT ... LEVEL(“lvl”)”

LMDDISP

LMDFREE

Notes:
In the following description of the individual services, I will mainly use the
descriptions of the IBM brochure ISPF Services Guide to explain a service.
Since however as the accompanying examples are very brief in all the
brochures of ISPF, I will bring to (almost) every service a sample program that
was tested by me. The resulting printout of the programs will always be shown.
Only for services where the function is very simple (e.g. LMFREE), I will not
spend any time explaining. In the descriptions of the individual parameters, I
will always mark the default values in gray.

8.1.2 LMINIT – Start of the data set processing


Function:
Each data set processed by ISPF services begins with LMINIT. The main
purpose of this command is to link the physical data set(s) with an
ISPF DATAID. This DATAID is used by the following commands to identify the
data object. The DATAID is at the execution of the LMINIT command
automatically defined by the system and stored into the variable specified in
the LIMINIT command.

Format:

dataid Here a name of maximal 8 characters must be specified. It is not necessary to enclose the
name at this point in apostrophes. This name must be used in all subsequent LM services
concerning this data set. In the following LM service statements must the DATAID entered
in a variable notation as shown below:

DATAID(“dataid”) or DATAID(&dataid)

Both notations can be applied.


dsn Name of the data set addressed with this LMINIT.

ddname DD name of the data set addressed with this LMINIT. When a DD name is specified, this
must have been previously allocated to a data set. This DD allocation can be present by a
previously executed TSO ALLOC command in the program, or come by a defined DD
statement from the outside in a BATCH JCL.

SHR Shared access to this data set is allowed. Other users can also access this data set.

EXCLU Exclusive access. No other users can simultaneously access the data set.

SHRW Works like SHR. However, members can be written into the PDS. This option only applies
for access to a PDS.

MOD Records can be added to an existing sequential data set.

Rules:
–The ENQ option can be used only if the data set is addressed using the
DATASET option. In addressing via DDNAME, the ENQ option conditions
determines the ALLOC or DD statement.
–If the LMINIT function addresses a set of concatenated data sets, then this is
only possible by using the DDNAME parameter. The concatenation of the
data sets must be previously performed using a TSO ALLOC statement or by a
DD statement in the JCL of a batch job.

LMINIT examples:

8.1.3 LMFREE – Free a data set


Function:
LMFREE frees a data set allocation established by a LMINIT command. LMINIT
and the associated LMFREE must occur in pairs with the same DATAID in the
program. All set ENQs by the LMINIT will be released.

Format:
ISPEXEC LMFREE DATAID(data-id)
data-id Here, the same variable must be specified which was used in
the corresponding LMINIT.

8.1.4LMOPEN – Open a data set for processing Function:


Depending on what data set processing is planned, a LMOPEN must be
performed before the data set processing can start. See Table 8.1: Grouping of
LM commands necessary for a particular type of data processing on page 134.

Format:

DATAID Here the same variable must be specified which was used in the corresponding
LMINIT.

OPTION This determines whether the data set should be opened for input or for output. INPUT
is the default value.

LRECL If this option is used, then LMOPEN stores the LRECL of the data set in the lrecl-var.

RECFM If this option is used, then LMOPEN stores the RECFM of the data set in the recfm-
var.

ORG If this option is used, then LMOPEN stores the organization form of the data set (PO
or PS) in the org-var.

Example:
Program 8.1:LMOPEN example
The SAY statement prints the following output:
LRECL=000007 96, RECFM=VB , ORG=PS

8.1.5 LMCLOSE – Close a data set


Function:
The data set associated with this DATAID is closed.

Format:
ISPEXEC LMCLOSE DATAID(data-id)
DATAID Here the same variable must be specified, which was
used in the LMINIT and LMOPEN. The possible setting
of ENQs performed by LMINIT will be freed.

8.1.6 LMMFIND – Localize a member


Function:
The LMMFIND function searches for a member in a PDS/PDSE or in a chain of
such data sets. LMMFIND can also return member statistics. If the object
addressed by LMINIT and LMOPEN is a concatenated data set, then LMMFIND
locates the first occurrence of the member found in the chain. The LMINIT and
LMOPEN services must have been executed before the command LMMFIND can
be executed.

Format:
MEMBER Enter here the name of the desired member.

LRECL This is the same parameter as used in the LMOPEN function. The difference, however, is
that when searching in a concatenated data set the characteristic values of the PDS will
be transferred in which the member was found.

RECFM Here mutatis mutandis applies the same to say as for LRECL. If YES is specified, then
some variables are set by ISPF containing values of the member statistics of the member
found. Here especially the ZLIB variable is of interest. When the LMOPEN refers to a list
of concatenated data sets, this variable contains the position number of the data set
within the chain of PDS in which the member was found. Since number, name and type
of the returned variables depend on the type of data set, I will refrain from a detailed
description. If you want to pursue the issue further, I recommend the manual ISPF
Services Guide.

Example:
The following program shows how to search members in a concatenated data
set.
Program 8.2: LMMFIND example
I ran the program. The result is shown here:

8.1.7 LMMREP – Replace a member


Function:
The LMMREP service replaced a member in a PDS. If the member does not exist,
it is added to the PDS. Before executing the command LMMREP, the LMINIT
service must have been performed with option ENQ (SHRW) or ENQ (EXCLU)
and the LMOPEN command with OPTION (OUTPUT). Additionally, a LMPUT
service must previously be used to produce data records in storage.

Format:

DATAID Specifies the data-id that has already been used by LMINIT and LMOPEN service.

MEMBER Specifies the name of the member to be written to the PDS.

STATS The STATS (YES) option specifies that the member statistics will be set or updated after
insertion of the member. The program must at least have set the values ZLCDATE for the
creation date and ZLMDATE for the modification date. For information about other
variables that can also be set, see the description of the service LMMREP in the
brochure ISPF Services Guide.

NOENQ This option causes the ISPF while deposing the execution of the command to set no ENQ
on the relevant PDS.

Advice:
If a particular member is not in the PDS available when running LMMREP, the
LMMREP command ends with a RC = 8, although everything was done correctly.
This must be observed when checking the return codes.
8.1.8 LMMADD – Add a member
Function:
This service works the same as the LMMREP service. The only difference is that
an existing member will not be replaced. This service should always be used if
you never want to overwrite already existing members. If the concerned
member is available in the PDS when running LMMADD, the LMMADD
command ends with a RC = 4 and the member is not written into the PDS.

8.1.9 LMGET – Read a data records


Function:
LMGET reads a record from the data set provided under the same DATAID by
LMINIT and LMOPEN. If a member should be read sequentially, the member
must previously be located using a LMMFIND.

Format:

All parameters must always be specified!


DATAID data-id refers to the same DATAID for which the LMINIT, the LMOPEN and possibly
the LMMFIND service had already been performed.

MODE Defines whether the data is to be moved, located or stored into an ISPF dialog variable.

DATALOC dataloc-var is the name of a REXX variable in which the read data record is stored when
mode INVAR was specified.

DATALEN datalen-var is the name of a REXX variable in which the length of the read data record
is saved.

MAXLENE max-length is an input variable that contains the maximum length of a record. You can
always specify the number 32760 here.
Example:
Read the member LANZT.LOGON.CLIST(ALIAS). This data set is defined with
RECFM=VB. I have deliberately avoided any error checking during
development of the program to make the example easier to read.

Program 8.3: LMGET – Read data records

Here are the results of program execution:

8.1.10 LMPUT – Output data records


Function:
LMPUT writes a data record into a data set or a member that is defined with
LMINIT and LMOPEN using the same DATAID. If the records are written to a
member, then a LMMADD or LMMREP must be performed with the same
DATAID for this member after all records are written by LMPUT.

Format:

DATAID Specifies the same data-id that is already used by LMINIT and LMOPEN
service.

MODE Mode INVAR must always be used in REXX programs.

DATALOC dataloc-var is the name of a REXX variable which contains the data to be
written.

DATALEN data-length must contain the length of the record to be written.

[NOBSCAN] This option specifies that the trailing blanks will not cut off when writing VB
records.

Example:
Program 8.4: LMPUT – Writing a member with setting the statistic
information
8.1.11 LMCOPY – Copy data
Function:
The LMCOPY service copies PDS members or entire sequential data sets.

Format:
FROMID Specifies the same data-id that is already used by LMINIT and LMOPEN service to
allocate the input data set.

TODATAID Specifies the same data-id that is already used by LMINIT and LMOPEN service to
allocate the output data set.

FROMMEM from-member-name is the name of the source member or a mask through which the
members to be copied are generically selected. If an asterisk (*) is specified, all members
are copied. If the source data set is a PDS, this parameter must be specified. If the source
data set is of type sequential, this parameter must not be specified.

TOMEM to-member-name is the member name of the member in the output data set. If the from-
member-name is specified and the to-member name not, the member is copied using
the from-member-name in the output data set. If the source data set is of type sequential
to-member-name, this must be specified. If the target data set is of type sequential the
to-member-name cannot be specified.

REPLACE Specifies that existing members are replaced. If this parameter is not specified when
copying multiple members, only those members that are not present in the output data
set will be copied. If members are not copied because they are already present, then the
RC=12 is set.

TRUNC Allows clipping of the input data to the LRECL of the output data set.

Program 8.5: LMCOPY example


8.1.12 LMMOVE – Move data
Function:
The LMMOVE service moves members of PDS or entire sequential data sets.
Since LMMOVE has the same functions and parameters as LMCOPY, I will
refrain from giving a complete description. The difference to LMCOPY is merely
that LMMOVE deletes the data source after copying.

8.1.13 LMMDEL – Delete members


Function:
The LMMDEL service deletes a member of a PDS. The following services must
be called first:
1.LMINIT with parameters ENQ(SHRW) or ENQ(EXCLU)
2.LMOPEN with the OPTION parameter (OUTPUT)

Format:

The parameters are the same as those described in the previous services. Since
this is a very simple function, I will refrain from giving a detailed example.

8.1.14 LMMREN – Rename members


Function:
The LMMREN service renames a member of a PDS. The following services must
be called first:
1.LMINIT with parameters ENQ(SHRW) or ENQ(EXCLU)
2.LMOPEN with the OPTION parameter (OUTPUT)

Format:

The parameters are the same as those described in the previous services. Since
this is a very simple function, I will refrain from giving a detailed example.
8.1.15 LMMSTATS – Display or change member statistics
Function:
The LMMSTATS service sets or clears the member statistics for a member in a
PDS. Not all statistic values must be set when calling the service. If some values
are not set, LMMSTATS tries to determine the remaining values (such as the
number of records in a member) to set it correctly.

Prior to the execution of this command, LMINIT must be performed.

Format:

DATAID Variable name of DATAID from the associated LMINIT.

MEMBER The name of the member, which statistics should be changed. There can be a generic
mask entered to set statistics for multiple members.

DELETE With this option, all statistics will be deleted.

VERSION Version number that is to be set. Here a number from 1 to 99 must be specified.

MODLEVEL Modification level that is to be set. Here a number from 1 to 99 must be specified.

CREATED Creation date of the members. A date in the form valid for the respective country must
be entered. This form is provided in REXX by calling the function DATE (“O”).

MODDATE Modification date of the members. The shape is the same as in CREATED.
MODTIME Time of the modification of the member in the form HH:MM:SS. This format is
provided by the function TIME () in REXX.

CURSIZE Number of records in the members. This parameter should never be specified. The
system determines and sets this value.

INITSIZE The same as in CURSIZE.

MODRECS Specifies the number of modified records. This value can only be set by the system.

USER The user ID that is inserted in the member statistics. This information may contain a
maximum of 7 characters. When the ISPF editor edits the member, the editor sets the
user ID automatically when the member is stored.

CREATED4 Creation date of the member in the form with four-digit year. A date in the form valid
for the respective country must be entered. Normally the form YYYY/MM/DD is used
in Europe. The text must be assembled to contain the correct form for the appropriate
country.

MODDATE4 The same as for CREATED4.

Program 8.6: LMMSTATS example

Prior to the creation of statistics, the existing values are deleted (lines 09 and
14).
On line 12, the statistics for the member login are created without any
indication of parameters. In this case, the system searches for the values itself.
The date and time values are taken from the date of execution of the command.
The number of records in the data set and the user ID will also be determined
and entered by the system.
The following two displays show the member lists after the execution of the
above program:
Display 1: Normal view

Display 2: The alternative view after shift right using the PF11 key

Tips:
When you use LMMREP or LMMADD to create a new member, then it is easiest
to execute these commands with the STATS option NO, the default value, and
then right after that execute a call to LMMSTATS with no parameters. Make sure
in this case that you run a LMCLOSE before LMMSTATS because LMMSTATS
may only be applied to a DATAID not opened. This procedure has the advantage
that the LMMSTATS command determines the statistics values based on
existing physics and the present time itself.

When you use LMMREP or LMMADD you must, however, determine the values
yourself and set the corresponding variables. When using STATS (YES) in
LMMREP or LMMADD you need to previously fill some values, otherwise
nothing is entered.

8.1.16LMCOMP – Compress a PDS


Function:
With LMCOMP, a PDS is compressed. A PDSE can and does not need be
compressed! If no compress exit is installed in the system, the program
LMCOMP uses IEBCOPY for the execution of COMPRESS.

Format:
ISPEXEC LMCOMP DATAID(data-id)

Before executing the command LMCOMP, a LMINIT command with the option
ENQ(EXCLU) must be executed.
8.1.17LMMLIST – Display a member list
Function:
If the LMMLIST service is executed with the LIST or the SAVE option, it will
generate a list of the first occurrence of a member in a concatenated data set. If
only one data set is specified in the TSO ALLOC statement that precedes the
LMINIT service, only the member names of this data set will be listed. When
LMMLIST is executed for first time in a program the content of
the MEMBER variable determines the touchdown point for the selection of
members returned. If the MEMBER variable contains a BLANK, then all member
names of the PDS will be returned.
Note:
LMMLIST returns for each call only the next name in ascending alphabetical
sort order in the PDS directory. Therefore, you must call LMMLIST in a loop if
you want to capture multiple members of a PDS. Before LMMLIST is used, the
LMINIT and LMOPEN service have to be run.

Format:

DATAID Variable name of DATAID from the associated LMINIT.

OPTION(LIST) The first call of LMMLIST creates an internal member list. If the member-var is
initialized with blanks, then LMMLIST returns on each call the next member in
the list beginning with the first member in the PDS. In this case, you successively
get all members contained in the PDS.

OPTION(FREE) FREE releases the occupied shared memory. Whenever a loop for the
determination of member names is completed, perform a single call to LMMLIST
with the FREE option to free the occupied memory.

OPTION(SAVE) With the SAVE option, the list of members is outputted to a data set. The GROUP
parameter defines the name of this data set.

MEMBER Before the first call to LMMLIST, initially specify in member-var the starting
position for the search for the members in the member list. The member-var
contains after the call either the name of the directly addressed member or the
name of the member that is found next.

STATS When YES is specified then, LMMLIST stores for each member the member
statistics information in the corresponding variables. A detailed description of the
member statistics variable can be found in section 8.1.15 LMMSTATS – Display
or change member statistics on page 147.

GROUP Here, an up to eight characters long name can be specified from which a DSN of a
data set is formed in which then, when specifying OPTION(SAVE), the member
list is written. When the GROUP parameter is omitted and OPTION(SAVE) is
specified, then the output of the member names list is written in the LIST data set
of ISPF. The DSN will be formed as follows: <prefix>.<group>.members.

PATTERN You can specify a mask here, which determines the actually returned members.
The description of how the mask must be set up, can be taken from ISPF
Services Guide.

Program 8.7: LMMLIST example


I executed the above program and got the following output:

8.1.18 LMMDISP – Display and edit a member list


Function:
LMMDISP displays member names in an ISPF panel. In front of each member,
you can enter a command, which can be used for further processing in the
program. The members may also originate from a string of concatenated data
sets. LMMDISP has a very large scope of functions. I will only explain the
DISPLAY option here. If you are interested in other options, please take a look
to the brochure ISPF Dialog Services.

Format:

OPTION This option starts the display functionality.

MEMBER Here, a member selection mask can be specified.


STATS STATS(YES) specifies that LMMDISP returns the statistic values for each selected
member.

PANEL Determines an optional (own) panel for display.

CURSOR CURSOR defines at which position the cursor should be displayed for the panel.

ZCMD The cursor is positioned on the command line of the panel.

ZLLCMD The cursor is positioned at the beginning of the first line of data.

ZLUDATA The cursor is positioned in the second input field of the first row of data.

TOP This is a very complicated parameter. Here the original text from the manual ISPF
Services Guide:

The name that designates which member is to appear first on the display. If the member
cannot be found and the list is sorted by name, the member immediately preceding the
requested one in the member list is scrolled to the top. If the list is not sorted by name and
the member is not found, the list is scrolled to the top.

COMMANDS S means: Only S can be entered as a selection code.

ANY means: Any selection codes can be entered.

FIELD 1 Only single-character selection codes can be entered.

9 Eight-character selection codes can be entered. Nine-character commands are not


possible in ISPF.
Program 8.8: LMMDISP exemple

I ran the program and entered a few commands. Expenditures incurred there
can be found behind the display of the panel.

Screen 8.1: LMMDISP panel display

I entered line commands in the panel display and then pressed the enter key
and three times. Successively the following lines appeared:
Note:
The column Lib in the panel shows the data sets position in the chain in which
the member is first found. The member may still occur, but often in the
underlying data sets of the chain.

8.1.19 LMDINIT – Initialize the LMDDISP service


Function:
The LMDINIT service generates a DATAID for a subsequent LMDDISP or
LMDLIST service.

Format:

LEVEL The dsname-level defines a mask for selecting the DSNs. The rules for the design of the
mask are the same as in the ISPF menu 3.4.

VOLUME Here a VOLSER (a disk name) can be specified. If a VOLSER is specified, the data sets
are only searched in the VTOC of this disk.

8.1.20 LMDDISP – Data set list service


Function:
The LMDDISP service displays a panel, which is similar to that in ISPF menu 3.4.
The displayed DSNs are determined by the mask which is specified when calling
the command LMDINIT and must have been called before calling LMDDISP.

Format:

LISTID Here the LISTID from an earlier performed LMDINIT must be specified.

VIEW Here you can specify what additional information should appear when displaying the
panel.
CONFIRM YES means: The confirm delete panel appears always before the DELETE of a data set
is performed.
NO means: The confirm delete panel appears only when a data set should be deleted,
which expiration date has still not expired.

PANEL Here you can specify a panel that you want to use instead of the default panel as used in
ISPF menu 3.4.

Program 8.9: LMDDISP – Display data sets in a panel

When the program executes, the following panel will be displayed:

Due to using the option VIEW(TOTAL) in the LMDDISP call, all data set
attributes are displayed.

8.1.21 LMDLIST – List of data sets


Function:
This service works almost exactly like the LMDDISP service. The difference is
that each time you run the LMDLIST function selected by the mask, DSNs are
returned one at a time. The LMDINIT service must be executed prior to calling
LMDLIST service.
For return of the internally stored DSNs, you have two options:
–When using the LIST option, one name per call will be returned. Therefore, in
this way the LMDLIST command must be called so long in a loop until the RC=8
occurs.
–When using the SAVE option, the DSNs are written to a data set. Of course, in
this case only one call is required.

Format:

LISTID Specifying the dslist-id from the LMDINIT statement.

OPTION The description of these options is very complicated and extensive. Please see this in
the brochure ISPF Services Guide. A simple example of using LMDLIST is shown
below.

DATASET Before the first call to LMDLIST you must initialize dataset-var with a DSN mask. At
each return from LMDLIST, this variable contains the name of the next DSN found in
the list.

STATS If you set STATS(YES) then for each returned DSN, the statistic information of the data
set is returned in special variables. Please see the descriptions of the variables in the
brochure ISPF Services Guide. See also section 8.1.15 LMMSTATS – Display or
change member statistics on page 147 and Table 8.3: Variables returned by the
LMDLIST service on page 161.

GROUP If you entered OPTION(SAVE), then you must specify a 8-character value. The data set
list is then written into a data set. Its name is built up as follows:
<prefix>.<group>.DATASET.
Program 8.10: LMDLIST example

The above program prints out the follwing list:

8.1.22 LMDFREE – Free a LISTID


Function:
Release a resource that was initialized with LMDINIT.

Format:
ISPEXEC LMDFREE LISTID(list-id)

8.1.23 MEMLIST – member list dialog service


The MEMLIST service displays a panel that displays the members of one or
more PDS. In front of each member commands can be entered like in the panel
of an ISPF menu 3.4/M screen. The LMINIT service must be executed before
calling the MEMLIST service.

Format:
DATAID Specify the DATAID from the associated LMINIT service call.

MEMBER A mask for the selection of member names can be specified here. If there is no mask
specified, all members of the PDS appear in the displayed panel.

CONFIRM If YES is active, the confirm delete panel appears after entering a delete command in
front of a member and before the deletion is performed. Otherwise, the deletion will be
executed immediately.

PANEL You can specify the name of a panel here that you want to use instead of the default panel
for the display of the member list.

FIELD Defines the length of the line command fields. If 1 is specified, only single digit line
commands such as B, E, V, etc. can be entered. See also the command LMMDISP service
on page 153.

In the following example, by using ALLOC and LMINIT, an access to a chain of


two PDS will be defined.

Program 8.11: Display a MEMLIST consisting of two data sets

When calling this program, the following panel is displayed:

Screen 8.2: MEMLIST display


Note:
The column Lib in the panel shows the data set position in the chain in which
the member is first found. However, the member may still occur very often in
the data sets further down in the chain.

8.2 DATA SET QUERY SERVICES


In programming of ISPF applications, you very often need information about
data sets. Unfortunately, there is no service that will deliver all data set
characteristics in one call. If you need ALL information about a data set, you
have to call even three services. See following table:
Table 8.2: Data set query services

Function System Description

LMDLIST ISPF This service is the only data set list service that returns the HSM migration
status.
DSINFO ISPF This service provides a very comprehensive overview of the characteristics of
a data set.

LISTDSI REXX This service almost provides the same information as DSINFO, but some of
the information is to use something better.

8.2.1 LMDLIST – Data set list service


This service is described already earlier in section 8.1.21 LMDLIST – List of data
sets on page 157. The following table lists the names and contents of the
variables that are provided when invoking the service with the STATS(YES)
option.
Table 8.3: Variables returned by the LMDLIST service

Variable Description

ZDLVOL Volume serial number

ZDLDEV Device type

ZDLDSORG Data set organization

ZDLRECFM Record format

ZDLLRECL Logical record length

ZDLBLKSZ Block size

ZDLSIZE Data set size in tracks

ZDLUSED Used space in % (PDSE only).

ZDLEXT Number of blocks of the data set.

ZDLCDATE Creation date


ZDLEDATE Expiration date

ZDLRDATE Date last referenced

ZDLMIGR HSM migration status (YES or NO)

ZDLDSNTP Data set type. (‘PDS’, ‘LIBRARY’, or ‘ ’

ZDLSPACU Units of the size specified (CYLINDERS, TRACKS, BLOCKS)

ZDLMVOL Specifies whether this data set spans over multiple volumes. (Y or N)

Remark:
The LMDLIST service is the only service that returns the information on the
migration status of a data set. Therefore, I marked the variable ZDLMIGR.

8.2.2DSINFO – ISPF service which provides data set information


This service mainly provides the same information as the REXX function
LISTDSI.

Format:

DATASET DSNAME is the name of the dataset for the information be returned.

VOLUME VOLSER is the volume serial number (disk name) on which the data set is located.
Specify this parameter only when the data set is not cataloged. The following table shows
the variables that this service returns.

Table 8.4: DSINFO variables content

Variable Description

ZDSVOL VOLSER of the first or only volume


ZDS#VOLS Number of volumes over which the data set extends

ZDSDEVT Device type

ZDSORG DSORG (PS or PO)

ZDSRF Record format (RECFM)

ZDSLREC Record length (LRECL)

ZDSBLK Block size (BLKSIZE)

ZDSSPC Primary space units

ZDS1EX Primary space allocated

ZDS2SPC Secondary space unit

ZDS2EX Secondary space allocated

ZDSDSNT Data set name type

ZDSSEQ Compressible YES/NO

ZDSCDATE Creation date

ZDSXDATE Expiration date

ZDSRDATE Last referenced ate

ZDSTOTA Units of allocated space

ZDSTOTU Used space units

ZDSEXTA Allocated extents


ZDSEXTU Used extents

ZDSDIRA Allocated directory blocks (PDS only)

ZDSDIRU Used directory blocks (PDS only)

DZSDIR Always NOLIMIT for PDSE

ZDS#MEM Number of members

DZSPAGU Number of used pages of a PDSE

ZDSPERU % used space of a PDSE

ZDSMC SMS – Management class

ZDSSC SMS – Storage class

ZDSDC SMS – Data class

ZDSCB1 Format 1 data control block

ZDSVTAB String of volsers of all used disks


Example 1: PDS not SMS managed
Example 2: PDSE SMS managed

8.2.3 LISTDSI – REXX function to list data set information


Function:
LISTDSI is a TSO/REXX function. Depending on the call type, it provides
different information about data sets.

Format:
Data set name or DD name. If a DD name is specified, FILE must also be
specified. You must use the DD name notation when the REXX program runs in
a batch job and a DD statement specifies the data set.
location This option is normally not used.

DIRECTORY The option DIRECTORY specifies whether the requested directory information of a
PDS/PDSE is stored in the corresponding variables. When NODIRECTORY or
nothing is specified, then this information will not be returned. DIRECTORY should
only specified if the corresponding information is really needed because
determination of the directory information takes a long time.

RECALL When entering RECALL, then a data set that is HSM migrated is loaded back to the
normal disk environment. NORECALL is the default value.

SMSINFO When you type the SMSINFO option, then the SMS information about this data set
will be determined and set into the appropriate variables. Because this option causes
much more work by the system, you should use this option only when you need the
information. NOSMSINFO is the default value.

Variables set by LISTDSI:


The following table shows the variables that are set by LISTDSI. This is an
excerpt from the IBM brochure TSO/E REXX Reference. For VSAM data sets,
only the variables SYSVOLUME, SYSUNIT and SYSDSORG are set. All other
variables contains a question mark (?).
Table 8.5: LISTDSI – Variables and their contents

Variable name Description

SYSDSNAME Data set name

SYSVOLUME Volume serial ID

SYSUNIT Generic device type on which volume resides, for e example 3390.

SYSDSORG Data set organization:

PSPhysical sequential
PSUPhysical sequential unmovable

DADirect organization

DAUDirect organization unmovable

ISIndexed sequential

ISUIndexed sequential unmovable

OPPartitioned organization

POUPartitioned organization unmovable

VSVSAM

???Unknown

SYSLRECL Logical record length

SYSBLKSIZE Block size

SYSKEYLEN Key length

SYSALLOC Allocation, in space units

SYSUSED Allocation used, in space units. For a partitioned data set extended (PDSE),
‘N/A’ will be returned see the description of the variable SYSUSEDPAGES for
used space of a PDSE.

SYSUSEDPAGES The used space of a partitioned data set extended (PDSE) in 4K pages.

SYSPRIMARY Primary allocation in space units

SYSSECONDS Secondary allocation in space units


SYSREASON LISTDSI reason code

SYSMSGLVL1 First-level message if an error occurred

SYSMSGLVL2 Second-level message if an error occurred

SYSRECFM Record format one to six character combination of the following:

URecords of undefined length

FRecords of fixed length

VRecords of variable length

BRecords blocked

SRecords written as standard or spanned variable-length blocks

ARecords contain ASCII control characters

MRecords contain machine code control characters

??????Unknown

SYSUNITS Space units:

CYLINDERSpace units in cylinders

TRACKSpace units in tracks

BLOCKSpace units in blocks ????????Space units are unknown

SYSEXTENTS Number of extents allocated

SYSCREATE Creation date Year/day format, for example: 1990/102


SYSREFDATE Last referenced date in Year/day format, for example: 1990/107 (Specifying
DIRECTORY causes the date to be updated

SYSEXDATE Expiration date in Year/day format, for example: 1990/365

SYSPASSWORD Password indication:

NONENo password protection

READPassword required to read

WRITEPassword required to write

SYSRACFA RACF indication:

NONENo RACF protection

GENERICGeneric profile covers this data set

DISCRETEDiscrete profile covers this data set

SYSUPDATED Change indicator:

YESData set has been updated

NOData set has not been updated

SYSTRKSCYL Tracks per cylinder for the unit identified in the SYSUNIT variable

SYSBLKSTRK Blocks (whose size is given in variable SYSBLKSIZE) per track for the unit
identified in the SYSUNIT variable. For a PDSE, the value “N/A” is returned
because a block of size SYSBLKSIZE can ‘span’ a track in a PDSE. The value
contained in SYSUSEDPAGES is a more meaningful measurement of space
usage for a PDSE.

SYSRACFA RACF indication:


NONENo RACF protection

GENERICGeneric profile covers this data set

DISCRETEDiscrete profile covers this data set

SYSUPDATED Change indicator:

YESData set has been updated

NOData set has not been updated

SYSTRKSCYL Tracks per cylinder for the unit identified in the SYSUNIT variable

SYSBLKSTRK Blocks (whose size is given in variable SYSBLKSIZE) per track for the unit
identified in the SYSUNIT variable. For a PDSE, the value “N/A” is returned
because a block of size SYSBLKSIZE can ‘span’ a track in a PDSE. The value
contained in SYSUSEDPAGES is a more meaningful measurement of space
usage for a PDSE.

SYSADIRBLK For a partitioned data set (PDS) the number of directory blocks allocated will be
returned. For a partitioned data set extended (PDSE), “NO_LIM” will be
returned because there is no static allocation for its directory. A value is
returned only if DIRECTORY is specified on the LISTDSI statement.

SYSUDIRBLK For a partitioned data set (PDS) the number of directory blocks used will be
returned. For a partitioned data set extended (PDSE), "N/A" will be returned
because it is not a static value. A value is returned only if DIRECTORY is
specified on the LISTDSI statement.

SYSMEMBERS Number of members – returned only for partitioned data sets when
DIRECTORY is specified

SYSDSSMS Contains information about the type of a data set, provided by DFSMS/MVS. If
the SMS DSNTYPE information could not be retrieved, the SYSDSSMS variable
contains:

SEQfor a sequential data set


PDSfor a partitioned data set

PDSEfor a partitioned data set extended.

If the data set is a PDSE and the SMS DSNTYPE information could be retrieved,
the SYSDSSMS variable contains:

LIBRARYfor an empty PDSE

PROGRAM_LIBRARYfor a partitioned data set extended program library

DATA_LIBRARYfor a partitioned data set extended data library.

SYSDATACLASS The SMS data class name – returned only if SMSINFO is specified on the
LISTDSI statement and the data set is managed by SMS.

SYSSTORCLASS The SMS storage class name – returned only if SMSINFO is specified on the
LISTDSI statement and the data set is managed by SMS.

SYSMGMTCLASS The SMS management class name – returned only if SMSINFO is specified on
the LISTDSI statement and the data set is managed by SMS.

If errors are detected in the LISTDSI call or when specific information is to be


returned, the variable SYSREASON contains a reason code as a numerical value.
The following table contains the description of the individual reason codes:
Table 8.6: LISTDSI – Description of reason codes

Code Description

1 error parsing LISTDSI statement.

2 dynamic allocation (SVC 99) error.

3 data set type prohibits its being processed.

4 error extracting unit name.


5 data set is not cataloged.

6 error obtaining data set name from VTOC.

7 error finding device type.

8 data set is not on DASD.

9 HSM migrated data set & NORECALL was specified.

11 Directory info was asked for but user ID has insufficient, access authority for this data set.

12 VSAM data set.

13 data set OPEN failed.

14 device type not found in UCB tables.

17 ABEND occurred.

18 partial data set information obtained.

19 multi-volume data set.

20 device type not found in EDT table.

21 catalog error prevented LOCATE completion.

22 volume not mounted.

23 I/O error during OBTAIN macro.

42 OBTAIN could not find data set in VTOC.

25 data set migrated off of DASD.


26 data set is on a mass storage device.

27 no volume serial number is allocated for this data set.

28 DD name is invalid, must be 1 to 8 characters.

29 both data set name and filename were omitted on call.

30 Data set is not SMS-managed.

31 ISITMGD macro returned with bad return code and reason code. Return code and reason code
can be found in message IKJ58431I, which is returned in variable &SYSMSGLVL2.

32 Unable to retrieve SMS information. DFSMS/MVS has incorrect level.

33 Unable to retrieve SMS information. DFSMS/MVS is not active.

34 Unable to retrieve SMS information. OPEN error.

35 Unexpected error from DFSMS/MVS internal service IGWFAM.

36 Unexpected error from the SMS service module.

37 Unexpected error from DFSMS service IGGCSI00

Tips:
If you want to use the LISTDSI function in one of your programs, then you find
in the program SSC of the SMART ISPF utilities an internal subroutine named
DSLSTRC that contains the appropriate description for each reason code. You
can copy this subroutine to your program.

8.2.4QBASELIB – Query DSN information


Function:
Returns the DSNs of an allocated DD name. Format:

Format:
ISPEXEC QBASELIB dd-name ID(id-var)
dd-name DD name.

ID The DSNs are stored by the function in this string.

Example 1: Use of QBASELIB in an online allocation:

Program 8.12: Test of QBASELIB in an online call

The printed output:

Example 2: Use of QBASELIB in a batch job:


I have created and executed the following batch job. Because QBASELIB is an
ISPF service, the batch job has to build here in such a way, that ISPF commands
can be executed within the REXX program. We have already dealt with the issue
in ISPF batch jobs in detail.
JCL 8.5: QBASELIB function used in a batch job
In lines 32 through 34 are respectively the ISPF started while the REXX
program QBASELIB was called with a DD name as a parameter.
During execution of the job, SYSTSPRT puts out the following lists:
8.2.5 QLIBDEF – Query LIBDEF Information Function:
QLIBDEF returns the DSNs of an active LIBDEF chain. If there is no LIBDEF
chain for the entered ISPF library available, the return code is set to 4.

Format:

dd- DD Name of the ISPF library. The value may be ISPPLIB, ISPMLIB, ISPSLIB, ISPTLIB,
name ISPLLIB, ISPILIB, ISPTABL and ISPFILE.

TYPE type-var is a variable where the QLIBDEF service returns the definition type from the
ID original LIBDEF statement. The returned value can be DATASET, EXCLDATA, LIBRARY
or EXCLLIBR.

ID id-var is a variable into which the QLIBDEF service stores the DSNs of active LIBDEF chain.

Example:
First executes the program a LIBDEF command for ISPSLIB (skeletons). Then
the existing LIBDEF chain for ISPSLIB is queried and displayed using QLIBDEF.
Then the function QBASELIB is executed to print the ISPSLIB chain as well.
Program 8.13: QLIBDEF example
The output of the program (side by side):

8.2.6 QUERYENQ – ENQs determination


Function:
With QUERYENQ can you check whether any users are holding a particular
resource.

Format:
TABLE A freely chosen name for the ISPF table into which this service stores its information
about the ENQs found. This table is returned to program in open state and it must not
exist before calling QUERYENQ. The program must delete the table at the end of the
program with TBEND.

QNAME The user must define the type prior to the call of the QUERYENQ in this variable. Query
types can be SYSDSN, SPFEDIT, SPFUSER etc. Normally, an asterisk (*) is assigned. This
means that all query types are queried.

RNAME Before calling QUERYENQ this variable must contain the name of the queried resource.
This can also be a generic mask ending with an asterisk.

REQ The description for this value is very complex. I refrain from taking this opportunity to
give a comprehensive explanation and always recommend to keep the characters %* for
use. Look at the following example.

WAIT If you specify this option, only the currently pending ENQ contentions will be issued. The
information in rname and qname has no significance in this case.

LIMIT LIMIT is the number of rows that the function maximally returns. The default value is
5000. The specification of zero (0) cancels the limit.

SAVE If you specify an up to eight digits long name of a DSN qualifier here, then the
QUERYENQ service writes the results to a data set with the following name:
prefix.userid.listid.ENQLIST.

XSYS Indicates that the XSYS=YES parameter should be used on the GQSCAN macro call. This
option causes that all available LPARs are searched for the resource, which may mean a
lot of effort. If you are interested in this option, please look at the description of the
GQSCAN macro.

Functioning of the QUERYENQ function


The QUERYENQ function generates an ISPF table which name is specified by
the TABLE parameter. After a successful call to QUERYENQ rows in the table
containing information on the ENQs are found. The following table is an excerpt
from the brochure ISPF Services Guide. It contains the column names that
appear in the returned ISPF table with their descriptions:
Table 8.7: Variables description of the QUERYENQ ISPF table

Name Size Descriptione

ZENJOB 8 Job or address space name holding or requesting the ENQ

ZENQNAME 8 Qname portion of the ENQ

ZENRNAME 255 Rname portion of the ENQ

ZENDISP 5 SHARE or EXCLU

ZENHOLD 4 OWN or WAIT

ZENSCOPE 7 SYSTEM or SYSTEMS

ZENSTEP 7 STEP or blank

ZENGLOBL 6 GLOBAL or blank

ZENSYST 8 System name

ZENRESV 7 RESERVE or blank

Return codes of QUERYENQ:


The descriptions of the return codes that can occur after a call to QUERYENQ
have also been taken from the above brochure:
Table 8.8: QUERYENQ return codes

RC Description

0 Table returned or data set written, but XSYS parameter was not specified and the system is
running in STAR mode. The data returned may not reflect all ENQs on all systems.
2 Table returned or data set written.

4 Table returned but truncated due to limit.

8 No ENQs satisfy the request.

10 No ENQs satisfy the request, but XSYS parameter was not specified and the system is running in
STAR mode. The data returned may not reflect all ENQs on all systems.

12 Table creation error, parameter or other termination error. See messages for more detail. This
includes services not available due to configuration table restrictions.

14 The SAVE data set is in use by another user.

20 Severe error, including TBADD error or data set creation errors.

Note:
Please note that even if a RC>0 appears, quite useful results can be returned.
When requesting the RC, you must always consider possible situations.

Example:
The following program investigates whether a specific data set has any ENQs.
Program 8.14: QUERYENQ example
The program produced the following output:

As you can see, only the gray shaded user is currently using the data set.

9 Messages – Definition, setting, output


Error handling and issuing appropriate messages to the operator play an
important role in the programming online applications. The ISPF provides for
the fulfillment of this task very good tools. It provides a very good facility for
the feedback of errors that occur during the execution of functions. On the other
hand, you can very easily use the message output facility of ISPF to inform the
user about everything that happens.
The following functions of the ISPF can print out messages:
– From a REXX program using the ISPF command SETMSG.
– From panel by specifying a message ID in plausibility test instructions.
– From the ISPF service commands DISPLAY and TBDISPL.
– Into the ISPF LOG data sets through the ISPF LOG command.

9.1 ERROR HANDLING IN ISPF


Having already discussed the issue of all kinds of reports in the previous
chapters, I want to familiarize you with the techniques with which you see
errors when running ISPF commands and how you can output error messages.
The ISPF provides very sophisticated procedures for reporting errors that
occur during the execution of ISPF functions. However, there is a small catch:
Note:
You have to explicitly say at the beginning of each REXX procedure that ISPF
should report the errors back to the program after an error occurs. However,
this also has a disadvantage: If you forget to check the RC behind any ISPF
command, then errors having occurred during its execution, will not inform you
about these errors. The program works just wrong. Moreover, you do not know
why. For this reason, you must place a query for errors behind every ISPF
command in which an error could happen. In addition, you should never forget
to insert the command CONTROL ERRORS RETURN at the beginning of each
program that uses ISPF services.
When an error occurs?:
You should query the RC after each call to an ISPF function. Depending on the
function an RC <> 0 may be a bug or not. For example, when the LMGET function
reads a sequential data set or the records of a member a RC = 8 returns when
the end of data set is reached. In this case of course a RC > 0 is not an error. For
other functions, however, such as the LMINIT function, a RC <> 0 always
indicates an error.

Returning error messages


The ISPF command CONTROL is used to control the behavior of ISPF errors
during execution of an ISPF function. The CONTROL command is used for a
variety of purposes. I would like to only explain the specific function to return
the error messages at this point. This statement looks like this:
"ISPEXEC CONTROL ERRORS RETURN"

Once you have executed this command, from now on the errors occurring
during the execution of ISPF functions (and only these) back to the program
will be reported and the procedure will not be aborted.

The ISPF error messages are reported as follows:


Each ISPF function automatically generates error information when an error
occurs (and only then). This information is stored in the ISPF system in two
variables. These are the variables:
ZERRSM Short error message text, 24 characters.
ZERRLM Long error message text, 512 characters.

If an error occurs, these variables are written in the function pool. They are
usually only present when an error with an RC > 8 occurred during the
execution of an ISPF function. The two shaded characters in variable names are
very important: S Stands for SHORT. That is, in ZERRSM a short error message
with 24 characters will be returned. L stands for LONG. In ZERRLM, extensive
error messages with 512 characters will be returned. These variables can be
queried in a program and used appropriately for own message output.
Tip:
The variables are always returned in the above-mentioned length. Before using
these two variables, you should remove the superfluous BLANKS using the
REXX STRIP function.

Output of error messages


The own and the ISPF error messages can be displayed in several ways:
– Using the REXX SAY statement
– Using the ISPF function SETMSG

Method 1: Display error messages with the SAY statement


The method with SAY statements has the disadvantage on an online panel that
the currently displayed ISPF panel is completely removed from the screen and
then the message is written from top to bottom. As a result, you can often not
see which situation caused the error. In addition, the disappearance of the ISPF
panels is annoying. An advantage of this method is that the error message also
issues when the program runs in a batch job. Moreover, there is no restriction
for the length of the message.
Method 2: Output error messages with SETMSG
With SETMSG, you can output error messages and other information so that
they will appear in the display of the next panel. This has the distinct advantage
that the message will still appear when the creating program (e.g. because of
error occurred) was long over.

Comparison of both methods


If we look at the pros and cons of both methods, we soon come to the conclusion
that when working online in ISPF, also called in foreground, we should always
use the SETMSG method. However, since the SETMSG method cannot be used
in batch jobs, in this case you must use the SAY method.. In this situation, it is
very useful to be able to determine whether an ISPF program runs online in the
foreground or in the background as batch job. A very useful REXX function gives
us the information in which environment a REXX/ISPF program runs:

if sysvar("SYSENV") = "FORE" then fore = 1; else fore = 0

If you use this function, you always know in which environment a program runs
and then you can use the correct method for outputting your error messages.
See the following short program:
Program 9.1: TEST2 – Output of messages when a program runs online or in
batch

9.1.3 SETMSG – Set next message :


Function:
When a program is running online in ISPF, generally all messages can be
displayed with the following command.

Format:
SETMSG MSG(msg-id) [COND]
MSG Here the message ID of a programmer-defined message must be specified. There are also pre-
defined message IDs, which can be used for the issuance of own messages. See the next
chapter.

COND This parameter indicates that this message is only issued when an earlier SETMSG message
is not waiting for output.

9.1.4 Definition of ISPF messages


The message members are stored in the ISPF library ISPMLIB .

The definition of ISPF messages is somewhat complicated. Messages are


defined in message members, which are used for the output of the messages.
This is related; on the one hand, the messages should easily be found by the
names of their ID, and on the other hand, not every message should form a
member. This results in the need to combine multiple messages in one member.
To give you an idea about the structure of message members, I have inserted a
member that contains the messages beginning with ISRZ00 here.
Program 9.2: Messages definition member ISRZ00

As you can see, variables can be used in the definitions of the message line.
These are the names that begin with an ampersand (&). These variables are
replaced through their actual content before outputting the message. In REXX
programs, these variables are naturally without specifying & defined.
9.1.5 Naming convention of the ISPF message IDs
When printing a message, the name of the message ID is searched in the
members of the data sets of the ISPMLIB chain. This raises the question: What
is the name of the member in which a message ID is defined?

Rules:
The name of the member is found by cutting the name of the message ID after
the second numeric characters. Examples are shown in the following table:

Rules for building of message members


Message ID Member names

G015 G01

ISPE241 ISPE24

XYZ123A XYZ12

Thus all message IDs always start with the name of the member in which they
are defined. In addition, the message ID and the associated member name must
contain at least two numeric characters.

Searching of message members:


When the following message display command occurs in a program:

"ISPEXEC SETMSG MSG(XYZ123A)"

Then the member XYZ12 is searched in the allocation chain of the ISPF library
ISPMLIB and the message XYZ123A is displayed.

9.1.6 Definition of messages


The chapter for the definition of messages fills in the brochure ISPF Dialog
Developer's Guide and Reference 10 pages. Since I am not able to
demonstrate all the information contained in these pages here, I would like to
show an example of the message definition. The message member SSC01
contains the following definition:
This entry defines that the following happens when the error occurs:
Short message text None

Long message text As an Expiration Date only PERM, NONE, blank or a date in the form
YYYY/MM/DD can be entered.

Alarm Yes

This message appears when in the panel SSCPP01 in the field Exp.Date a wrong
value is entered. To display the message, the following command is used:

"ISPEXEC SETMSG MSG(SSC013B)"

If a wrong value is entered in Exp.Date, the following message appears on the


screen:

Format of the message definition:


The definition of a message in a message member is composed of two or more
lines.

Coding 9.1: Format of message definition


Note:
As you see, you can use a plethora of options here, but do not have to! I have
grayed the mandatory parts. If I define a message, I always let the short message
text away. This has the advantage that the long message text is displayed
immediately without pressing the PF1 key before. If you have defined the short
message also, then, when issuing the message, only the short message is
displayed initially at top right of the screen, the long message only after
pressing the PF1 key.
You will see in the following design, the basic structure of a message member.
The name of the member is TT00. There are four messages defined in the
member:

Coding 9.2: Member TT00 – Example for the definition of a message member

I have outputted all the messages once each with the command ISPEXEC
SETMSG MSG (TT00x). See the results below:

Program 9.3: MSGTEST – Test of messages outputting


After the short message has appeared, I pressed the PF1 key. Then the Long
Message was displayed at the bottom of the screen.
Tip:
You can move the framed message box with the cursor within the total available
display. This is especially helpful if the message field obscures such parts of the
surrounding panels that you want to see together with the message text.
Moving goes like this: You position the cursor on a point of the frame of the
message field and then press ENTER. Then the text Window move
pending appears in the upper right corner of the screen. Now move the cursor
to any position on the screen and press ENTER, the entire message frame moves
to the cursor position. You can use this method to make invisible places of the
surrounding screen again visible.

9.1.7 The standard message member ISRZ00


Now that you have received an overview of the technology of the message
output in ISPF, I will explain how you can easily put out own messages from a
REXX program, without having to define an own message member in the
ISPMLIB library. In order to offer this possibility, a standard message member
is included in ISPF. This member is contained in the ISPF standard message
library ISP.SISPMENU and its name is ISRZ00. If we remember the rules for the
name structure of messages, messages will be stored in the member ISRZ00
that begin with ISRZ00. Let us have a look into this member:
Program 9.4: Standard message member ISRZ00
You can use the message IDs contained in this member to print out any message
texts as you like. As you can see, four message IDs are defined there. In all these
definitions, the message issued texts are specified as a variable. If these
variables are filled in the calling program with texts accordingly, then the texts
are displayed on the screen when the message is outputted. The use of variables
in REXX programs is naturally done without the ampersand.
Remark:
When the variable of the short message is not defined or contains a null string,
only the long message will be outputted immediately.

Description of the individual message IDs:

ISRZ000
Names of variables: ZEDSMSG and ZEDLMSG.

This Message ID is used when you want to spend only a hint. The issue of the
long message appears in white.

ISRZ001
Names of variables: ZEDSMSG and ZEDLMSG.

This Message ID is most commonly used to issue error messages. There is an


alarm output and the message will appear in yellow.

ISRZ002
Names of the variables:

ZERRSM, ZERRLM, ZERRALRM, ZERRHM, ZERRTP, ZERRWN

Allows you to output the error message data directly, which are returned from
ISPF because the ISPF error messages will be stored exactly in the variables
which are used in this error message definition. The message appears in yellow.
Depending on the content of the variable ZERRALRM, a beep will be outputted.
The name of a HELP panel can be stored in the variable ZERRHM. This HELP
panel is called when the PF1 key is pressed after the message appears.

ISRZ003
Names of the variables:

ZERRSM, ZERRLM, ZERRALRM, ZERRHM, ZERRTP, ZERRWN

Here you have the same options as with the ID ISRZ002. Additionally, you can
fill the variables ZERRTP and ZERRWN. I do not want to explain these two
variables, I have nowhere in the literature found a useful note concerning them.
If you are interested, I suggest you perform some tests with these variables. I
have never needed these variables previously.

Examples from practice programs for using the message member ISRZ001:
Example 1: Excerpt from a REXX program.

Lines Explanation

14: This query is determined that the message is only outputted if the REXX program runs in
FOREGROUND online under ISPF.

15+16 The text of the message is stored in the variable ZERRLM.

17+18 If ZERRLM contains an ISPF message, then the ISPF error message will be appended to the
existing message text.

19 The message will be outputted and is displayed on the next screen.

Example 2: Excerpt from an edit macro.


Lines Explanation

70 Because the ISPF EDIT command stores its messages when an error occurs in the variables
ZERRSM and ZERRLM, then the message ID ISRZ002 can be used here.

78 Here, the variables ZEDSMSG and ZEDLMSG are filled with private texts. Therefore,
ISRZ001 will be used here.

Remark:
The program from which the above excerpt is derived, is an edit macro.
Therefore, the ISPF commands must be called using the form address
"ISPEXEC". You cannot use the shape by prefixing the command with ISPEXEC
here because the ISPF edit processor would not accept this. The shape with
ISPEXEC before an ISPF command only understands the TSO command
processor!

10 Panels – create and use


In this chapter, I will explain how you can easily define and use ISPF panels. To
control applications panels are suited much better than using the simple
queries SAY and PULL. Therefore, if you want to create elegant applications in
ISPF you should already dominate the creation and use of ISPF panels. The ISPF
provides very simple methods and tools to create screens and to use these
masks in programs. In ISPF, screens are referred consistently to as panels.
There are two ways to create panels:
–Use the Dialog Tag Language (DTL).
–Use of panel definition statements.
10.1 THE DYNAMIC TAG LANGUAGE (DTL)
The DTL was added to the ISPF later. Thus, you have the possibility to define
the panel using a description language. This definition is converted using the
Panel Conversion Utility in executable codes. The DTL is described in the
brochure ISPF Dialog Tag Language Guide und Reference. That this is a very
comprehensive tool, you can recognize by the fact that an extra brochure for
this theme exists. Since the DTL is very extensive and we panel definitions for
our purposes as quickly as possible, I will not use the DTL in this book. I do not
want to deprive here, what benefits that IBM provides in the use of the DTL.
That is why I copied the relevant passage from the DTL brochure below:

Why the Dialog Tag Language (DTL)?


If you are already familiar with a tag-based markup language, such as IBM Book
Master*, you will find that DTL is very similar. We created DTL for many of the
same reasons that we created Book Master:
Markup tags are easy to use. Because tag names are short and relate directly to
the structure of the dialog elements, they are also easy to remember.
DTL lends flexibility to application development. Panels can be quickly changed
without your having to tediously line up text and fields. This gives you greater
control over application development and updates.
DTL provides consistency when many programmers are working on the same
application, or when programmers who are new to your company must update
existing applications. Since each programmer is using the same tags, only minor
adjustments may be needed to achieve complete uniformity.
DTL techniques improve the way in which interactive programs, like ISPF
applications, are developed. The language concentrates on the role of the various
elements and their interrelationships, and ISPF takes care of their form and
appearance at run time.
DTL also enforces some formatting rules defined by the Systems Application
Architecture* Common User Access (CUA), so you do not have to be familiar with
all of the CUA formatting rules. Therefore, the CUA skills required by
programmers who are developing CUA-conforming applications are significantly
reduced.
DTL enables National Language Support (NLS) and the conversion utility
provides NLS translations for certain key words.
In other words, if you are looking for an application development and
maintenance system that is sophisticated, flexible, and easy to use, that's DTL.
If you come to the conclusion that the DTL is the right tool for you to develop
ISPF panels, you can use the DTL of course, because when calling the panel,
there is no difference between the two development methods for panels.

10.2 PANEL TYPES IN ISPF


The following table shows which panel types in ISPF exist:
Type Description

Standard Standard panels in ISPF normally have a width of 80 characters and consist of up to
panels 43 lines on a screen. When they are displayed, the currently displayed panel is
completely replaced.

HELP Help panels will be formed using certain instructions in the panel definition. They
panels can contain any number of rows and they have their own scrolling mechanism.

POPUP The dimensions of the pop-up panels are determined in the panel definition. When
panels you call them, they will be embedded in the currently displayed panel. The rest of the
underlying panel remains visible. POP Up panels can be moved while the display on
the screen using the cursor. HELP panels are very often defined as POP UP panels.

10.3 DEFINITION OF PANELS


In the following chapters, I will explain the key elements of the panel definition
using the Panel Definition Statements. I will discuss only those definition
items that I constantly use when I develop panels. The panel definition
statements are described in the brochure ISPF Dialog Developer's Guide and
Reference.

10.3.1 The structure of a panel


A panel definition generally consists of three elements:
–The attribute characters
–The text fields
–The data fields

The attribute characters


Attribute characters always occupy only ones character (byte). They determine
the characteristics of the field behind them up to the next attribute character.
The attribute character can consist of any characters. In practice, only special
characters are used as an attribute character.
Attention:
A sign that is defined as an attribute character can be used throughout the panel
definition text only as an attribute character. In other words, when a character
below the )ATTR statement in the )BODY section of the panel definition exists,
it will be used always as an attribute character, irrespective of whether this is
intended or not. Therefore, if you for example want to use a colon (:) in the
panel text, you cannot this define as an attribute character.

How to specify the attribute characters; see section 10.3.3.1 The Attribute
section starting on page 193.

The text fields


They contain solid, non-rewritable texts. Text fields can be colored using
attribute characters. How to specify the text fields; see section 10.3.3.2 The
)BODY section on page 195.

Data fields
There are two types of data fields:
–Input fields. These are defined for entering data. Input fields can also be used
for output.
–Output Fields. These fields are only defined for output of data. Output fields
cannot be used for input.

How to specify the data fields; see section 10.3.3.2 The )BODY section on page
195.

The attribute character in front of the field defines the type of a data field.

10.3.2 Creation of panels and their call


ISPF panels are typically created using the ISPF editor. In the edit sessions to
create ISPF panels it is essential to ensure that NUMBER OFF is set. If panel
definition lines include line numbers on the right, the display of this panel ends
with an error. Panels will be executed as they were created. A compiler or other
conversion process is not necessary. (Except DTL panels. However, we do not
want to discuss this here).
ISPF panels must be stored in a PDS/PDSE, which must be assigned during the
execution of the panels under the DD name ISPPLIB. Panels can be displayed
using the ISPF SELECT, DISPLAY or TBDISPL service. When called by
the TBDISPL service, the panel must contain a )MODEL section.

ISPF panels should have the following basic structure:


–Line 1: Panel ID, Title, Short message area
–Line 2: A command / option field and the scroll definition

The remaining lines can be designed as desired. ISPF short messages are always
displayed at the end of the first line from right to left in their current length. If
necessary, parts of the title line are truncated on the right. Long messages will,
if this is defined in the ISPF Settings menu, always be displayed at the bottom
of the panel in a frame. The )BODY section defines the panel structure.

10.3.3 The panel definition sections


A panel definition consists of several departments, the sections. Each section
is intended for a very specific purpose. In the table below, I listed those sections
that we want to deal with in this book. Each section starts at column one with
a ) (right parentheses) character that is followed by a keyword identifying the
type of section.
Table 10.1: Description of panel sections

Section Description

)ATTR The attr section defines the attribute characters for the fields of the panel.

)BODY The body section defines the panel layout.

)MODEL The model section defines a structure for the representation of variables of an ISPF
table.

)INIT The init section will go through before the panel is displayed. Here, initial values
can be set.

)REINIT The reinit section will go through when the panel is repeatedly displayed.
)PROC The proc section will go through when the panel display is exited by a command.
Here, the processing of the input values is performed. Typically, the plausibility
checks of the input values are performed here.

)END The end statement ends the panel definition. All lines behind this statement will be
ignored.

10.3.3.1 The Attribute section


The )ATTR line is usually the first line of a panel definition. However, it is not
always necessary. This is the case when the standard character attribute for
this panel are sufficient.

The default attribute characters are as follows:

These default attribute characters can be replaced by other characters using


the option DEFAULT(xyz) in the )ATTR line.

Example:

By defining this ATTR options, the following standard attribute characters are
active in this panel:

The attribute characters can be defined in any number and any character in the
)ATTR section. The following panel definition shows this:
Program 10.1: Panel definition of panel SLEP1

Note:
If the )ATTR statement is needed in a panel, this must always be the first line.
Comment lines can begin first after the )ATTR line.

The table below comes from the brochure ISPF Dialog Developer's Guide and
Reference. It contains all possible definitions for the attribute characters. The
most important type definitions for everyday use are greyed. I will refrain from
giving a complete description of all options. This is explained in the before
mentioned booklet and occupies circa 30 pages. I recommend you read this
when needed. Moreover, the options used in the above type commands are self-
explanatory.
Table 10.2: )ATTR definitions list

10.3.3.2 The )BODY section


The appearance of the panel is determined in the )BODY section. The panel
appears later as it was designed in this section. The following coding contains
all possible options:
Coding 10.1: )BODY section definitions

All information must be on the )BODY line. The greyed options are frequently
used. I will explain these here.
This statement defines a pop up panel which is 50 columns wide and 20
rows depth. It is important to ensure that the in the )BODY section defined
rows and columns fit the available framework.

With this statement, the expansion characters are determined. With these
characters, you can fill text lines dynamically with padding characters. See the
following example:

Example:
The panel definition of panel SLEP1 contains the following code:

When the panel is displayed, it looks like this.

The first and the last line are shown expanded with the expand character –
(hyphen).

Remark:
The expansion characters must be unique (just like the attribute characters)
within the panel definition. Therefore, this character can only be use for the
definition of dynamic expanding.

10.3.3.3 The )INIT section


In the )INIT section all measures can be taken that are necessary prior to the
display of the panel. Such measures may include:
–Fill variables with initial values.
–Definition of the Z variables using the .ZVARS statement.
–Define the cursor position for the initial display of the panel.
–Specifying the general help panel. This panel appears when the PF1 key is
pressed.
Coding 10.2: )INIT section example
Note:
In the above .ZVARS definition can be seen how continuation lines are
formed in panel definitions by the plus sign.

10.3.3.4 The )PROC section


The )PROC section is run through when the input is terminated by pressing the
ENTER or a PF key. In the )PROC section normally plausibility checks and some
processing of the entered values are performed. For these purposes, a number
of commands are available that are used for the following tasks.

When assignments are performed, the following functions are often used for
the determination of the result:

If and ELSE:
Because no THEN is available, another rule must exist how commands are
defined when an IF statement as true ends. This rule is very simple:
Rule:
If an IF query is recognized as true, then all the instructions in the following
lines are executed that are indented at least one column to the right.

Again, it is beyond the scope of this book to discuss the above listed statements
and functions in detail. To explain the design of an ISPF screen, I will use the
screen SSCPP01. The SSCPP01 screen is one screen of the SMART ISPF utilities.
The SSC program calls it. The panel has a complex format and is therefore a
good example to explain the functionality of an ISPF screen structure:
Coding 10.3: SSCPP01 – Panel definition example
Explanations for some lines in this panel definition:
Lines Explanation

57+58: If the variable LRC was set greater than zero in the calling procedure SSC, then the
special variable .RESP will be filled with the text END. This means that the PANRC
variable is set to 1 at the end in row 111. When after returning from the panel the variable
PANRC is 1, the procedure SSC will be exited.

59: If the special variable .RESP contains the text ENTER, the statements up to line 108 will
be executed. Otherwise, the program is continued at line 109.

60– When the function code is EX, then only the expiration date of the data set is changed.
68: In these lines, the date variables that the function DSINFO has delivered will be checked
and if necessary updated. Due to the statement go to out: in line 068 the execution of
the panel continues at line 109.

69: The variable NEWDSN will be verified. NB means NEWDSN must not be blank.
DSNAME means that the variable must contain a valid DSN. If one of these conditions
is not met, then the message CR011A is displayed on the screen.

70: The variable FCHARS will be verified. FCHARS represents function characters. NB
means FCHARS must not be blank. LIST means that the variable must contain only one
of the values contained in the LIST option within the comma-separated text string. If
one of these conditions is not met, then the message CR010A will be displayed.

71+72: The variable FCHARS contains always two characters. The first character of FCHARS
is extracted into the variable FCHAR1 using the TRUNC function and the second
character is extracted in the variable FCHAR2 using the .TRAIL function.

73 If the variable FCHAR1 does not contain C, then no copying operation will be
performed. In this case, the statements until the line 108 is reached will be executed.
79–81: Here the functions TRANS and TRUNC are combined. This has the following meaning:
With TRUNC the first character of the variable UNITS will be extracted. Then the word
following the comma is placed in the UNITS variable with TRANS. This means the full
names are set by the TRANS function. The advantage of this method is that you always
have to enter only the first letter of CYLINDERS, TRACKS or BLOCK at the input. When
the content of the variable UNITS does not begin with one of the letters given in the list,
the message CR018A will be displayed and the program will be exited

The commands after line 81 contain further examinations and assignments. I


think that the explanations of statements, which I made up to line 081 are
sufficient as a guide to understand the other instructions.

10.3.4 Variables in panel definitions


Behind every attribute character for an input or output field a variable must be
named. The variable name can consist of up to eight alphanumeric characters.
Everywhere in the panel definition, where only a variable name can stand, no
ampersand must precede the variable name. For example, in the .ZVARS
statement.
Rule:
All variables in the panel definition and in the REXX program, which the
panel displays, are known mutually in both elements. If variables are defined
in a REXX procedure which are also used in screen definitions, it must be
ensured that they are not longer than 8 characters.

The Z variables

Why are Z variables needed?


If a data field in a panel is shorter than the corresponding variable name, then
the variable name cannot be written into the data field in the panel. In order to
overcome this handicap, the so-called Z-variables were introduced. This works
like this: Whenever behind an attribute character for an input or output field
only a Z stands, the variable used in this field will be extracted from the
corresponding variable name in the allocation of Z variables in the .ZVARS
statement and assigned to this field.
Definition:
The .ZVARS control variable can be set in the initialization section to a list of
variable names that correspond to Z place-holders in the body and/or model
lines.

Example:
The following excerpt from the panel Coding 10.3: SSCPP01 – Panel definition
example on page 198 shows the allocation of the Z variables in the .ZVARS
statement to the panel locations.

As you can see, 10 variable names are defined in the .ZVARS statement and 10
Z fields are defined in the panel. By the way, you can also address such variables
as Z variables which name would not be too long for a direct placement (e.g.
PRIM, SEC, UNITS).
Attention:
When you insert or remove Z variables during the development of a panel, it
is essential to adapt the .ZVARS statement accordingly.

10.3.5 Panel processing


ISPF provides multiple services to call up panels:
–The DISPLAY service
–The SELECT service
–The TBDISPL service

10.3.5.1 The DISPLAY Service


The DISPLAY service calls up a panel. It may be indeed some options given.
However, these are largely theoretical.

Example 1: Call up a standard panel


The following coding shows a part of the program SSC of the SMART ISPF
utilities. The SSC processing starts with the display of the main panel SSCPP01.
You can also see how the processing of the program is ended. When in panel
SSCPP01 the PF3 key is pressed, then the variable PANRC is set to 1. At return
from the panel display the IPANEL loop is left and the program exits (statement
line 305).

Example 2: Display of a POP UP panel


When the program SSC copies a data set and records would be truncated, then
a POP UP panel is issued which displays a warning and the operator can confirm
the truncation and continue or exit the processing.

I simulated such a critical copy task. See the display of the POP UP panel:
Tip:
You can use the cursor to move a pop-up panel within the totally available
display to another position. Proceed as follows: Place the cursor to a point of
the frame of the pop up panel and then press ENTER. Then the
text Window move pending appears in the upper right corner of the
screen. If you now move the cursor to any position in the screen and press
ENTER, the entire pop up panel will be moved to the new position. Using
this method, you can make invisible parts of the surrounding panel visible
again.

10.3.5.2 The SELECT PANEL service


The SELECT service can also be used to call up panels. These panels must have
a special structure. They are normally used to start an application. One of the
typical panels of this type is the panel to display the ISPF Primary Option
Menu. Its name is normally ISR@PRIM. This panel has been created with the
ISPF Dynamic TAG language. Therefore, I will not discuss the panel here.

10.3.5.3 The TBDISPL service


The TBDISPL service not only calls the panel in question; but also the content
of the underlying ISPF table will be displayed. See section 10.3.5.1 The DISPLAY
Service on page 202 and the section 10.3.5.3 The TBDISPL service on page 204.

10.3.6 Help panels


There are four types of help panels:
–The general help panel for a screen.
–Help panels, which are assigned to a field in the screen.
–Full screen help panels.
–POP UP help panels.

1. The general help panel


Each screen definition may contain an entry for the display of a so called general
help screen. The general help panel must be defined in the )INIT section. The
general help screen is called when the PF1 key is pressed and the cursor is at a
location of the screen for which no specific help panel is defined.

2. Field assigned help panels


For each data field in a panel a specific help panel can be defined. Such a panel
is called, when the cursor is at any position within the data field in question and
PF1 is pressed. Field assigned help panels must be defined in the )HELP section.
See lines 114 to 138 of the Coding 10.3: SSCPP01 – Panel definition example on
page 198.

3. Full screen help panels


As the name suggests, these panels replace the entire screen when they are
displayed. This type is used the most for general help panels.

4. POP UP help panels


This type of panels is mostly used for field assigned help panels. See section
10.2 Panel types in ISPF on page 190.
The basic structure of a help panel looks like this:
Program 10.2: HELPMASK – Help panel template

Remarks:
To define help panels the grayed lines are needed. I always use this template
when I need to create a new help panel. The general help panel is entered in
the )INIT section of the panel definition. Please note that help panels
specified in the )INIT section act as general help panels. They appear when
PF1 is pressed and the cursor stands at any position in the panel and not in
a field for which an own help panel exists.

General help panels are defined in the )INIT section as follows:


10.3.7 Panels to display ISPF tables
Table display panels are used to display and edit ISPF tables. ISPF tables are
two- dimensional tables that are created by using ISPF table services. These
services are also used for the data maintenance of the tables. A table display
panel contains a )MODEL statement in which those variables from the ISPF
table are defined which want to be displayed with this panel.

Example:
The panel SLEP1 is a typical table display panel. The SMART ISPF utility
program SLE uses it:
Program 10.3: Definition of panel SLEP1
Lines Explanation

23 The )MODEL statement defines that the following line 24 structures the display of values
contained in the table $SLETAB.

24 The Z variable is the last one which occurs in the panel definition and therefore is assigned
to the last varaiable in in the .ZVARS definition in line 26. It is the variable function. The
fields of DSN, DATE and TIME are large enough to contain the variable name itself.

27 The general help panel for the panel SLEP1 is defined here.

42–8 Here the help panels for all fields are defined, which have an own help panel.

Excerpt from macro #IMACRO2:


Excerpt from macro #IMACRO2 where the table $SLETAB is updated
respectively created and updated.

Excerpt from program SLE:


The following excerpt from program SLE shows the command, that displays the
panel SLEP1 together with the contents of the table $SLETAB.
Finally yet importantly, here is a display of panel SLEP1 with the data in table
$SLETAB.
Screen 10.1: Panel SLEP1 displayed by program SLE

For each of the shaded boxes a dedicated help panel is defined.

Mnemonics to table display panels


Behind the )MODEL statement up to eight model lines may be defined.
–The table display panels are automatically SCROLLABLE. Therefore, you can
handle ISPF tables of any length.
–Scrolling is done with keys PF7 and PF8. PF7 ˆ backward, PF8 ˆ forward.
–The display can only be performed in 80 columns.
–If you want to also edit the contents of the tables, you should define the first
column as an input field for the operation code. See the above panel SLEP1.
–In the row behind the )MODEL line there is no need to be list all names of an
ISPF table.

11 Skeletons – Design and use


In this chapter, you will learn how you can create JCL members and other data
elegantly by using ISPF skeletons. ISPF skeletons are members in a PDS/PDSE
that are created with the editor. They are masks which are used for the
management of any data structures. Skeleton members consist of basic texts,
skeleton control statements and variable names. The variable names are
replaced during processing of skeletons by the ISPF file-tailoring services by
the actual values which are set in the processing REXX procedure. As with the
panels, the variable names must not be longer than eight characters.

11.1 CREATING SKELETONS


For the creation of skeletons, the following commands are available:
Table 11.1: Commands to create skeletons

Command Function

)BLANK )BLANK 5 inserts 5 blank lines into the skeleton, which is being edited.

)CM With )CM, comment lines can be defined in the skeleton. These lines are not
copied to the output component.

)DEFAULT To control the skeleton processing, seven special characters are reserved by
default. These are the characters: ), &, ?, !, <, |, und >. With the )DEFAULT
command these characters can be changed temporarily

)DOT Using these two statements, a loop can be formed.

)ENDDOT

)IM This statement inserts another skeleton. The variables of the inserted skeleton will
be dissolved and the result is added to the output component.

)SEL With )SEL a condition can be queried. If this condition is satisfactory, all the rows
are

)ENDSEL processed until the next )ENDSEL.

)SET Assignments can be made by using this instruction.


)TB, )TBA Tab stops can be set by using this instruction.

Example:
The following skeleton adds a step into a job which executes instructions for
DB2 BIND PACKAGE commands. The BIND PACKAGE instructions will not be
executed in this job step; they are executed in the called REXX procedure
VINTPAC.
JCL 11.6: Definition of a skeleton

Remarks:
–I have grayed all relevant places for a skeleton definition.
–In line 10 the skeleton $ISPFDD is inserted. This skeleton contains the
necessary DD statements for execution of REXX procedures in an ISPF batch
environment.
–If a skeleton variable should be connected to another skeleton variable, a point
is used as concatenation operator. If the resulting string is a DSN, an
additionally point will be inserted for separating the single DSN qualifiers. DSNs
are built in the lines 14 and 16. Therefore, here two consecutive dots are used
to assemble DSNs.

Here are the statements of the REXX procedure VINTSN that processes this
skeleton:
Coding 11.1: Skeleton processing
In this part of the program, most skeleton variables are filled with values. Some
have already been set earlier in the procedure. When the statement FTINCL
VINTPAC in line 3221 is executed, the following happens:
–The member VINTPAC will be searched in the data set chain associated with
the DD name ISPSLIB and inserted in an internal area.
–Thereafter, the file-tailoring service is called. This processes the skeleton line
by line.
–The contents of the variables from the REXX/ISPF variable pool replaces the
variables.
–Any existing file-tailoring statements are executed. In this skeleton only one
)IM statement is contained. The member $ISPFDD is searched in the ISPSLIB
chain and inserted in the JCL stream. The variables contained in the member
will be replaced by the actual values.
–When the file-tailoring service has conducted all processing, the result is
added to the internal data stream that has been opened with the FTOPEN
statement.
–When all file-tailoring work that is necessary to form a JCL member is finished
in the procedure VINTSN, the created JCL member is saved using the command
FTCLOSE NAME(name) LIBRARY(ddname). If ddname is not
specified ISPFILE is used.

The job step created by the file-tailoring service looks as follows:


JCL 11.7: Job step created by the file-tailoring service
In the previous image, I grayed all the locations where values were inserted by
variable substitution and all inserted rows.

11.2 STEPS TO USE THE FILE-TAILORING SERVICE


1.Use the ISPF editor to create a member in a PDS that is assigned under the DD
name ISPSLIB for processing skeletons by a REXX procedure.
2.Create a REXX procedure where the variables are set used by the file-tailoring
service to replace the corresponding variables of the skeletons.
3.Use in the REXX program the FTINCL service to insert a skeleton.
4.Use the FTCLOSE NAME(name) service to save the member name.
Tip:
The file-tailoring service can also be used to generate any arbitrary data set.

12 Tables – Create and edit


Here you will learn how to create, edit and view ISPF tables. The table service
of ISPF provides the ability to create tables, to edit and to use them for your
daily work. A row in the ISPF table consists of columns that are named by ISPF
variables. Each line can be addressed using ISPF table service commands. After
carrying out such a command, the names of the variables in the manufacturing
procedure are known.

12.1 LOCATIONS FOR TABLES


Tables can be created either temporarily or permanently. A temporary table
only exists in virtual memory. It cannot be saved in a permanent data set.
For processing, the entire table always resides in virtual memory. This means
that an ISPF table is limited in its size by the available virtual memory. Normally
tables are stored in memory above the 16-megayte-line. This allows ISPF tables
to become quite large.

12.2 READING ISPF TABLES


A table is read from the ISPTLIB data set chain with the TBOPEN statement into
the memory or it is created there temporarily. When a table is read from
ISPTLIB with the WRITE option, then an ENQ is set on the member in which this
table resides. This prevents that this table can be read a second time. The ENQ
is cancelled when the table is closed with TBCLOSE. When reading with the
NOWRITE option, the ENQ is only active during the read operation. Under the
DD name ISPTLIB several PDS/PDSE are normally allocated. When executing
the TBOPEN, the member is searched in this data set chain. The first occurring
member of the name will be loaded.

12.3 WRITING ISPF TABLES


When writing ISPF table members, you cannot use the DD name ISPTLIB
because under this DD name usually a chain of PDS/PDSE is allocated.
Moreover, we have learned above, that we cannot write to a DD, which
addresses a concatenated data set. The DD name ISPTABL is used to write
tables. Therefore, always only one data set is allocated to ISPTABL. If this
applies, you must consider that the following question naturally arises: How
can I maintain a table if I cannot write back to the file of which I have read?

A small trick solve this problem:


–You can read all the tables that are included in the PDS/PDSE concatenation
of about the DD name ISPTLIB.
–Tables can only be written into a data set that is associated with the DD name
ISPTABL.
–When the data set that is allocated with the DD name ISPTABL to write tables
is also allocated as first data set in the ISPTLIB chain, then a recently written
table will always be loaded with its latest contents.

This allocation looks in practice in my TSO user:

Rule:
When I write a table (whether new or read before), then it will be written via
ISPTABL in the LANZT.ISPF.TLIBTAB.LPRT data set. When I read them
afterwards, it is first found in the same physical data set under the DD name
ISPTLIB and read from there. In order for the ongoing maintenance of a
table will guaranteed.

12.4 COMMANDS OF THE TABLE SERVICES


In ISPF, a number of commands for working with tables is available. We
distinguish the commands that relate to an entire table and those, which relate
to the processing within the tables:
Table 12.1: Table services commands that refer to the entire table

Command Description of the commands that refer to the entire table.

TBCLOSE Closes a table and saves it in the output data set if it had been read before.

TBCREATE Creates a new table and opens it for processing.

TBEND Closes a table without saving them.

TBERASE Deletes a table member in the ISPTABL data set.

TBOPEN Opens an existing table for processing.


TBQUERY Provides information about a table.

TBSAVE Backs up a table in the member in ISPTABL without the table to close.

TBSORT Sorts a table.

TBSTATS Provides statistics information on the table.

Table 12.2: Table service commands that relate to individual rows

Command Description of commands that relate to


individual rows

TBADD Inserts a new row in the table.

TBBOTTOM Sets the CRP (Current Row Pointer) on the last line
of the table.

TBDELETE Deletes a row from the table.

TBEXIST Tests if there is a line with a specific key.

TBGET Stores the contents of the current row in the


corresponding variables.

TBMOD Changes the contents of an existing line or adds a


new line.

TBPUT Changes the contents of an existing line if it exists,


and if the key matches.

TBSARG Sets on a search argument for a subsequent TBSCAN


or TBDISPL.

TBSCAN Searches in the table for a row which is in accordance


with the given arguments.
TBSKIP Moves the CRP forward or backward by a specified
number of rows and stores the values of the
addressed row into the corresponding variables.

TBTOP Sets the CRP at the beginning of the table.

TBVCLEAR Fills all the variables of the table with zero values.

Again, I will refrain from describing the above commands in detail. Instead, the
following examples will show you how to create a table and how to use it.

12.5 EXAMPLE OF WORKING WITH TABLES


As I mentioned on several occasions, I wrote an ISPF application which displays
the DSNs of the most recently edited data sets in a panel. The main program of
this application is SLE which stands for Smart Last Edit. It is contained in the
collection of the SMART ISPF utilities. All programs of this application are
written in REXX. The following table shows the most important components
that belong to this application:
Table 12.3: Components of the SLE application

Name Type Function

SLE Main This program is called as ISPF function. It displays the panel SLEP1
program and performs the work initiated there.

#IMACROA Edit If an edit session is started, this macro checks whether the IMACRO
macro option is already set for the edited data set in the edit profile. If this is
not the case, the option IMACRO is set to #IMACRO1.

#IMACRO1 Edit This macro defines an ALIAS so, that at the end of the edit session
macro #IMACRO2 is called.

#IMACRO2 Edit This macro will be called automatically when an edit session ends. It
macro inserts the DSN of the currently edited data set into the ISPF table
$SLETAB. At the next call of SLE, the name of the recently edited data
set is contained in the table $SLETAB and it will be displayed in the
panel SLEP1.
SLEP1 ISPF This is the main panel for execution of the SLE application. It shows
panel the table $SLETAB and offers the ability to perform some actions with
the shown data sets.

Many help panels are defined to assist the user in the working with the SLE
application. However, these panels are not important for the function of the
application and are therefore not named here.

Here the part of the edit macro #IMACRO2, which shows the updating (or
creation) of the ISPF table $SLETAB:
Program 12.1: Excerpt from edit macro #IMACRO2

Lines Explanations

66 Table $SLETAB is opened. The RC is saved in openrc.

68 Some table variables are set.

70–74 When the table $SLETAB exists, it will be updated and written back to ISPTABL.

75–79 When the table $SLETAB does not exist it will be created and written into ISPTABLE as
new member which then contains one row of data.
Here an excerpt of the panel description of panel SLEP1 where the )MODEL
line defines the structure of the displayed rows of the table $SLETAB.
Coding 12.1:Excerpt from panel definition of the panel SLEP1

Lines Explanation

23 Here the model definition segment begins. This line can be followed by up to 8 definitions
of data structures.

24 Here only one line structure is defined. It contains the names and positions where the
contents of the variables of the table $SLETAB are displayed. Because in the previous
panel definitions already four Z-variables are set, the Z-variable in line 24 for the name
FUNCTION is assigned by the .ZVARS definition.

The complete definition of panel SLEP1 is found in Program 10.1: Panel


definition of panel SLEP1 on page 194.

The TBDISPL command to display the panel SLEP1 together with the table
$SLETAB is shown in the following excerpt from program SLE:
Coding 12.2: Excerpt from program SLE showing the TBDISPL command of
panel SLEP1

Here now a display of the panel SLEP1 containing the data of the table
$SLETAB:
Screen 12.1: Display of panel SLEP1 produced by the program SLE
13 Variables – Definition and using
In this chapter, you will learn how to define and use ISPF variables. ISPF
variables are either automatically known in REXX programs or they can be
made known there.
Advice:
If you intend to use a defined variable in REXX source code and in the called
ISPF services, then the variable name must not be longer than eight characters.

The variables of the ISPF services are an important part of ISPF. Dialog
variables are the primary communicator between the individual components
of ISPF. Programs, procedures, panels, tables and skeletons can all share the
variables from the three ISPF variable pools. The three ISPF variable pools are:
–Function pool for implicit variables.
–Shared pool.
–Profile pool.
The variables are combined in groups, which are associated with a particular
service. Many variables are set only by certain ISPF services. Other variables
must be filled with appropriate values before a service that requires these
variables is called. A ISPF application ID is assigned to each pool of variables.

13.1 VARIABLES POOLS


As mentioned above, the ISPF variables are arranged in variables pools with the
following subdivisions:
13.1.1 Function pool
These variables are only known in the currently running function or group of
procedures. These include, for example, all variables in a REXX procedure whch
names are not longer than eight characters, and the variables of panels,
skeletons etc. These variables are called function variables.
Each function has its own set of variables. If an item within the ISPF in different
logical screens is launched parallel, then the variable exist with the same name
several times, but with different contents. These variables can only be
exchanged with other functions when you write them in a function in the
shared pool and are read in the other function from there.
When a new function will be started, ISPF creates a variables pool for this
function. This pool of variables is deleted at the end of the function. A function
is a program or a procedure that can be called with the SELECT service. This
means you can exchange variables between these programs or procedures only
via the shared or the profile pool.

13.1.2 Shared pool


The shared pool contains variables that are used within an application. A
variable in this pool is called shared variable. The SELECT service creates a
shared pool when executing the commands ISPSTART or ISPF. The same
happens when a SELECT is performed using the options NEWAPPL or
NEWPOOL .
One function may use the VPUT service to copy shared variables into the shared
pool, and another function in the same application can use the VGET service to
read these variables for using.

13.1.3 Profile pool


The variables in this pool will be saved from session to session for each
application. This means that the variables of this application are written in a
member which is associated with the application in the profiles data set. When
the application is started later again, the corresponding member will be read.
If you need these variables in a function, you have to read them using the VGET
service. To save them so that they are available again the next time you start a
function, they must be re-written using the VPUT service into the profile pool
before leaving the function.
Thus, the variables of profiles pools can be made available from session to
session and from application to application. Of course, a data set must exist in
which these variables are saved. This data set must be assigned under the DD
name ISPPROF as PDS/PDSE before starting the ISPF. If this data set is not
assigned, ISPF cannot be started. As mentioned above, the variables in the
profiles pool are stored separately for each ISPF application into a member
in the profile data set. The name of this member is formed as follows:

xxxx PROF, where xxxx is the up to four digits long name of the application. The
profile members are created and processed as ISPF tables.

The following figure shows an excerpt from the list of members in the ISPPROF
data set of my TSO user:

Screen 13.1: Members of an ISPPROF data set

The application dependent members are grayed.

13.2 SAVING THE PROFILE MEMBERS


If an ISPF application is terminated normally, their profile variables are written
back to the appropriate member of the profile data set. The member ISPPROF
will only be written back if the ISPF itself terminates.
Attention:
If ISPF, from whatever reason, is not properly completed or is aborted, then the
currently active profile members will not be written back. This means that
after a restart of ISPF, all changes made in the profile variables before the
demolition are lost. The same applies if a single application aborts. In this case,
the profile member containing the application variables will not be secured.

13.3 CREATING PROFILE MEMBERS


When ISPF or a new application starts, then ISPF searches for a profile member
as
follows:
1First, the user profile associated with the DD name ISPPROF is searched for
the member xxxxPROF. If the member is found there, then it is loaded and the
profile variables contained therein are available for the application. This means
you can now read variables with VGET and write back with VPUT.
2If the profile member is not found in the ISPPROF chain, then the member will
be searched in the ISPTLIB chain. If it is found there, it will used and written
back in the ISPPROF data set when the application or ISPF is closed.
3.When also on the ISPTLIB chain no fitting member for the launched
application is found, the default profile member will be read from ISPPROF and
copied to the variable pool for this application. When closing the application, its
profile member is written into the ISPPROF data set.

Consideration:
ISPF will be started at the end of the LOGON procedure. This can be done with
three different commands:
1ISPSTART PANEL(name) NEWAPPL(applid).
2PDF
3ISPF
If called with PDF or ISPF, then the following command is issued internally:

ISPSTART PANEL(ISP@PRIM) NEWAPPL(ISR).


This way of calling the ISPF causes the standard APPLID in the ISPF to be ISR.
This means that the member ISRPROF is used as standard ISPF profile
member. Therefore, if you want to operate your ISPF with the APPLID ISP, then
you would have to start your ISPF with the following command:

ISPSTART PANEL(ISP@PRIM) NEWAPPL(ISP).


13.4 DISPLAY OF ACTUALLY USED PROFILE MEMBER
I have launched several ISPF applications in my TSO user. Then I looked which
profile members are loaded now. Here is the first indication of the started
applications. I created this display using the ISPF command SWAP LIST.

Screen 13.2: List of started ISPF applications

When these applications are launched, then all members belonging to these
applications profiles must be loaded. This can be checked very easily by looking
up which ENQs exist on the data set containing the profile members. The easiest
way to check this is using the utility DDLIST. Therefore, I called DDLIST and
entered ENQ in the command line. In the appearing panel, I entered as minor
name prefix the DSN of my profile data set LANZT.ISPF.PROFILE.LPRT and
pressed ENTER.

The following ENQs are displayed:


As you can see, the corresponding profile members are loaded and ENQed for
all open applications.

13.5 THE SYSTEM PROFILE POOL


ISPF contains own variables that can be used by the user, but not overwritten.
These variables are always present. They are stored in the member ISPSPROF.
This member is always loaded when ISPF starts. The system profiles pool is
located behind the ISPF standard pool. Therefore, if you read a variable from
the system profile pool, you can put it back in the standard profiles pool.
However, you must observe the following:
>Attention:
When you read a variable from the system profile pool, you can change it and
write it back. In this case, the changed variable be stored in the standard profile
pool. Afterwards is it impossible to read the origin variable again from the
system profile pool. If you delete the variable using the VERASE command, you
can read then the origin variable from the system profile pool again.
Tip:
In the brochure, ISPF Dialog Developer's Guide and Reference there are
several attachments, where all standard ISPF variables are described.

13.5.1 Frequently used ISPF variables


As mentioned above, many ISPF variables are only provided when certain
services are running. These variables can be found in the description of the
respective services. However, there is a whole range of ISPF variables that you
can make good use of when creating applications in ISPF. If you want to use
these variables in a REXX program, then you can read the appropriate variables
using the command ISPEXEC VGET (namel, name2, …). In the two tables
below, I listed several ISPF system variables that are used most frequently:

13.5.1.1 General ISPF variables


Table 13.1: General ISPF system variables

13.5.1.2 System variables containing date and time in different


variations
13.5.2 Process ISPF variables
There are exactly three commands that you can use with REXX to work with
ISPF variables. These are:
VGET → Read variables

VPUT → Write variables

VERASE → Delete variables

Formats of the three commands


VGET (name-list) ASIS | SHARED | PROFILE
ASIS The variable will initially be searched in the shared pool. If it is not found there, the search
is continued in the profile pool.

SHARED The variable is searched only in the shared pool. If it is not found there, the command
ends with a RC=8.

PROFILE The variable will be searched only in profile pool. If it is not found there, the command
ends with a RC=8 and a variable of the same name in the shared pool will be deleted.

VPUT (name-list) ASIS | SHARED | PROFILE


ASIS The variable is written to the pool, where it already exists. If it exists nowhere, it is written
into the shared pool. If it already exists in the shared pool and in the profile pool, it is only
changed in the shared pool.

SHARED The variable is only written to the shared pool.

PROFILE The variable is only written to the profile pool. A variable of the same name in the shared
pool is deleted.

VERASE (name-list) ASIS | SHARED | PROFILE | BOTH


ASIS The variable is deleted from the shared pool. If it does not exist there, it is tried to delete
them from the profile pool.

SHARED The variable is deleted from the shared pool.


PROFILE The variable is deleted from the profile pool.

BOTH The variable is deleted from the shared and from the profile pool.

Remark:
All REXX variables whose name is not longer than eight characters are
automatically known in function pool. If you want to write a REXX variable
into the shared or profile pool, you must explicitly use a VPUT command.

Example:
I wrote a small REXX procedure to read and display some ISPF Z-variables:

Program 13.1: ZVARS – Display some ISPF Z-variables


I executed this procedure and got the following result:

14 Edit macros – Create and apply


In this chapter, you will learn how you create and use edit macros. With edit
macros will recurring tasks are performed quickly and elegantly. To get the full
benefit of the ISPF editor, edit macros in my opinion are indispensable.
We have already extensively worked in the first part of this book on the
operation of the ISPF editor; therefore, we now want get to know another very
interesting part of the ISPF editor. There are many activities in ISPF where a
certain automation may be helpful. These are, for example, the preparation and
the SUBMIT batch jobs, the edit output lists, etc.
For such tasks, the use of edit macro is a very nice aid. This recurring work can
be always greatly accelerated and facilitated. The SMART ISPF
utilities contains a series of such useful macros. In the literature collection for
ISPF there is a brochure in which next to the description of the manual
operation of the editor, also the creation of edit macro is described.

This brochure is ISPF Edit and Edit Macros.

14.1 WHAT IS AN EDIT MACRO?


An edit macro is a REXX procedure that contains special commands for the ISPF
editor beside the REXX commands. These edit commands are passed to the ISPF
editor to run under the ADDRESS label ISREDIT. Of course, in an edit macro, all
other commands are possible, which can occur in REXX procedures.

Edit macros can be executed as follows:


–Enter in the command line of ISPF editor the name of the edit macro
procedure. This is the normal way to execute edit macro.
–Use the command EDIT DATASET(dsn) MACRO(name) in a REXX procedure.
–Define initial and/or end macros for editing data.

14.1.1Naming conventions for edit macros


The name of an edit macro must only correspond to those of REXX procedures.
However, I have found in the course of my work in the ISPF that it may be well
of advantage to use a naming convention for the edit macros. The advantage is
that you can distinguish them from the rest of REXX procedures. I always start
the name of my edit macro with the # character. This has the advantage that the
names of my edit macro stand on the top in the REXX procedures data set
directory consecutively. Even if I look for a template for a new edit macro, I
need only look up the members that start with #. In addition, it is abundantly
clear that you can never call an edit macro like a normal procedure. The
commands that are addressed to the editor are only executable when the REXX
procedure runs under control of the editor.
If an edit macro is called from within a REXX procedure using the EDIT
command, I call it up the same way as calling the REXX procedure by prefixing
the procedure name with the # character.

14.1.2Example of two very useful edit macros


Before we go into the details of programming edit macros, I want to show you
a simple example what an edit macro can supply.

The first macro #SSS


The SMART ISPF utilities contain the program SSS.
SSS stands for Smart Super Search.
This program uses the standard ISPF program ISRSUPC to perform the search.
This program produces a list output. This list is very elaborate. It contains many
needless lines. I have therefore written an edit macro, which removes all
unnecessary texts from this list. According to the naming conventions
mentioned above, the name of the macro is #SSS.
The second macro #SSSCH
When the editor displays the resulting list of the search, you can change some
lines in this list. If you then call the macro #SSSCH, the lines currently being
edited replace the lines in the members. Using this technique, you can perform
mass changes in all members of a PDS very easy and very quickly.

The program SSS works as follows:


1The program SSS is called by entering SSS in front of a DSN in a DSLIST display
panel. The search will be performed for all members of this partitioned data set.
2The program then displays a panel, which is designed to enter the search
arguments.
3After pressing ENTER, the program calls ISRSUPC and the search starts. The
program ISRSUPC writes the search results in a temporary sequential data set.
4The ISPF editor is called in the REXX program using the following
statement “EDIT DATAID(“UTID”) MACRO(#SSS)” The DATAID UTID was
established by a LMINIT command earlier in the program.
5The macro #SSS removes all needless lines from the data set before the list is
displayed.

Example for using of both above mentioned macros:


Task: I would like to know in which programs of the SMART ISPF utilities the
ISPF service QUERYENQ is used.

Step 1:
I enter SSS in front of the PDS where the SMART ISPF utility programs are
located. The following panel will displayed. In the field 1. = I enter the search
text QUERYENQ.
Screen 14.1: Panel SSSP1 for entering search arguments

When enter is pressed, the search will performed and the following edit panel
is displayed:

Screen 14.2: Resulting panel after executing a SSS search

The program ISRSUPC produces a list with LRECL=133. Therefore, the lines of
this display are cut off on the right side. To see what lines by the macro #SSS
were removed, here is the origin output of the program ISRSUPC:
Screen 14.3: Original output list of program ISRSUPC

As you can see, the list is reduced from 33 lines to 17 lines.

Step 2:
As you can see in line 487 of the program SLE, the word Paramter is wrong. I
will now correct this error. First, I remove all unneeded lines and correct the
wrong word to Parameter. Then the following edit panel remains:
I enter #SSSCH in the command line and press enter. The following display
appears:

What shall the macro #SSS do with the list produced by ISRSUPC?
–Remove any blank lines.
–Remove all lines that start with the following texts: ISRSUPC, PROCESS
OPTIONS USED, THE FOLLOWING PROCESS.
–Shift the lines where the name of the text SEARCH DNS: scanned data set
appears together with the DSN as far to the left that the DSN text starts at
column one.
–Remove the lines that begin with LINES-FOUND together with the next line.
–At the beginning of the revised text put a notice that this data set has been
optimized by macro #SSS.
–Inserting a row by pointing out that using the edit macros #SSSCH, the edited
and possibly changed lines can be written back to the members.

Here the source codes of both macros:


Program 14.1: Edit macro #SSS
Program 14.2: Edit macro #SSSCH
Conclusion:
With the program SSS of the SMART ISPF utilities and its edit macros, you have
a very strong tool for searching and changing mass data. Additionally, these two
edit macros are well suited to explain the using of edit macros.
14.2 TABLE OF EDIT MACRO COMMANDS
Edit macro command types:
The edit macro commands are generally divided into two types:

First type: editor action command:

“CURSOR = line col”.

This command positions the cursor on line line and column col in the edited
data.

Second type: assignment commands


This commands set values into variables:

“(line,col) = cursor”.

The variable line contains the cursor position of the current line and the
variable col the column in the line of the data currently being edited.
As you can see in the following table, many edit macro commands offer both
possibilities.
The following table is a condensed summary of the main edit macro commands
as can be used in a REXX procedure. Of course, the IBM brochure Edit and edit
Macros also contains a description of the edit macro commands. However, this
is presented in a very confusing manner. Incidentally, this is one of the reasons
why this book has been written. Therefore, I make an effort to present the
reader a focused summary in the following table.
Table 14.1: Edit macro commands
14.3 OPERANDS AND ABBREVIATIONS USED
IN THE EDIT MACRO COMMANDS
To help you work with the macro commands as listed in the table above, please
find below a brief description of those operands and abbreviations that are not
always self-explanatory by their name:
Table 14.2: Operands and abbreviations of edit macro commands

Operands Meaning

(var1,var2,..) Here are some variables specified, depending on the function.

(var) The name of a variable must be specified. This name must be not longer than 8
characters. If the (var) is on an assignment statement on the left side, the editor
stores into the variable a value. If (var) is on the right side in an assignment
statement, the REXX program must have been previously stored a value into the
variable.

[FIRST] A search for the first or last occurrence of the text is performed in the data
[LAST] currently being edited.
[NEXT] Starts at the current cursor location and performs the operation forward [NEXT]
[PREV] or backward [PREV] in the data currently being edited.

[PREFIX] The specified text is used in the search as a prefix or suffix.


[SUFFIX]

[x] [nx] The operation in question is performed only for EXCLUDED lines (x) or the NOT
EXCLUDED lines (nx).

ALL This operation will affect all lines of the data currently being edited.

amt amt defines the relative number of elements in shift or jump operations. (amt =
amount)

col-1 col-2 Two integers, which limits an operation on the designated columns.

col1 col2

data Denotes a text enclosed in quotes.

labelname Name of a labeled line. e.g. .AA, .XY etc.

label-range Consists of two line labels of the form .LA and .LB. These can either be standard
labels such as .ZF And .ZL or user-defined edit labels. The characters after the
point may be just letters.

linenum-range Two integer variable or constant that designate a start and an end line for an
operation.

lptr col Integers that contain a line number and a column number.

lptr-range Two integers that specify the first and last line for an operation.

string Text that does not have to be enclosed in quotation marks.


14.4 TEST AIDS IN THE CREATING MACROS
In this chapter, I will introduce the test facilities that can be used in the creation
of edit macros.

14.4.1 Prototyping
Unfortunately, there is no macro recorder for the ISPF editor available. I
recommend the edit commands, before you use them it in a REXX program to
test them by manually entering in the editor. Therefore, you should prototype
commands after you have seen that the result is right, gather in a second data
set using the clipboard, and then you can create the edit macro from this
collection.

14.4.2 The REXX TRACE command as developing aid


The undoubtedly most useful support facility in the creation of edit macro is the
TRACE facility of REXX language. Here, mainly the variation of the TRACE
command with the ?i option is helpful because it provides the complete
development of contents of variables when executing a REXX command. By
specifying ? you have instructed the REXX interpreter to stop after each
command. This results in the ability to entering commands manually at this
point. E.g. to display contents of any variables using the SAY command.

Example:
The following sample macro determines some values using macro commands.
I inserted trace ?i at the beginning. Thus, the development of the variable is
displayed and the macro stops after each command. I entered SAY commands
to display contents of variables at the stop points.

Program 14.3:#TT1 – Using the TRACE command in the macro


development
Here is the run of the macro. I have entered by hand (in gray) at some stops
further macro commands. Of course, you can also enter any other REXX
command there.

I entered the shaded commands by hand each time when the TRACE stops. As
you can see, the echo print of the REXX commands contain the REXX source line
number.
14.4.3 The program ISREMSPY
During run of the macro, you can use the program ISREMSPY to look at the data
currently being edited at this time. This program is a purely formal TSO
program. Therefore, it must be run under ADDRESS TSO. It can only be used
within an edit session or during the execution of edit macros. To demonstrate
the application of this program, I wrote the following small macro.
Program 14.4: Example program for using the macro testing aid ISREMSPY

I called this macro in the edit session of the data set displayed on the following
screen. On the pages thereafter, you will find the generated screens on each call
of ISREMSPY.

I received the following displays successively during the execution of the


macro. The program ISREMSPY inserted the shaded lines. You can see that
these panels are provided by ISREMSPY program. I left each these ads with PF3.
14.5 SYSTEM VARIABLES OF THE ISPF EDITOR
The system variables of the editor are valuable especially when creating an edit
macro. The name of these variables is always preceded by a point. They can be
used in the source code of the macro because they are actually line labels of the
data currently being edited. I put these variables together in the following table:
Table 14.3: System variables of the ISPF editor

Name Content

.ZCSR Contains the line number where the cursor is currently located.

.ZFIRST Contains the line number of the first row of the data currently being edited. You can
abbreviate it with .ZF.

.ZLAST Contains the line number of the last row of the data currently being edited. You can
abbreviate it with .ZL.

14.6PASSING PARAMETERS TO MACROS


If call parameters should be passed to a macro, you have to define the MACRO
command with a parameter list.

Format:
MACRO (parm1,parm2,..)

The variable names in macro parameters must not be longer than eight
characters. parml and parm2 are variables that must be known in the calling
REXX program.

Example:
The edit macro #ALTXT of the SMART ISPF utilities requires two or four
parameters.
Program 14.5: #ALTXT – Use of parameter passing to edit macros
The Help panel of this edit macro:

14.7 EXAMPLES FOR EDITING AND SUBMIT


BATCH JOBS
Edit macros are often used to assemble and SUBMIT batch jobs. The SMART
ISPF utilities contain three such macros:
Table 14.4: Edit macros of SMART ISPF utilities to assemble and submit
batch jobs
#ISPFB Edit macro to submit a batch job to execute the REXX procedure currently being edited
within an ISPF environment.

#TSOB Edit macro to submit a batch job that executes the REXX procedure currently being edited
within a TSO environment.

#SU Submit a JCL containing no JOB statement.

Advice:
Please look at these edit macros. Everything is included there. You need to
create and SUBMIT batch jobs using edit macros.

14.8 MNEMONICS FOR MACRO PROGRAMMING


–If you do not yet have extensive experience in programming macros,
remember to develop the complex statements by previous manual testing in an
edit session.
–Use for testing the macros the REXX TRACE mechanism and the test program
ISREMSPY. See section 14.4.3 The program ISREMSPY on page 249.
–Use the advantage the EXCLUDE statement offers. Most macro commands can
be applied on both, the excludet lines (using the option X) as well as on
the visible lines (using the option NX).
–If a command sequence does not have the desired success, perhaps it may be
that the cursor is incorrectly positioned. This problem can be usually solved by
examining the incorrect place of the cursor with a TRACE ?i pass and
determining the position of the cursor manually as follows:
“ISREDIT (L1,C1) = CURSOR”
SAY L1 C1

14 Edit macros – Create and apply


In this chapter, you will learn how you create and use edit macros. With edit
macros will recurring tasks are performed quickly and elegantly. To get the full
benefit of the ISPF editor, edit macros in my opinion are indispensable.
We have already extensively worked in the first part of this book on the
operation of the ISPF editor; therefore, we now want get to know another very
interesting part of the ISPF editor. There are many activities in ISPF where a
certain automation may be helpful. These are, for example, the preparation and
the SUBMIT batch jobs, the edit output lists, etc.
For such tasks, the use of edit macro is a very nice aid. This recurring work can
be always greatly accelerated and facilitated. The SMART ISPF
utilities contains a series of such useful macros. In the literature collection for
ISPF there is a brochure in which next to the description of the manual
operation of the editor, also the creation of edit macro is described.

This brochure is ISPF Edit and Edit Macros.

14.1 WHAT IS AN EDIT MACRO?


An edit macro is a REXX procedure that contains special commands for the ISPF
editor beside the REXX commands. These edit commands are passed to the ISPF
editor to run under the ADDRESS label ISREDIT. Of course, in an edit macro, all
other commands are possible, which can occur in REXX procedures.

Edit macros can be executed as follows:


–Enter in the command line of ISPF editor the name of the edit macro
procedure. This is the normal way to execute edit macro.
–Use the command EDIT DATASET(dsn) MACRO(name) in a REXX procedure.
–Define initial and/or end macros for editing data.

14.1.1 Naming conventions for edit macros


The name of an edit macro must only correspond to those of REXX procedures.
However, I have found in the course of my work in the ISPF that it may be well
of advantage to use a naming convention for the edit macros. The advantage is
that you can distinguish them from the rest of REXX procedures. I always start
the name of my edit macro with the # character. This has the advantage that the
names of my edit macro stand on the top in the REXX procedures data set
directory consecutively. Even if I look for a template for a new edit macro, I
need only look up the members that start with #. In addition, it is abundantly
clear that you can never call an edit macro like a normal procedure. The
commands that are addressed to the editor are only executable when the REXX
procedure runs under control of the editor.
If an edit macro is called from within a REXX procedure using the EDIT
command, I call it up the same way as calling the REXX procedure by prefixing
the procedure name with the # character.
14.1.2 Example of two very useful edit macros
Before we go into the details of programming edit macros, I want to show you
a simple example what an edit macro can supply.

The first macro #SSS


The SMART ISPF utilities contain the program SSS. SSS stands
for Smart Super Search. This program uses the standard ISPF
program ISRSUPC to perform the search. This program produces a list output.
This list is very elaborate. It contains many needless lines. I have therefore
written an edit macro, which removes all unnecessary texts from this list.
According to the naming conventions mentioned above, the name of the macro
is #SSS.

The second macro #SSSCH


When the editor displays the resulting list of the search, you can change some
lines in this list. If you then call the macro #SSSCH, the lines currently being
edited replace the lines in the members. Using this technique, you can perform
mass changes in all members of a PDS very easy and very quickly.

The program SSS works as follows:


1The program SSS is called by entering SSS in front of a DSN in a DSLIST display
panel. The search will be performed for all members of this partitioned data set.
2The program then displays a panel, which is designed to enter the search
arguments.
3After pressing ENTER, the program calls ISRSUPC and the search starts. The
program ISRSUPC writes the search results in a temporary sequential data set.
4The ISPF editor is called in the REXX program using the following
statement “EDIT DATAID(“UTID”) MACRO(#SSS)” The DATAID UTID was
established by a LMINIT command earlier in the program.
5The macro #SSS removes all needless lines from the data set before the list is
displayed.

Example for using of both above mentioned macros:


Task: I would like to know in which programs of the SMART ISPF utilities the
ISPF service QUERYENQ is used.
Step 1:
I enter SSS in front of the PDS where the SMART ISPF utility programs are
located. The following panel will displayed. In the field 1. = I enter the search
text QUERYENQ.

Screen 14.1: Panel SSSP1 for entering search arguments

When enter is pressed, the search will performed and the following edit panel
is displayed:

Screen 14.2: Resulting panel after executing a SSS search


The program ISRSUPC produces a list with LRECL=133. Therefore, the lines of
this display are cut off on the right side. To see what lines by the macro #SSS
were removed, here is the origin output of the program ISRSUPC:

Screen 14.3: Original output list of program ISRSUPC

As you can see, the list is reduced from 33 lines to 17 lines.

Step 2:
As you can see in line 487 of the program SLE, the word Paramter is wrong. I
will now correct this error. First, I remove all unneeded lines and correct the
wrong word to Parameter. Then the following edit panel remains:
I enter #SSSCH in the command line and press enter. The following display
appears:

What shall the macro #SSS do with the list produced by ISRSUPC?
–Remove any blank lines.
–Remove all lines that start with the following texts: ISRSUPC, PROCESS
OPTIONS USED, THE FOLLOWING PROCESS.
–Shift the lines where the name of the text SEARCH DNS: scanned data set
appears together with the DSN as far to the left that the DSN text starts at
column one.
–Remove the lines that begin with LINES-FOUND together with the next line.
–At the beginning of the revised text put a notice that this data set has been
optimized by macro #SSS.
–Inserting a row by pointing out that using the edit macros #SSSCH, the edited
and possibly changed lines can be written back to the members.

Here the source codes of both macros:


Program 14.1: Edit macro #SSS
Program 14.2: Edit macro #SSSCH
Conclusion:
With the program SSS of the SMART ISPF utilities and its edit macros, you have
a very strong tool for searching and changing mass data. Additionally, these two
edit macros are well suited to explain the using of edit macros.
14.2 TABLE OF EDIT MACRO COMMANDS
Edit macro command types:
The edit macro commands are generally divided into two types:

First type: editor action command:

“CURSOR = line col”.

This command positions the cursor on line line and column col in the edited
data.

Second type: assignment commands


This commands set values into variables:

“(line,col) = cursor”.

The variable line contains the cursor position of the current line and the
variable col the column in the line of the data currently being edited.
As you can see in the following table, many edit macro commands offer both
possibilities.
The following table is a condensed summary of the main edit macro commands
as can be used in a REXX procedure. Of course, the IBM brochure Edit and edit
Macros also contains a description of the edit macro commands. However, this
is presented in a very confusing manner. Incidentally, this is one of the reasons
why this book has been written. Therefore, I make an effort to present the
reader a focused summary in the following table.
Table 14.1: Edit macro commands
14.3 OPERANDS AND ABBREVIATIONS USED IN
THE EDIT MACRO COMMANDS
To help you work with the macro commands as listed in the table above, please
find below a brief description of those operands and abbreviations that are not
always self-explanatory by their name:
Table 14.2: Operands and abbreviations of edit macro commands

Operands Meaning

(var1,var2,..) Here are some variables specified, depending on the function.

(var) The name of a variable must be specified. This name must be not longer than 8
characters. If the (var) is on an assignment statement on the left side, the editor
stores into the variable a value. If (var) is on the right side in an assignment
statement, the REXX program must have been previously stored a value into the
variable.

[FIRST] A search for the first or last occurrence of the text is performed in the data
[LAST] currently being edited.
[NEXT] Starts at the current cursor location and performs the operation forward [NEXT]
[PREV] or backward [PREV] in the data currently being edited.

[PREFIX] The specified text is used in the search as a prefix or suffix.


[SUFFIX]

[x] [nx] The operation in question is performed only for EXCLUDED lines (x) or the NOT
EXCLUDED lines (nx).

ALL This operation will affect all lines of the data currently being edited.

amt amt defines the relative number of elements in shift or jump operations. (amt =
amount)

col-1 col-2 Two integers, which limits an operation on the designated columns.

col1 col2

data Denotes a text enclosed in quotes.

labelname Name of a labeled line. e.g. .AA, .XY etc.

label-range Consists of two line labels of the form .LA and .LB. These can either be standard
labels such as .ZF And .ZL or user-defined edit labels. The characters after the
point may be just letters.

linenum-range Two integer variable or constant that designate a start and an end line for an
operation.

lptr col Integers that contain a line number and a column number.

lptr-range Two integers that specify the first and last line for an operation.

string Text that does not have to be enclosed in quotation marks.


14.4 TEST AIDS IN THE CREATING MACROS
In this chapter, I will introduce the test facilities that can be used in the creation
of edit macros.

14.4.1 Prototyping
Unfortunately, there is no macro recorder for the ISPF editor available. I
recommend the edit commands, before you use them it in a REXX program to
test them by manually entering in the editor. Therefore, you should prototype
commands after you have seen that the result is right, gather in a second data
set using the clipboard, and then you can create the edit macro from this
collection.

14.4.2 The REXX TRACE command as developing aid


The undoubtedly most useful support facility in the creation of edit macro is the
TRACE facility of REXX language. Here, mainly the variation of the TRACE
command with the ?i option is helpful because it provides the complete
development of contents of variables when executing a REXX command. By
specifying ? you have instructed the REXX interpreter to stop after each
command. This results in the ability to entering commands manually at this
point. E.g. to display contents of any variables using the SAY command.

Example:
The following sample macro determines some values using macro commands.
I inserted trace ?i at the beginning. Thus, the development of the variable is
displayed and the macro stops after each command. I entered SAY commands
to display contents of variables at the stop points.

Program 14.3: #TT1 – Using the TRACE command in the macro


development
Here is the run of the macro. I have entered by hand (in gray) at some stops
further macro commands. Of course, you can also enter any other REXX
command there.

I entered the shaded commands by hand each time when the TRACE stops. As
you can see, the echo print of the REXX commands contain the REXX source line
number.
14.4.3 The program ISREMSPY
During run of the macro, you can use the program ISREMSPY to look at the data
currently being edited at this time. This program is a purely formal TSO
program. Therefore, it must be run under ADDRESS TSO. It can only be used
within an edit session or during the execution of edit macros. To demonstrate
the application of this program, I wrote the following small macro.
Program 14.4: Example program for using the macro testing aid ISREMSPY

I called this macro in the edit session of the data set displayed on the following
screen. On the pages thereafter, you will find the generated screens on each call
of ISREMSPY.

I received the following displays successively during the execution of the


macro. The program ISREMSPY inserted the shaded lines. You can see that
these panels are provided by ISREMSPY program. I left each these ads with PF3.
14.5 SYSTEM VARIABLES OF THE ISPF EDITOR
The system variables of the editor are valuable especially when creating an edit
macro. The name of these variables is always preceded by a point. They can be
used in the source code of the macro because they are actually line labels of the
data currently being edited. I put these variables together in the following table:
Table 14.3: System variables of the ISPF editor

Name Content

.ZCSR Contains the line number where the cursor is currently located.

.ZFIRST Contains the line number of the first row of the data currently being edited. You can
abbreviate it with .ZF.

.ZLAST Contains the line number of the last row of the data currently being edited. You can
abbreviate it with .ZL.

14.6PASSING PARAMETERS TO MACROS


If call parameters should be passed to a macro, you have to define the MACRO
command with a parameter list.

Format:
MACRO (parm1,parm2,..)

The variable names in macro parameters must not be longer than eight
characters. parml and parm2 are variables that must be known in the calling
REXX program.

Example:
The edit macro #ALTXT of the SMART ISPF utilities requires two or four
parameters.
Program 14.5: #ALTXT – Use of parameter passing to edit macros
The Help panel of this edit macro:

14.7 EXAMPLES FOR EDITING AND SUBMIT


BATCH JOBS
Edit macros are often used to assemble and SUBMIT batch jobs. The SMART
ISPF utilities contain three such macros:
Table 14.4: Edit macros of SMART ISPF utilities to assemble and submit
batch jobs
#ISPFB Edit macro to submit a batch job to execute the REXX procedure currently being edited
within an ISPF environment.

#TSOB Edit macro to submit a batch job that executes the REXX procedure currently being edited
within a TSO environment.

#SU Submit a JCL containing no JOB statement.

Advice:
Please look at these edit macros. Everything is included there. You need to
create and SUBMIT batch jobs using edit macros.

14.8 MNEMONICS FOR MACRO PROGRAMMING


–If you do not yet have extensive experience in programming macros,
remember to develop the complex statements by previous manual testing in an
edit session.
–Use for testing the macros the REXX TRACE mechanism and the test program
ISREMSPY. See section 14.4.3 The program ISREMSPY on page 249.
–Use the advantage the EXCLUDE statement offers. Most macro commands can
be applied on both, the excludet lines (using the option X) as well as on
the visible lines (using the option NX).
–If a command sequence does not have the desired success, perhaps it may be
that the cursor is incorrectly positioned. This problem can be usually solved by
examining the incorrect place of the cursor with a TRACE ?i pass and
determining the position of the cursor manually as follows:
“ISREDIT (L1,C1) = CURSOR”
SAY L1 C1

15 The SMART ISPF utilities


Since the early 1980ies, I have been working with ISPF. Over the time, I often
missed some practical functions in ISPF. In the early 1980ies, no internet was
available. Therefore, it was very difficult to find appropriate functions to fulfil
my needs. In this situation, I began to develop these functions from time to time
myself. Now a whole series of programs have accumulated that I use in my daily
work in ISPF. They are all REXX programs in which I very often use the
functions provided by ISPF. Often there are functions consisting of one program
only. Sometimes it happens, however, that in order to fulfill the functions, more
programs have to work together. Although there are many utilities for ISPF
available on the internet, I think that my programs so far are still unique.
In my two books on Smart Practices for ISPF, I make the SMART ISPF utilities
available for you to download, so that these utilities provide good services.

15.1 NAMING CONVENTIONS


All programs are written in REXX language. There are generally two types of
programs:

Edit macros:
These program names all begin with character # (hash). Using these names
rule, the macros are easily distinguishable from the other programs.

Direct executable:
These program names all begin with character S (stands for smart).

15.2 THE DYNAMIC PANEL CONCEPT


All panels of SMART ISPF utilities are embedded in the programs REXX code
and are automatically loaded in a temporary ISPPLIB of DD Name $$DYNPAN
when a program executes.
This technique has the advantage that you do not need a separate ISPPLIB
version of ISPF panels to run SMART ISPF utilities. Another advantage of this
procedure is that REXX programs using ISPF panels are easily distributable
because the simultaneous distribution of a panel data set is not necessary.
The following excerpt from a program of the SMART ISPF utilities shows the
part where the decision is made to load the panels:

To decide whether the panels are to be loaded dynamically, the variable


DYNPAN from the ISPF profile will be read in. The program SPROFVAR loads
this variable together with other variables needed by some SMART utility
programs.
Urgent recommendation:
Before you can use the SMART ISPF utilities, you must edit the program
SPROFVAR, the values contained therein, customize them and run the edit
macro ##. This edit macro is executable without having to load the ISPF profile
variables for the SMART ISPF utilities. See the following excerpt from program
SPROFVAR:

See also the description of the installation process on page 286.

15.3 LIST OF EXECUTABLE PROGRAMS


The following table shows all programs and their functions:
Table 15.1: List of the SMART ISPF utilities programs

Name Usage Description

## stand Edit macro to execute a currently edited REXX procedure


alone immediately.

#ALTXT stand Realign documentation texts within given borders.


alone

#EDMEM stand Edit a member which name is the first word in a line of a data currently
alone being edited.

#IMACROA assist SLE General ISPF edit macro. Automatically executed by ISPF when an edit
session starts even if no initial macro is set for the data set currently
being edited.

#IMACRO1 assist Initial macro to insert DOC: lines into a data set, which is called for
SDOC editing.

#IMACRO2 assist SLE This macro inserts the DSN of an edited data set into the table
$SLETAB.
#ISPFB stand Edit macro to submit a batch job to execute the REXX procedure
alone currently being edited within an ISPF environment.

#LCH stand Offers the possibility to perform an edit change command with a long
alone parameter list.

#SSS assist SSS Purges unnecessary parts of a SRCHFOR list.

#SSSCH assist SSS This macro can be used when a super search list currently being edited
to restore the displayed lines back into the members in which the
searched lines were found.

#SPLJ stand This macro performs SPLIT and JOIN operations within an edit
alone session.

#SU stand Submit a JCL that does not contain a JOB statement.
alone

#TSOB stand Edit macro to submit a batch job that executes the currently edited
alone REXX procedure within a TSO environment.

#VERASE stand Erase an ISPF variable from the profile and the shared pool.
alone

SCURSOR stand Access to a data set by EDIT, VIEW, BROWSE, MEMLIST or DSINFO.
alone The DSN must appear on an ISPF panel.

SDOC stand This program reads all members of a PDS and produces the $DOC
alone member in the same PDS.

SHOSTPAC stand This macro grabs all members of a PDS and saves the result under the
alone name of the data sets LLQ in the same PDS.

SHOSTUNP stand Unpack a packed member coming as an upload from a PC which was
alone originally packed at a z/OS by the REXX program SHOSTPAC.

SICMD stand Maintaining ISPF command tables.


alone
SIDCAMS stand Produce an IDCAMS LISTCAT of a data set and browse the list. Call in
alone front of a DSN in a DSLIST display.

SJOBSUFF function Provide job suffix character for dynamic job assembly.

SLE stand Display recently edited data sets.


alone

SLIBOFF stand Reset a LIBDEF.


alone

SLISTC stand Produce an IDCAMS LISTCAT of a data set and browse the list. Call in
alone front of a DSN in a DSLIST display.

SLISTRAC stand Produce a RACF LISTDSD of a data set and browse the list. Call in
alone front of a DSN in a DSLIST display.

SLOGON stand SMART user logon procedure.


alone

SPROFEDT stand Execute program SPROFVAR to store users ISPF profile environment
alone variables into ISPF profile.

SPROFVAR stand Store the user’s environment variables into ISPF profile.
alone

SSC stand SMART super clone function for data sets.


alone

SSC01 assist SSC Messages for panel SSCPP01 called by function SSC.

SSS stand Perform a super-search operation by entering SSS in front of a DSN in


alone a DSLIST panel.

15.4 PROGRAM DESCRIPTIONS


This chapter contains individual descriptions of the programs of SMART ISPF
utilities. Most programs include extensive help descriptions displayable using
the PF1 key. When calling up some programs, a question mark can be entered
as parameter. In this case, the program will not run with its functionality. It will
only display a description of its functions in a help panel. The following
description of the programs points out the possibility of displaying a help panel
using a question mark. Therefore, the following description of the programs is
only a short one to show the basic function.

15.4.1 Edit macro ## – Execute a currently edited REXX procedure


Edit macro to execute a currently edited REXX procedure. After
typing ##, enter a parameter string which is transferred to the REXX program
for execution. This program is executable without having to load the ISPF
profile variables for the SMART ISPF utilities. Help display with ## ?

15.4.2 Edit macro #ALTXT – Realign line parts


Edit macro to realign line parts within given columns. Help display
with #ALTXT ?

15.4.3 Edit macro #EDMEM – Edit of a member


Edit of a member which name is the first word in a line of a data set currently
being edited.

Description:
The edited list can come from following sources:
–A list output of the procedure SSS and processed by the #SSS macro.
–A list output produced by ISPF function SRCHFOR in the resulting display list.
–The member $DOC from a PDS.

At call, the cursor must be in a line in which the member name occurs as first
word. No further help available.
Note:
For an optimal use of this macro, its call should be set on a PF key. E.g. PF22.

15.4.4 Edit macro #IMACROA – General ISPF edit macro


General ISPF edit macro. Whenever you start an edit session, this macro will
execute, regardless of whether an initial macro is defined for this data set or
not.
Activating of this macro:
1. Start an edit session in an ISPF environment.
2. Enter in line command = = = > EDITSET or EDSET
3. Make the necessary entries in the appearing panel. See following panel:

No further help available.


Screen 15.1: Set activation of #IMACROA

15.4.5 Edit macro #IMACRO1 – Initial edit macro


Initial macro to insert DOC: lines into edited members of partitioned data sets
(PDS).
When starting an edit session of a PDS member and no DOC lines are found in
the edited member within the first 20 lines, this macro then displays a panel
that offers the opportunity to insert DOC lines at the beginning of the member
currently being edited.
Help can be displayed via PF1 when the panel IMACRO11 appears. The
following screen shows an example for inserting DOC and REM lines into a
member.
Screen 15.2: Panel IMACRO11 for edit macro #IMACRO1
The greyed fields show the standard options inserted here by #IMACRO1
depending on LLQ. These options are changeable. The following screen shows
the resulting contents of the new member after ENTER is pressed:

15.4.6 Edit macro #IMACRO2 – Edit session end macro


This macro inserts the DSN of an edited data set into the table $SLETAB. This
macro is executed when an edit session ends in which the macro #IMACRO1
was executed. No further help available.

15.4.7 Edit macro #ISPFB – Submit an ISPF batch job


Edit macro to submit a batch job to execute the REXX procedure currently
being edited within an ISPF environment. When the macro is called, a
parameter text can be added in the call statement. This text is as a parameter
transferred to the executed REXX procedure. Help display with #ISPFB ?
15.4.8 Edit macro #LCH – Perform long edit change commands
Perform edit change with long parameter texts.

Function:
When the "Command = = = >" line in the normal edit panel is too short to contain
the whole CHANGE command, you can use this program to solve the problem.
This program opens a panel for input of two lines each with max 70 characters.
The first line is the SEARCH argument for the change and the second line is the
replacement value. Additionally, you can enter parameters for the CHANGE in
a third line. E.g. 1, ALL, WORD...

15.4.9 Edit macro #SPLJ – SPLIT and JOIN lines


This macro performs SPLIT and JOIN operations within an edit session.

Functional description:
When this macro is called, further processing of the position of the cursor
depends on the following:
1.If the cursor is within a line and after this position, characters are on the line,
these characters are moved to a new line after the current one. This is the split
function.
2.If after the position of the cursor only blanks are on the line, the line after the
current line moves to the current line after the cursors position. This is the join
function.

There is no other help available.

15.4.10 Edit macro #SSS – Clear SCHFOR lists


Remove unnecessary parts from SCHFOR list.

Functional description:
Delete all unnecessary lines from a list produced by the Super Search Function
of ISPF. The procedure SSS calls this macro as initial macro. If you have
performed a manual search, you can also use this macro to revise the list output.
There is no other help available.
15.4.11 Edit macro #SSSCH – Mass update of members
This macro offers a very smart functionality:
When you have performed a super search and you make some changes in the
edited list, you can write back the displayed lines completely to its members.
With this possibility, you can perform mass changes on many members in one
step.

Purpose:
This macro can be used, when a super search list is displayed in edit session, to
restore the displayed lines back into the members in which the searched lines
were found. There is no other help available.
Remarks:
You can remove rows and members from the data set currently being edited. If
you delete a member, all lines belonging to this member must also be deleted
bulky. New rows cannot be inserted because the row numbers which are
included in the displayed list, contain the relative position of these lines in the
member. These line numbers will be used when the lines are written back to
the member. The existing lines with the same number will be overwritten. If
you do not want to write back changes in individual lines, you can of course
delete these lines before calling #SSSCH.

15.4.12 Edit macro #SU – Submit JCL without a JOB statement


Submit a JCL that does not contain a JOB statement. Parameters: MSGLEVEL in
the form: 0,0 / 1,0 / 2,0 / 0,1 / 1,1 / 2,1. This MSGLEVEL is in the JOB statement
set.

Function description:
The program assembles the job statement using user-defined variables from
ISPF profile pool. Use the program SPROFVAR to store these variables into the
ISPF profile pool.

#SU is usable at the following positions:


–As an edit macro.
–In front of a member in a DSLIST/M display.

Special function:
EXCLUDED lines of the edited data set are NOT inserted in the submitted job
stream.
Attention:
Due to using the TSO SUBMIT command, all lines of the edited data set are
translated to UPPER CASE during SUBMIT. This is a regular effect of SUBMIT.
Author's remark:
During my years of consultant activity, I always had all my job statements
adapted to varying conditions in the data centers. To have to not always do this,
I developed the REXX program SPROFVAR. There, I have all the values that
apply to a data center inserted as variables and stored them in the ISPF profile.
When I installed the SMART ISPF utilities at a new customer, I adapted and
executed only the member SPROFVAR. In all the jobs I had to run at the
customer's site, I was able to leave the job statement and start jobs with #SU.

No further help available.

15.4.13 Edit macro #TSOB – Submit a TSO batch job


Edit macro to submit a batch job which executes the REXX procedure currently
being edited within a TSO batch environment. A parameter text can be added
to the macro call. This text is transferred to the executed REXX procedure.

Attention:
This macro does not save the source code of the data set currently being edited.
Hence, the UNDO status of the edit session is not changed by this macro.

Remarks:
To avoid the SAVE command, the currently edited REXX procedure is stored to
a work data set. The batch job will use this work data set to execute the REXX
procedure. The description of the 'SUBMIT *' command in the manual TSO/E
Command Reference contains the following note: The SUBMIT command
converts all characters of the job stream to uppercase before the stream is
submitted to the system.
Note:
To avoid setting all JCL lines in uppercase by command SUBMIT * and thus also
the line which contains the parameter text, this procedure writes the job stream
to member JOB into a work data set and submits the job from this member by
using the command: "SUBMIT '"workfile"(JOB)'". In this case, the lines of the
member JOB will not be transferred to uppercase.

Help is available with #TSOB ?


15.4.14 Edit macro #VERASE – Erase ISPF profile variables
With this edit macro, you can delete an ISPF variable from the profile and the
shared pool. At call, you can enter only one variable name.

15.4.15 Program SCURSOR – Calling a data set from an ISPF screen


With this program you can call a data set which name is somewhere in an ISPF
screen. When calling, a small panel appears which allows you to select the type
of file processing.

Description:
If a DSN of a data set appears on any ISPF screen, you can get access to this data
set by positioning the cursor within the DSN and call SCURSOR. For a
comfortable use of this function, I recommend to program a PF KEY with TSO
%SCURSOR. If you have positioned the cursor at any position within a DSN and
then pushed the PF key a panel appears to offer a range of access possibilities
to the data set. There are some restrictions for displaying GDGs and VSAM data
sets.

This function can be used in many displays. Some examples:


–In an EDIT panel
–In a BROWSE panel
–In the SDSF display
–In a data set display
–In a POPUP panel

See the selection panel below:


Screen 15.3: SCURSOR selection panel
15.4.16 Program SDOC – Produce documentation members
This program reads all members of a PDS and produces the $DOC member in
the same PDS.

Function:
The program scans all members of the PDS for lines with keyword DOC: as the
second word in a line. Only the first 200 lines in each member will be scanned.
When during this scan no DOC: lines are found, then only the member name will
be stored in the output. When the first DOC: line is found and there are more
than five lines following the last found DOC: line without a DOC: the scan of this
member ends.

15.4.17 Program SLE – Display last edited data sets


Purpose:
The program starts by input of SLE in the ISPF command line. It displays an
ISPF table containing names of recently edited data sets. The program displays
the ISPF table $SLETAB. The EDIT initial macro #IMACRO2 updates this table
with DSNs of recently edited data sets. The display panel offers the ability to
perform some functions on the data sets displayed. See the help panels
available in the programs screen. Smart Last Edit offers the following
functions:
Screentext 15.1: Description of SLE functionality

The following screen shows the above-mentioned input fields:


Screen 15.4: SLE working panel

Remark:
Help screens are available for all greyed fields. Position the cursor in such a field
and press PF1 to display the help. The general help screen appears, when the
cursor is on any other position on the screen and PF1 is pressed.
Tip:
Insert the following command in the ISPF command table to call the last edit
function very fast when you type in SL in the ISPF command line.
_ SLE 2 SELECT CMD(%SLE)
REXX SLE CALL THE LAST EDIT FUNCTION

15.4.18 SLOGDSN – Data member containing DSNs for logon


The member SLOGDSN contains DD names and the corresponding DSNs. The
logon procedure SLOGON reads this member, looks for the already existing
allocations by the same DDs and assembles a new structure in which the
members referred to in SLOGDSN DSNs are respectively arranged in front of
the existing DSNs of each affected DD. The program SLOGON then allocates
this new structure using the REUSE option. This technique ensures that the
DSNs specified by the user allocates in the member SLOGDSN BEFORE the
previously existing DSNs in each affected DSN chain. DDs that are not found in
the existing allocations will additionally allocated.
Program 15.1: Member SLOGDSN
15.4.19 Program SLOGON – Personal logon procedure
This is a personal logon procedure. It works as follows:
1.It reads all existing allocations of the TSO user and caches them.
2.It reads the control member SLOGDSN containing the DSNs that must
allocated before the already existing DSNs. The new DSN chains are assembled
in such a way that the DSNs read from the member SLOGDSN stay before the
existing DSNs.
3.When in the member SLOGDSN new DDs and their DSNs are contained that
are not present in the previous allocations, these chains will be added to the
allocation stream.
4.SLOGON now performs the new allocations using the new allocation stream
and the TSO ALLOC option REUSE. The REUSE option replaces the old
allocations.

For installing this logon procedure, see section 15.6.2 Installation on page 286.
Note:
If SLOGDSN contains DSNs of not existing data sets, a warning message is
displayed during SLOGON, but the logon process continues anyway. This
ensures that the logon process is successfully performed and a working user
environment is created. This is a very important advantage of the
procedure SLOGON.

15.4.20 Program SPROFEDT – Store users ISPF profile variables


Execute program SPROFVAR to store users ISPF profile environment variables
into ISPF Profile. This program is called by ISPF command SPROFVAR.

15.4.21 SPROFVAR – Load user ISPF variables


SPROFVAR defines and stores variables needed by the SMART ISPF utilities in
the ISPF profile pool. Several SMART utility programs use these profile
variables. The PF keys are also set. Each user can add his own profile variables
as needed!

15.4.22 Program SSC – Super clone for data sets Purpose:


This program uses a model data set to perform some functions on this data set
or to create a new data set based on the model data set.

Smart Super Clone offers the following functions:


–Allocate a new data set with the same or different attributes as the model data
set has with optionally copying the data.
–Restructure the model data set. Some attributes may be changed.
–Copy the model data set into another data set. The target data set must exist.
During this operation, the data set attributes cannot be changed.
–The source data set can be a PDS and the target data set can be sequential. In
this case, the program continuously writes the members into the sequential
data set.
–Only the following data set types can be processed with this program:
Generally data sets on DASD and Sequential, PDS, PDSE and VSAM.
Note:
A sequential data set cannot be copied into a PDS member.
Screen 15.5: SSC working screen
Remark:
Help screens are available for all greyed fields. Position the cursor in such a field
and press PF1 to display the help. The general help screen appears when the
cursor is on any other position on the screen when PF1 is pressed.

15.4.23 Program SSS – Perform a Super-Search


Purpose:
Perform a Super-Search operation by entering SSS in front of a DSN in a DSLIST
panel.
Two types of calling SSS (Smart Super Search) are available:
–Enter SSS <search string> in a line in front of a DSN on a DSLIST panel. The
search operation then performs with only one string. Enter the search string
without quotes and it can only consist of one word.
–Enter SSS in front of a DSN on a DSLIST panel. In this case, the panel SSSP1
appears. This panel allows the input of many search terms.
Screen 15.6: SSS input panel
Remarks:
–The program SSS calls the ISPF standard super search utility ISRSUPC to
perform the search.
–The standard ISPF help facility for super search appears when PF1 is pressed
on the SSS screen.
–SSS saves the entered search parameters in lines 1 to 10 automatically in the
ISPF profile and redisplays them at the next call of SSS.
–The edit macro #SSS removes unnecessary output contents from the standard
output list of the search before the list appears on the screen. The macro #SSS
is indicated as initial macro when the editor is invoked for displaying the search
results.
SSS special update function:
SSS stores the optimized search results into a temporary data set and then
displays this data set in the editor. This data set can be edited by using the
normal editor functions. If individual lines of the data set are changed, these
changes can restored into the individual members using the edit
macro #SSSCH. See description of #SSSCH on page 264. This is one of the
most important advantages of the program SSS.

15.5 PROGRAMMING AIDS


This chapter includes program elements which are intended for programmers
who develop programs using the REXX language. The following table shows
these edit macros, programs and subroutines, which are contained in the
programming aid package.

Table 15.2: Programming aids Program Function


Program Function

#C This edit macro compiles the REXX program currently being edited and executes
the compiled program immediately after the compile. One parameter can be
added in the #c call statement. This parameter string will be passed to the
compiled program to be used at execution time. To get an online tutorial
description enter: #c ?

#RO Online compile of the REXX program currently being edited. This procedure can
be called as an edit macro or in front of a member name in a DSLIST/M display
panel. Parms: When #RO is used as a macro additional compiler options may be
passed as parameters.

#RC Use this procedure to assemble and submit a batch job to compile a REXX
procedure.

#RCLOAD Assembly and SUBMIT a job to compile a REXX procedure and generate a LOAD
module or a CALL module.

#IE Edit macro to insert in an application program the call lines to the internal
ISPF_ERROR subroutine. The inserted statements calls the ISPF error handling
subroutine ISPF_ERROR in case an error appears. See the next row in this table.

ISPFERR ISPF error handling routine This subroutine is called when a call to an ISPF
service function ends with an error.

#PAN The screen whose program code is currently being edited will be displayed
immediately.

DAYDIFF Calculates the number of days between two DATE values. DATE values are
entered in the form dd.mm.yyyy.

ENDDAY Calculates the target date for a period of days starting at a given date plus or
minus a number of days.

JULDATE This subroutine calculates for a standard date the JULDATE or vise versa.

LEAPYEAR Calculates whether the entered year is a leap year or not. This function returns a
1 if the entered year is a leap year, otherwise it returns 0. Caution: No plausibility
checking of the entered year parameter is performed.
SCHANGE This REXX subroutine performs changes in any strings. See section
4.6.3 SCHANGE – Change of texts on page 86.

SDYNPAN This program converts the source code of an ISPF panel so that the code can be
embedded in a REXX procedure to be dynamically loaded from there into a
temporary ISPPLIB for execution.

15.5.1 Edit macro #C – Compile and execute a REXX program


If the REXX compiler is available in your installation of z/OS systems, you can
use this macro to compile your REXX programs very easily.

Program description:
Edit macro #c:

Edit macro to compile and execute the REXX procedure currently being edited.
After the characters #c you can enter a string, which will be passed as
parameter to the program for execution.

Examples:

Attention:
The entered parameter string MUST NOT contain the ISPF delimiter character.
This character is used for ISPF command stacking and your parameter will
possibly be truncated at the delimiter character position.
The ISPF delimiter character can be found in ISPF menu 0 in the line Command
delimiter.

Processing flow:
The REXX program currently being edited is written to a work data set. This
data set is used for input to the REXXCOMP program. If compilation is
successful, the CEXEC module is written to the online work data set with
DDNAME ##DD. If the ##DD data set is not allocated, it will be allocated. If the
compilation ends with a RC > 0, the compiler listing is immediately browsed.
The compiled program will be executed using the ISPF SELECT CMD service.
Remark:
Because the REXX program currently being edited is not stored to its data set
for the purpose of compilation, the UNDO command can still be used.

15.5.2 Edit macro #RO – Online compile of a REXX program


This procedure can be called as an edit macro or in front of a member name in
a DSLIST/M display panel. If called as an edit macro the following rules exist.
1. The source code currently being edited is stored into a temporary data set
and the compiler uses this data set as SYSIN file. When using this technique, the
editors save command will not be performed and the change status of the
edited file remains unchanged. Hence, the UNDO command can still be used in
the editor.
2. After #RO the user can add some additional parameters which will be
transferred to REXX compiler as compiler options.
3. If the REXX source code contains TRACE statements, the compiler produces
no XREF listing and the compilers output list will be written to a data set.

If called in front of a member name in a DSLIST/M display:


1. The compiler reads the REXX source from this member.
2. No additional compiler options may be set. This is bacause at this point
parameters cannot be added to the procedure call statement.
3. If the REXX source code contains TRACE statements, NO CEXEC output is
produced and the compile ends with an error.

The name of the output data set for the CEXEC code is set up as follows: The last
qualifier of the input DSN is substituted by CEXEC

Example:

Input DSN→ LANZ.LOGON.REXX

Output DSN→ LANZ.LOGON.CEXEC

15.5.3 Edit macro #RC – Compile a REXX procedure with a batch


job
Functional description:
Use this procedure to assemble and submit a batch job to compile a REXX
procedure. This procedure can be called as follows:
1.As an edit macro. In this case will the currently being edited REXX procedure
be saved and the batch job to compile the REXX procedure will submitted.
2.In a DSLIST/M in front of a REXX procedure member.
3.In a DSLIST/M display in the command line to compile all or a selected
number of members, e.g.: sei ab* #rc --> all members which names are
beginning with characters ab are compiled. At this type of call no
NOTIFY=userid() parameter is inserted into the JOB statement.

The name of the output data set for the CEXEC code is set up as follows: The last
qualifier of the input DSN is substituted by CEXEC

Example:

Input DSN→ LANZ.LOGON.REXX

Output DSN→ LANZ.LOGON.CEXEC

15.5.4 Edit macro #RCLOAD – Produce a load or a call module


Assembly and SUBMIT a job to compile a REXX procedure and generate a load
module or a CALL module. This procedure can only be called as edit macro.
Parms: none

Attention:
There are two things necessary in order to use this macro:
1.The REXX compiler REXXCOMP must be available in your system. You can
check this using the DDLIST utility.
2.The REXXCL jcl procedure must be available in your system. Ask your system
programming department where it is.

Two different types of load modules can be generated:


1.A load module that can be executed in a batch job using the EXEC PGM=name
statement. This type is called EXEC type. In this case the following comment line
must be found in the source code: /* STUB: MVS */
2.A load module which was added to a Function Package Lib needs to be called
with a CALL command. (CALL type). In this case the following comment line
must be found in the source code: /* STUB: EFPL */
After generating the load module of this call type, it has to be implemented in a
Function Package. See the corresponding manual TSO/E REXX Reference.
If you try to execute such a program directly, then the CALL ends with a return
code 0C4. This means the program ends with a hard crash.

Link library:
If STUB: MVS is set, a file in the source code needs to be defined to where the
load module is to be written. This load library is named by a comment line in
the source code which is structured as follows:
/* LNK: DSN of the load library */

Example:
/* LNK: PEVX.LANZ.LOAD*/

If no such row is found, then NO compile is performed.

15.5.5 Edit macro #IE – Insert a call to ISPF_ERROR


Preface:
I have been looking for a method a long time to report errors when executing
ISPF services elegantly and detailed. I think I have now found this method. This
method consists of two parts which must be inserted into each program:

First part of error handling:


After each call to an ISPF service function, the return code RC will be checked.
If this code signals an error, the error handling subroutine ISPF_ERROR will be
called. The parameters in this call statement contain all information to report
the error in detail.

After each call to an ISPF service, the following five lines of code are inserted:

The five lines must be manually inserted in the source code of a program as
follows:
1.Enter #IE in the ISPF command line or program a PF key with #IE.
2.Move the cursor to the line containing the call to an ISPF service.
3.Press enter or the appropriate PF key which contains the command #IE. The
above mentioned five lines will be inserted immediately behind the ISPF
command line.
Description of the lines:
Lines 1 and 5 contain comments and are self-explanatory.
Line Explanation

2 The RC returned by the ISPF service is passed as first parameter. Depending on the RC that
was returned by the ISPF service, a call will be executed to the error handling subroutine
ISPF_ERROR.

3 This line is passed as the second parameter to the subroutine ISPF_ERROR. It contains the
original ISPF command line without the variables contained in the command line being
resolved. This text is used by the subroutine ISPF_ERROR to find the original command line
in the source code of the program by using the REXX command SOURCELINE().

4 This line is passed to ISPF_ERROR as third parameter. It contains the original ISPF
command line with the variables contained in the command line being resolved.

These three parameters are used by the subroutine ISPF_ERRROR to print a


comprehensive error report.

Second part of error handling:


Insert the source code of the subroutine ISPF_ERROR manually into each
program that contains calls to ISPF_ERROR. This is necessary because an
externally called subroutine does not know the source code of the calling
program. Therefore, the command SOURCELINE is not applicable to determine
the line number of the line in the source code at which the error occurs.
Note:
In large programs, it can happen that a certain ISPF command line at several
points occurs with the same content. In such a case, it is important to know the
number of the program line in which the error occurred.

Example:
When using this method, errors in executing ISPF services are displayed as
follows:
I replaced in the above example the contents of the variable DATASET by the
text faked DSN to manually enforce the error. The statement where the error
occurs is in line number 284 in the source code of the program.

15.5.6 Subroutine ISPF_ERROR – Display ISPF error messages


I described above how the call to the subroutine ISPF_ERROR is performed. To
complete the method, here is the source code of the subroutine ISPF_ERROR:
Program 15.2: ISPF_ERROR subroutine
15.5.7 Edit macro #PAN – Execute a panel source code
When developing ISPF panels it is very tedious to test this using the ISPF menu
7.2. Therefore, I wrote the macro #PAN to test a panel which source code is
currently being edited. Please read the comment lines at the beginning of the
source code. It will describe how to use the macro.
Program 15.3: Edit macro #PAN to test macros directly

15.5.8 Subroutine DAYDIFF – Calculate number of days


Please see the source code to recognize the function of this subroutine.
Program 15.4: Subroutine DAYDIFF

Example:
The following call to DAYDIFF returns 365:
say daydiff(15.05.2015 15.05.2014)

15.5.9 Subroutine ENDDAY – Calculate a target date


Please see the source code to recognize the function of this subroutine.
Program 15.5: Subroutine ENDDAY

15.5.10 Subroutine JULDATE – Translate a date to Julian and vise


versa
Please see the source code to recognize the function of this subroutine.
Program 15.6: Subroutine JULDATE
15.5.11 Subroutine Return – LEAPYEAR the leap year information
Please see the source code to recognize the function of this subroutine.
Program 15.7: REXX function LEAPYEAR
15.5.12 REXX subroutine SCHANGE – REXX change function
Please see the source code to recognize the function of this subroutine.
Program 15.8: REXX subroutine SCHANGE

15.5.13 Program SDYNPAN – Convert a panel source code


To save space, I will refrain from the expressions of the entire source code. The
comment lines at the beginning of the program include a detailed description
of the function. The source code of SDYNPAN is very long. Therefore, only the
functional description of the program is inserted below.
Program 15.9: Program SDYNPAN
Remark:
I used this program to convert all panels of the SMART ISPF utilities to load
them dynamically when a program is started, which contains panels.

15.6 INSTALLATION OF SMART ISPF UTILITIES


To use the smart utilities, you must install them in your TSO/ISPF system.
Before you start transferring programs and panels, you need to make an
important decision:
Note:
The REXX procedures of the SMART ISPF utilities contain all required panel
definitions in their source code. Therefore, you do not have to transfer the
panels to your ISPPLIB. The installation program SPROFVAR that stores the
ISPF environment variables in the ISPF PROFILE POOL, contains the
variable dynpan. If you set dynpan to YES before you execute SPROFVAR, then
the REXX procedures uses imbedded panels when executed.

15.6.1 Download and unzip


Perform the following steps to install the SMART ISPF utilities:
1.Download the SMART ISPF utilities ZIP file from the DeGruyter
website www.degruyter.com.
2.Unzip the file to a folder in your PC. After unzipping, the following data sets
are in the folder:
REXX The REXX program package.
PANELS The ISPF panel package.

SHOSTUNP REXX program to unpack REXX programs and ISPF PANELS into their
libraries on z/OS host.

The two files REXX and PANELS contain all procedures and all panels of the
SMART ISPF utilities in packed form. After transferring into the appropriate
libraries on the z/OS/ system, they must be unpacked using the REXX program
SHOSTUNP. This REXX program is the only program that is usable to unpack
the data sets because the packed data sets have a proprietary format.

Upload and unpack the members to z/OS host:


1.Use the 3270 emulation software you have on your PC to upload the three
members to the z/OS host into a PDS or PDS-E with RECFM=FB and LRECL=80.
2.Then use the program SHOSTUNP to extract the packed members into the
appropriate libraries. Use the Command Shell (menu 6) of ISPF to execute the
program SHOSTUNP. The following screen shows these commands:
Screen 15.7: Examples of unpacking SMART ISPF utilities members

Note:
The last three lines in the above panel show the commands automatically
executed under TSO while the upload was running.

15.6.2 Installation
For the installation of the SMART ISPF utilities, multiple scenarios concerning
your TSO/ISPF user environment are possible:
1. You still have an own ISPF library environment with an own logon procedure.
This is the ideal case. You can copy the REXX procedures of the SMART ISPF
utilities directly into your SYSEXEC or SYSPROC library and unpack them there.
If you want to use a panel library for the panels, you can copy the panels to the
ISPPLIB chain. Additionally, you can decide whether you want to use the
SLOGON procedure of the SMART ISPF utilities together with the member
SLOGDSN to make your logon process more variable and convenient.
2. You get the TSO READY prompt when you leave ISPF.
In this case, you can call the logon procedure SLOGON at the READY PROMPT
using the command EX 'dsn(SLOGON)'. First, you must only adjust the member
SLOGDSN so that there the correct data set names are included.
3. Your TSO user is completely logged off when you leave ISPF and you have no
chance to start an own logon procedure.
In this case, you can still use the SMART ISPF utilities. However, installation of
the call environment is somewhat more complex. You can use the command
ALTLIB. While there is a restriction that makes the process somewhat
inconvenient: If you have performed an ALTLIB command, the calling
environment thus created is always only available in the logical screen in which
the ALTLIB command was executed. See the description of the ALTLIB
command below.

15.6.3 ALTLIB command


Excerpt from the IBM manual TSO-E Reference concerning ALTLIB:
Use the ALTLIB command to:
–Define alternative application-level libraries of REXX execs or CLISTs.
–Indicate that user-, application-, and system-level libraries of REXX execs and
CLISTs will be searched.
–Exclude one or more library levels (user, application, system) from being
searched.
–Reset the search order to the system level.
–Obtain a display of the search order that is in effect.

Using ALTLIB in ISPF:


When using ALTLIB when ISPF is active, you can define the libraries (user,
application, and system) that are active for each application. Libraries that you
define while running an application are in effect only while that application has
control. When the application completes, the previous libraries (user,
application, and system) will automatically be reactivated.
If you are in split-screen mode in ISPF and you issue the ALTLIB command from
a one-screen session, the changes affect only that screen session. The ALTLIB
search order is not valid across split screens.
To execute the ALTLIB command, enter the following command in an ISPF
command line:
TSO ALTLIB ACT APPLICATION(EXEC) DSNAME('dsn')

dsn is the data set where your REXX procedures reside. If you have installed
the REXX procedures of SMART ISPF utilities into this dsn, the utilities are also
executable.
Recommendation:
Program a PF key with this ALTLIB call. When you open a new logical screen in
ISPF, then you can execute the command immediately by pressing the PF key.

Example:
The following screen shows the assignment of keys PF18 and PF19 for
execution of the ALTLIB command.
Screen 15.8: PF key setting to execute ALTLIB

The command ALTLIB DISPLAY shows the current ALTLIB chain. After pressing
PF18 and then PF19, the following display appears:
I used DDLIST to find the DDNAME SYS00278 and found it in the following
screen:

Remarks concerning the ALTLIB command:


–ALTLIB commands can occur in a stacked manner.
–Only the procedures of the first level in a chain of stacked ALTLIB chains are
reachable.
–Use the command altlib deact application(exec) to remove the top level of
the chain.

Example:
I pressed PF18 four times and then I pressed PF19. The following chain
appears:

Note:
The command ALTLIB DISPLAY shows in opposition to the command ISPLIBD
only the DD names of the allocated data sets. If you want to see the
corresponding DSNs, you can view them with the utility DDLIST as shown
below.
15.6.4 Make the SMART ISPF utilities ready to run
Before you can use the SMART ISPF utilities, there are still some steps
necessary:
1.If you can fully use an own logon procedure, you must adapt the members
SLOGON and SLOGDSN and perhaps copy the procedure SLOGON into an
appropriate library. See section 15.6.2 Installation on page 286.
2.Edit the member SPROFVAR, perform the necessary changes and execute it
using the edit macro ##. This program is executable without having to load the
ISPF profile variables for the SMART ISPF utilities.

The following profile variables are important to have appropriate values:

Conclusion:
After having performed all mentioned steps above, the SMART ISPF utilities
should work fine and I wish you much success with it.

List of tables
Table 1.1: Reference books for the programming of ISPF applications
Table 1.2: ISPF service groups

Table 2.1: Arithmetic REXX operators

Table 2.2: Compare operators

Table 2.3: Logical operators

Table 3.1: REXX host command environments

Table 3.2: Table of PARSE types

Table 4.1: REXX function groups

Table 4.2: Parameters of the DATE function

Table 4.3: Options of the TIME function

Table 4.4: DATATYPE type options

Table 4.5: Description of parameters for the FORMAT function

Table 7.1: ISPF system variables concerning error messages

Table 7.2: Search sequence in the procedures libraries

Table 8.1: Grouping of LM commands necessary for a particular type of data


processing

Table 8.2: Data set query services

Table 8.3: Variables returned by the LMDLIST service

Table 8.4: DSINFO variables content

Table 8.5: LISTDSI – Variables and their contents

Table 8.6: LISTDSI – Description of reason codes

Table 8.7: Variables description of the QUERYENQ ISPF table

Table 8.8: QUERYENQ return codes

Table 10.1: Description of panel sections

Table 10.2: )ATTR definitions list

Table 11.1: Commands to create skeletons


Table 12.1: Table services commands that refer to the entire table

Table 12.2: Table service commands that relate to individual rows

Table 12.3: Components of the SLE application

Table 13.1: General ISPF system variables

Table 14.1: Edit macro commands

Table 14.2: Operands and abbreviations of edit macro commands

Table 14.3: System variables of the ISPF editor

Table 14.4: Edit macros of SMART ISPF utilities to assemble and submit batch jobs

Table 15.1: List of the SMART ISPF utilities programs

Table 15.2: Programming aids

List of screens
Screen 2.1: Example of a command call in a DSLIST display panel

Screen 4.1: Read the job name from CVT

Screen 7.1: Panel SLEP1 displayed by the program SLE

Screen 7.2: ISPF variables display using ISPF menu 7.3

Screen 7.3: ISPLIBD – Display the current active LIBDEF assignment

Screen 8.1: LMMDISP panel display

Screen 8.2: MEMLIST display

Screen 10.1: Panel SLEP1 displayed by program SLE

Screen 12.1: Display of panel SLEP1 produced by the program SLE

Screen 13.1: Members of an ISPPROF data set

Screen 13.2: List of started ISPF applications

Screen 14.1: Panel SSSP1 for entering search arguments

Screen 14.2: Resulting panel after executing a SSS search


Screen 14.3: Original output list of program ISRSUPC

Screen 15.1: Set activation of #IMACROA

Screen 15.2: Panel IMACRO11 for edit macro #IMACRO1

Screen 15.3: SCURSOR selection panel

Screen 15.4: SLE working panel

Screen 15.5: SSC working screen

Screen 15.6: SSS input panel

Screen 15.7: Examples of unpacking SMART ISPF utilities members

Screen 15.8: PF key setting to execute ALTLIB

Bibliography
This bibliography contains excerpts from some IBM manuals concerning the
z/OS TSO/ISPF complex:

TSO/E Publications
–z/OS TSO/E Administration, SA22-7780
–z/OS TSO/E CLISTs, SA22-7781
–z/OS TSO/E Command Reference, SA22-7782
–z/OS TSO/E Customization, SA22-7783
–z/OS TSO/E General Information, SA22-7784
–z/OS TSO/E Guide to SRPI, SA22-7785
–z/OS TSO/E Messages, SA22-7786
–z/OS TSO/E Primer, SA22-7787
–z/OS TSO/E Programming Guide, SA22-7788
–z/OS TSO/E Programming Services, SA22-7789
–z/OS TSO/E REXX Reference, SA22-7790
–z/OS TSO/E REXX User’s Guide, SA22-7791
–z/OS TSO/E System Programming Command Reference, SA22-7793
–z/OS TSO/E System Diagnosis: Data Areas, GA22-7792
–z/OS TSO/E User’s Guide, SA22-7794

z/OS MVS Publications


–z/OS MVS Planning: APPC/MVS Management, SA22-7599
–z/OS MVS Programming: Writing Transaction Programs for APPC/MVS, SA22-
7621
–z/OS MVS Initialization and Tuning Reference, SA22-7592
–z/OS MVS Programming: Authorized Assembler Services Guide, SA22-7608
–z/OS MVS Programming: Authorized Assembler Services Reference ALE-DYN,
SA22-7609
–z/OS MVS System Messages, Vol 1 (ABA-AOM), SA22-7631
–z/OS MVS System Messages, Vol 2 (ARC-ASA), SA22-7632
–z/OS MVS System Messages, Vol 3 (ASB-BPX), SA22-7633
–z/OS MVS System Messages, Vol 4 (CBD-DMO), SA22-7634
–z/OS MVS System Messages, Vol 5 (EDG-GFS), SA22-7635
–z/OS MVS System Messages, Vol 6 (GOS-IEA), SA22-7636
–z/OS MVS System Messages, Vol 7 (IEB-IEE), SA22-7637
–z/OS MVS System Messages, Vol 8 (IEF-IGD), SA22-7638
–z/OS MVS System Messages, Vol 9 (IGF-IWM), SA22-7639
–z/OS MVS System Messages, Vol 10 (IXC-IZP), SA22-7640
–z/OS MVS System Codes, SA22-7626

ISPF Publications
–z/OS ISPF Dialog Developer’s Guide and Reference, SC19-3619-00
–z/OS ISPF Dialog Tag Language Guide and Reference, SC19-3620-00
–z/OS ISPF Edit and Edit Macros, SC19-3621-00
–z/OS ISPF Messages and Codes, SC19-3622-00
–z/OS ISPF Reference Summary, SC19-3624-00
–z/OS ISPF Services Guide, SC19-3626-00
–z/OS ISPF User’s Guide Vol I, SC19-3627-00
–z/OS ISPF User’s Guide Vol II, SC19-3628-00

Bibliography
This bibliography contains excerpts from some IBM manuals concerning the
z/OS TSO/ISPF complex:

TSO/E Publications
–z/OS TSO/E Administration, SA22-7780
–z/OS TSO/E CLISTs, SA22-7781
–z/OS TSO/E Command Reference, SA22-7782
–z/OS TSO/E Customization, SA22-7783
–z/OS TSO/E General Information, SA22-7784
–z/OS TSO/E Guide to SRPI, SA22-7785
–z/OS TSO/E Messages, SA22-7786
–z/OS TSO/E Primer, SA22-7787
–z/OS TSO/E Programming Guide, SA22-7788
–z/OS TSO/E Programming Services, SA22-7789
–z/OS TSO/E REXX Reference, SA22-7790
–z/OS TSO/E REXX User’s Guide, SA22-7791
–z/OS TSO/E System Programming Command Reference, SA22-7793
–z/OS TSO/E System Diagnosis: Data Areas, GA22-7792
–z/OS TSO/E User’s Guide, SA22-7794

z/OS MVS Publications


–z/OS MVS Planning: APPC/MVS Management, SA22-7599
–z/OS MVS Programming: Writing Transaction Programs for APPC/MVS, SA22-
7621
–z/OS MVS Initialization and Tuning Reference, SA22-7592
–z/OS MVS Programming: Authorized Assembler Services Guide, SA22-7608
–z/OS MVS Programming: Authorized Assembler Services Reference ALE-DYN,
SA22-7609
–z/OS MVS System Messages, Vol 1 (ABA-AOM), SA22-7631
–z/OS MVS System Messages, Vol 2 (ARC-ASA), SA22-7632
–z/OS MVS System Messages, Vol 3 (ASB-BPX), SA22-7633
–z/OS MVS System Messages, Vol 4 (CBD-DMO), SA22-7634
–z/OS MVS System Messages, Vol 5 (EDG-GFS), SA22-7635
–z/OS MVS System Messages, Vol 6 (GOS-IEA), SA22-7636
–z/OS MVS System Messages, Vol 7 (IEB-IEE), SA22-7637
–z/OS MVS System Messages, Vol 8 (IEF-IGD), SA22-7638
–z/OS MVS System Messages, Vol 9 (IGF-IWM), SA22-7639
–z/OS MVS System Messages, Vol 10 (IXC-IZP), SA22-7640
–z/OS MVS System Codes, SA22-7626

ISPF Publications
–z/OS ISPF Dialog Developer’s Guide and Reference, SC19-3619-00
–z/OS ISPF Dialog Tag Language Guide and Reference, SC19-3620-00
–z/OS ISPF Edit and Edit Macros, SC19-3621-00
–z/OS ISPF Messages and Codes, SC19-3622-00
–z/OS ISPF Reference Summary, SC19-3624-00
–z/OS ISPF Services Guide, SC19-3626-00
–z/OS ISPF User’s Guide Vol I, SC19-3627-00
–z/OS ISPF User’s Guide Vol II, SC19-3628-00

You might also like