|
>>-EXECIO--+-lines-+-------------------------------------------->
'-*-----'
>--+-DISKW--ddname--+-----------------+---------------+--------><
| '-| Write Parms |-' |
'-+-DISKR--+-ddname-+---------+-+----------------+-'
'-DISKRU-' '-linenum-' '-| Read Parms |-'
Write Parms
|--+--------------------------------------------------+---------|
'-(--+---------------+--+------+--+-------+--+---+-'
'-STEM var-name-' '-OPEN-' '-FINIS-' '-)-'
Read Parms
|--+-------------------------------------------------------+----|
'-(-+---------------+-+------+-+-------+-+------+-+---+-'
+-FIFO----------+ '-OPEN-' '-FINIS-' '-SKIP-' '-)-'
+-LIFO----------+
'-STEM var-name-'
controls the input and output (I/O) of information
to and from a data set. Information can be read from a data set to
the data stack for serialized processing or to a list of variables
for random processing. Information from the data stack or a list of
variables can be written to a data set.
The EXECIO command
can be used in REXX execs that execute in both the TSO/E address space
and non-TSO/E address spaces.
You can use the EXECIO command
to do various types of I/O tasks, such as copy information to and
from a data set to add, delete, or update the information.
Note: The EXECIO command does not support I/O on
files allocated to data sets with track overflow. However, if a data
set is allocated with track overflow, that attribute is reset by DFSMS
before any I/O is performed. The user may see a message like: IEC137I TRACK OVERFLOW RESET FOR <ddname>
and
then the I/O is performed.
An I/O data set must be either
sequential or a single member of a PDS. Before the EXECIO command
can perform I/O to or from the data set, the data set must be allocated
to a file that is specified on the EXECIO command. The EXECIO command
does not perform the allocation.
Both fixed and
fixed standard record formats with or without blocking are supported.
Also variable record formats, including spanned records, with or wihtout
blocking are supported. In addition, data sets with undefined record
formats are supported. That is, all of the following record formats
(RECFM) are allowed: F, FB, FS, FBS, V, VB, VS, VBS, and U
The data set may also optionally include ANSI or MACHINE
carriage control characters. With carriage control included in the
RECFM, the following additional record formats are also supported: FA, FM, FBA, FBM, FSA, FSM, FBSA, FBSM,
VA, VM, VBA, VBM, VSA, VSM, VBSA, VBSM
EXECIO does not support read for update (DISKRU) for
files allocated with RECFM=VS or VBS, nor for files allocated to a
member of a PDSE Program Library. EXECIO does not support write (DISKW)
for files allocated to a member of a PDSE Program Library.
When
performing I/O with a system data set that is available to multiple
users, allocate the data set as OLD, before issuing the EXECIO command,
to have exclusive use of the data set.
When you use EXECIO,
you must ensure that you use quotation marks around any operands,
such as DISKW, STEM, FINIS, or LIFO. Using quotation marks prevents
the possibility of the operands being substituted as variables. For
example, if you assign the variable stem to a value in the
exec and then issue EXECIO with the STEM option, if STEM is not enclosed
in quotation marks, it will be substituted with its assigned value.
Operands
for Reading from a Data Set: The operands for the EXECIO command
to read from a data set are as follows:
- lines
- the number of lines to be processed. This operand can be a specific
decimal number or an arbitrary number indicated by *. When the operand
is * and EXECIO is reading from a data set, input is read until EXECIO
reaches the end of the data set.
If you specify a value of zero
(0), no I/O operations are performed unless you also specify either
OPEN, FINIS, or both OPEN and FINIS. - If you specify OPEN and the data set is closed, EXECIO opens the
data set but does not read any lines. If you specify OPEN and the
data set is open, EXECIO does not read any lines.
In either case,
if you also specify a non-zero value for the linenum operand,
EXECIO sets the current record number to the record number indicated
by the linenum operand.
Note: By default, when a file is
opened, the current record number is set to the first record (record
1). The current record number is the number of the next record EXECIO
will read. However, if you use a non-zero linenum value with
the OPEN operand, EXECIO sets the current record number to the record
number indicated by linenum.
- If you specify FINIS and the data set is open, EXECIO does not
read any lines, but EXECIO closes the data set. If you specify FINIS
and the data set is not already opened, EXECIO does not open the data
set and then close it.
- If you specify both OPEN and FINIS, EXECIO processes the OPEN
first as described above. EXECIO then processes the FINIS as described
above.
- DISKR
- opens a data set for input (if it is not already open) and reads
the specified number of lines from the data set and places them on
the data stack. If the STEM operand is specified, the lines are placed
in a list of variables instead of on the data stack.
While a data
set is open for input, you cannot write information back to the same
data set.
The data set is not automatically closed unless:
- DISKRU
- opens a data set for update (if it is not already open) and reads
the specified number of lines from the data set and places them on
the data stack. If the STEM operand is specified, the lines are placed
in a list of variables instead of on the data stack.
While a data
set is open for update, the last record read can be changed and then
written back to the data set with a corresponding EXECIO DISKW command.
Typically, you open a data set for update when you want to modify
information in the data set.
However, note that
data sets with spanned record format (i.e. VS or VBS) cannot be opened
in update mode.
The data set is not automatically closed unless:
- the task, under which the data set was opened, ends
- the last language processor environment associated
with the task, under which the data set was opened, is terminated
After a data set is open for update (by issuing a DISKRU
as the first operation against the data set), you can use either DISKR
or DISKRU to fetch subsequent records for update.
- ddname
- the name of the file to which the sequential data set or member
of the PDS was allocated. You must allocate the file before you can
issue EXECIO. For example, you can allocate a file using the ALLOCATE
command in the TSO/E address space only or a JCL DD statement.
- linenum
- the line number in the data set at which EXECIO is to begin reading.
When a data set is closed and reopened as a result of specifying a
record number earlier than the current record number, the file is
open for:
- input if DISKR is specified
- update if DISKRU is specified
When a data set is open for input or update, the current
record number is the number of the next record to be read. When linenum specifies
a record number earlier than the current record number in an open
data set, the data set must be closed and reopened to reposition the
current record number at linenum. When this situation occurs
and the data set was not opened at the same task level as that of
the executing exec, attempting to close the data set at a different
task level results in an EXECIO error. The linenum operand
must not be used in this case.
Specifying a value of zero (0)
for linenum is equivalent to not specifying
the linenum operand. In either case, EXECIO
begins reading the file as follows: - If the file was already opened, EXECIO begins reading with the
line following the last line that was read.
- If the file was just opened, EXECIO begins reading with the first
line of the file.
- FINIS
- close the data set after the EXECIO command completes. A data
set can be closed only if it was opened at the same task level as
the exec issuing the EXECIO command.
You can use FINIS with a lines value
of 0 to have EXECIO close an open data set without first reading a
record.
Because the EXEC command (when issued from TSO/E READY
mode) is attached by the TSO/E terminal monitor program (TMP), data
sets opened by a REXX exec are typically closed automatically when
the top level exec ends. Good programming practice, however, would
be to explicitly close all data sets when finished with them.
- OPEN
- opens the specified data set if it is not already open. You can
use OPEN with a lines value of 0 to have
EXECIO do one of the following:
- open a data set without reading any records
- set the current record number (that is, the number of the next
record EXECIO will read) to the record number indicated by the linenum operand,
if you specify a value for linenum
- STEM var-name
- the stem of the set of variables into which information is to
be placed. To place information in compound variables, which allow
for easy indexing, the var-name should end
with a period. For example,
MYVAR.
When var-name does
not end with a period, the variable names are appended with numbers
and can be accessed in a loop such as: "EXECIO * DISKR MYINDD (FINIS STEM MYVAR"
DO i = 1 to MYVAR0
this_line = VALUE('MYVAR'||i)
END
In the first example above, the list of
compound variables has the stem MYVAR. and lines
of information (records) from the data set are placed in variables MYVAR.1, MYVAR.2, MYVAR.3,
and so forth. The number of variables in the list is placed in MYVAR.0
Thus
if 10 lines of information were read into the MYVAR variables, MYVAR.0 contains
the number 10, indicating that 10 records are read. Furthermore, MYVAR.1 contains
record 1, MYVAR.2 contains record 2, and so forth
up to MYVAR.10 which contains record 10. All stem
variables beyond MYVAR.10 (i.e. MYVAR.11, MYVAR.12,
etc.) are residual and contain the values that they held before entering
the EXECIO command.
To avoid confusion as to whether a residual
stem variable value is meaningful, you may want to clear the entire
stem variable before entering the EXECIO command. To clear all compound
variables whose names begin with that stem, you can either: - Use the DROP instruction as follows, to set all possible compound
variables whose names begin with that stem to their uninitialized
values:
DROP MYVAR.
- Set all possible compound variables whose names begin with that
stem to nulls as follows:
MYVAR. = ''
See the example at 12,
which shows the usage of the EXECIO command with stem variables.
- LIFO
- places information about the data stack in LIFO (last in first
out) order.
- FIFO
- places information about the data stack in FIFO (first in first
out) order. FIFO is the default when neither LIFO or FIFO is specified.
- SKIP
- reads the specified number of lines but does not place them on
the data stack or in variables. When the number of lines is *, EXECIO
skips to the end of the data set.
Operands for Writing to a Data Set: The
operands for the EXECIO command that write to a data set are as follows:
- lines
- the number of lines to be written. This operand can be a specific
decimal number or an arbitrary number indicated by *. If you specify
a value of zero (0), or if you specify * and it is determined
that there are no lines available to be written, no I/O operations
are performed unless you also specify either OPEN, FINIS, or both
OPEN and FINIS.
- If you specify OPEN and the data set is closed, EXECIO opens the
data set but does not write any lines. If you specify OPEN and the
data set is open, EXECIO does not write any lines.
- If you specify FINIS and the data set is open, EXECIO does not
write any lines, but EXECIO closes the data set. If you specify FINIS
and the data set is not already opened, EXECIO does not open the data
set and then close it.
- If you specify both OPEN and FINIS, EXECIO processes the OPEN
first as described above. EXECIO then processes the FINIS as described
above.
When EXECIO writes an arbitrary number of lines from the
data stack, it stops only when it reaches a null line. If there is
no null line on the data stack in an interactive TSO/E address space,
EXECIO waits for input from the terminal and stops only when it receives
a null line. See note below.
When EXECIO writes an arbitrary
number of lines from a list of compound variables, it stops when it
reaches a null value or an uninitialized variable (one that displays
its own name).
The 0th variable has no effect on controlling
the number of lines written from variables.
Note: EXECIO running
in TSO/E background or in a non-TSO/E address space has the same use
of the data stack as an exec that runs in the TSO/E foreground. If
an EXECIO * DISKW ... command is executing in the background or in
a non-TSO/E address space and the data stack becomes empty before
a null line is found (which would terminate EXECIO), EXECIO goes to
the input stream as defined by the INDD field in the module name table
(see Module name table). The system default is SYSTSIN.
When end-of-file is reached, EXECIO ends.
- DISKW
- opens a data set for output (if it is not already open) and writes
the specified number of lines to the data set. The lines can be written
from the data stack or, if the STEM operand is specified, from a list
of variables.
You can use the DISKW operand to write information
to a different data set from the one opened for input, or to update,
one line at a time, the same data set opened for update.
When
a data set is open for update, you can use DISKW to rewrite the last
record read. The lines value should be 1 when doing an update.
For lines values greater than 1, each write updates the same
record.
The data set is not automatically closed unless: - The task, under which the data set was opened, ends.
- The last language processor environment associated
with the task, under which the data set was opened, is terminated.
Note: - The length of an updated line is set to the length of the line
it replaces. When an updated line is longer than the line it replaces,
information that extends beyond the replaced line is truncated. When
information is shorter than the replaced line, the line is padded
with blanks to attain the original line length.
- When using EXECIO to write to more than one member of the same
PDS, only one member of the PDS should be open at a time for output.
- Do not use the MOD attribute when allocating a member of a PDS
to which you want to append information. You can use MOD only when
appending information to a sequential data set. To append information
to a member of a PDS, rewrite the member with the additional records
added.
- ddname
- the name of the file to which the sequential data set or member
of the PDS was allocated. You must allocate the file before you issue
the EXECIO command.
- FINIS
- close the data set after the EXECIO command completes. A data
set can be closed only if it was opened at the same task level as
the exec issuing the EXECIO command.
You can use FINIS with a lines value
of 0 to have EXECIO close an open data set without first writing a
record.
Because the EXEC command (when issued from TSO/E READY
mode) is attached by the TMP, data sets opened by a REXX exec are
typically closed automatically when the top level exec ends. Good
programming practice, however, would be to explicitly close all data
sets when finished with them.
- OPEN
- opens the specified data set if it is not already open. You can
use OPEN with a lines value of 0 to have EXECIO open the data
set without writing any records. If you specify OPEN with a lines
value of * and it is determined that there are no lines to be written,
the data set will still be opened.
- STEM var-name
- the stem of the list of variables from which information is to
be written. To write information from compound variables, which allow
for indexing, the var-name should end with
a period, MYVAR., for example. When three lines
are written to the data set, they are taken from MYVAR.1,
MYVAR.2, MYVAR.3. When * is specified as the number of lines
to write, the EXECIO command stops writing information to the data
set when it finds a null line or an uninitialized compound variable.
In this case, if the list contained 10 compound variables, the EXECIO
command stops at MYVAR.11.
The 0th variable has
no effect on controlling the number of lines written from variables.
When var-name does
not end with a period, the variable names must be appended with consecutive
numbers, such as MYVAR1, MYVAR2, MYVAR3.
See
the example 12 which shows the
usage of the EXECIO command with stem variables.
Closing Data Sets: If
you specify FINIS on the EXECIO command, the data set is closed after
EXECIO completes processing. If you do not specify FINIS, the data
set is closed when one of the following occurs: - The task, under which the data set was opened, is terminated,
or
- The last language processor environment associated
with the task, under which the data set was opened, is terminated
(even if the task itself is not terminated).
In general, if you use the TSO/E EXEC command to invoke
a REXX exec, any data sets that the exec opens are closed when the
top level exec completes. For example, suppose you are executing
an exec (top level exec) that invokes another exec. The second exec
uses EXECIO to open a data set and then returns control to the first
exec without closing the data set. The data set is still open when
the top level exec regains control. The top level exec can then read
the same data set continuing from the point where the nested exec
finished EXECIO processing. When the original exec (top level exec)
ends, the data set is automatically closed.
Figure 1 is an example of two execs that show
how a data set remains open. The first (top level) exec, EXEC1, allocates
a file and then calls EXEC2. The second exec (EXEC2) opens the file,
reads the first three records, and then returns control to EXEC1.
Note that EXEC2 does not specify FINIS on the EXECIO command, so
the file remains open.
When the first exec EXEC1 regains control,
it issues EXECIO and gets the fourth record because the file is still
open. If EXEC2 had specified FINIS on the EXECIO command, EXEC1 would
have read the first record. In the example, both execs run at the
same task level.
Figure 1. Example of closing data sets with EXECIO FIRST EXEC ---- EXEC1
/* REXX exec (EXEC1) invokes another exec (EXEC2) to open a */
/* file. EXEC1 then continues reading the same file. */
say 'Executing the first exec EXEC1'
"ALLOC FI(INPUTDD) DA(MYINPUT) SHR REUSE" /* Allocate input file */
/* */
/* Now invoke the second exec (EXEC2) to open the INPUTDD file. */
/* The exec uses a call to invoke the second exec. You can */
/* also use the TSO/E EXEC command, which would have the */
/* same result. */
/* If EXEC2 opens a file and does not close the file before */
/* returning control to EXEC1, the file remains open when */
/* control is returned to EXEC1. */
/* */
say 'Invoking the second exec EXEC2'
call exec2 /* Call EXEC2 to open file */
say 'Now back from the second exec EXEC2. Issue another EXECIO.'
"EXECIO 1 DISKR INPUTDD (STEM X." /* EXECIO reads record 4 */
say x.1
say 'Now close the file'
"EXECIO 0 DISKR INPUTDD (FINIS" /* Close file so it can be freed */
"FREE FI(INPUTDD)"
EXIT 0
SECOND EXEC ---- EXEC2
/* REXX exec (EXEC2) opens the file INPUTDD, reads 3 records, and */
/* then returns to the invoking exec (EXEC1). The exec (EXEC2) */
/* returns control to EXEC1 without closing the INPUTDD file. */
/* */
say "Now in the second exec EXEC2"
DO I = 1 to 3 /* Read & display first 3 records */
"EXECIO 1 DISKR INPUTDD (STEM Y."
say y.1
END
Say 'Leaving second exec EXEC2. Three records were read from file.'
RETURN 0
Return Codes: After the EXECIO command runs,
it sets the REXX special variable RC to one of the following return
codes:
Return code |
Meaning |
---|
0 |
Normal completion of requested operation |
1 |
Data was truncated during DISKW operation |
2 |
End-of-file reached before the specified number
of lines were read during a DISKR or DISKRU operation. This does
not occur if * is used for number of lines because the remainder of
the file is always read. |
4 |
During a DISKR or DISKRU operation, an empty data
set was found in a concatenation of data sets. The file was not successfully
opened and no data was returned. |
20 |
Severe error. EXECIO completed unsuccessfully
and a message is issued. |
Examples
- This example copies an entire existing sequential data set named
prefix.MY.INPUT into a member of an existing PDS named DEPT5.MEMO(MAR22),
and uses the ddnames DATAIN and DATAOUT respectively.
"ALLOC DA(MY.INPUT) F(DATAIN) SHR REUSE"
"ALLOC DA('DEPT5.MEMO(MAR22)') F(DATAOUT) OLD"
"NEWSTACK" /* Create a new data stack for input only */
"EXECIO * DISKR DATAIN (FINIS"
QUEUE '' /* Add a null line to indicate the end of information */
"EXECIO * DISKW DATAOUT (FINIS"
"DELSTACK" /* Delete the new data stack */
"FREE F(DATAIN DATAOUT)"
- This example copies an arbitrary number of lines from existing
sequential data set prefix.TOTAL.DATA into a list of compound variables
with the stem DATA., and uses the ddname INPUTDD:
ARG lines
"ALLOC DA(TOTAL.DATA) F(INPUTDD) SHR REUSE"
"EXECIO" lines "DISKR INPUTDD (STEM DATA."
SAY data.0 'records were read.'
- To update the second line in data set DEPT5.EMPLOYEE.LIST in file
UPDATEDD, allocate the data set as OLD to guarantee exclusive update.
"ALLOC DA('DEPT5.EMPLOYEE.LIST') F(UPDATEDD) OLD"
"EXECIO 1 DISKRU UPDATEDD 2"
PULL line
PUSH 'Crandall, Amy AMY 5500'
"EXECIO 1 DISKW UPDATEDD (FINIS"
"FREE F(UPDATEDD)"
- The following example scans each line of a data set whose name
and size is specified by the user. The user is given the option of
changing each line as it appears. If there is no change to the line,
the user presses the Enter key to indicate that there is no change.
If there is a change to the line, the user types the entire line
with the change and the new line is returned to the data set.
PARSE ARG name numlines /* Get data set name and size from user */
"ALLOC DA("name") F(UPDATEDD) OLD"
eof = 'NO' /* Initialize end-of-file flag */
DO i = 1 to numlines WHILE eof = no
"EXECIO 1 DISKRU UPDATEDD " /* Queue the next line on the stack */
IF RC = 2 THEN /* Return code indicates end-of-file */
eof = 'YES'
ELSE
DO
PARSE PULL line
SAY 'Please make changes to the following line.'
SAY 'If you have no changes, press ENTER.'
SAY line
PARSE PULL newline
IF newline = '' THEN NOP
ELSE
DO
PUSH newline
"EXECIO 1 DISKW UPDATEDD"
END
END
END
"EXECIO 0 DISKW UPDATEDD (FINIS"
- This example reads from the data set allocated to INDD to find
the first occurrence of the string "Jones". Upper and lowercase distinctions
are ignored. The example demonstrates how to read and search one
record at a time. For better performance, you can read all records
to the data stack or to a list of variables, search them, and then
return the updated records.
done = 'no'
DO WHILE done = 'no'
"EXECIO 1 DISKR INDD"
IF RC = 0 THEN /* Record was read */
DO
PULL record
lineno = lineno + 1 /* Count the record */
IF INDEX(record,'JONES') ¬= 0 THEN
DO
SAY 'Found in record' lineno
done = 'yes'
SAY 'Record = ' record
END
ELSE NOP
END
ELSE
done = 'yes'
END
"EXECIO 0 DISKR INDD (FINIS"
EXIT 0
- This exec copies records from data set prefix.MY.INPUT to the
end of data set prefix.MY.OUTPUT. Neither data set has been allocated
to a ddname. It assumes that the input data set has no null lines.
"ALLOC DA(MY.INPUT) F(INDD) SHR REUSE"
"ALLOC DA(MY.OUTPUT) F(OUTDD) MOD REUSE"
SAY 'Copying ...'
"EXECIO * DISKR INDD (FINIS"
QUEUE '' /* Insert a null line at the end to indicate end of file */
"EXECIO * DISKW OUTDD (FINIS"
SAY 'Copy complete.'
"FREE F(INDD OUTDD)"
EXIT 0
- This exec reads five records from the data set allocated to MYINDD
starting with the third record. It strips trailing blanks from the
records, and then writes any record that is longer than 20 characters.
The file is not closed when the exec is finished.
"EXECIO 5 DISKR MYINDD 3"
DO i = 1 to 5
PARSE PULL line
stripline = STRIP(line,t)
len = LENGTH(stripline)
IF len > 20 THEN
SAY 'Line' stripline 'is long.'
ELSE NOP
END
/* The file is still open for processing */
EXIT 0
- This exec reads the first 100 records (or until EOF) of the data
set allocated to INVNTORY. Records are placed on the data stack in
LIFO order. A message is issued that gives the result of the EXECIO
operation.
eofflag = 2 /* Return code to indicate end of file */
"EXECIO 100 DISKR INVNTORY (LIFO"
return_code = RC
IF return_code = eofflag THEN
SAY 'Premature end of file.'
ELSE
SAY '100 Records read.'
EXIT return_code
- This exec erases any existing data from the data
set FRED.WORKSET.FILE by opening the data set and then closing it
without writing any records. By doing this, EXECIO just writes an
end-of-file marker, which erases any existing records in the data
set.
In this example, the data set from which you are erasing
records must not be allocated with a disposition of MOD. If you allocate
the data set with a disposition of MOD, the EXECIO OPEN followed by
the EXECIO FINIS results in EXECIO just rewriting the existing end-of-file
marker. "ALLOCATE DA('FRED.WORKSET.FILE') F(OUTDD) OLD REUSE"
"EXECIO 0 DISKW OUTDD (OPEN" /* Open the OUTDD file for writing,
but do not write a record */
"EXECIO 0 DISKW OUTDD (FINIS" /* Close the OUTDD file. This
basically completes the erasing of
any existing records from the
OUTDD file. */
Note
that in this example, the EXECIO … (OPEN command
followed by the EXECIO … (FINIS command is equivalent
to: "EXECIO 0 DISKW OUTDD (OPEN FINIS"
Also
note that the above EXECIO 0 DISKW command is equivalent
to using EXECIO * DISKW when there are no lines to
write. That is, the above EXECIO 0 is equivalent
to: push '' /* Place null on stack to terminate EXECIO*/
"EXECIO * DISKW OUTDD (OPEN FINIS"
- This exec opens the data set MY.INVNTORY without reading any records.
The exec then uses a main loop to read records from the data set and
process the records.
"ALLOCATE DA('MY.INVNTORY') F(INDD) SHR REUSE"
"ALLOCATE DA('MY.AVAIL.FILE') F(OUTDD) OLD REUSE"
"EXECIO 0 DISKR INDD (OPEN" /* Open INDD file for input, but
do not read any records */
eof = 'NO' /* Initialize end-of-file flag */
avail_count = 0 /* Initialize counter */
DO WHILE eof = 'NO' /* Loop until the EOF of input
file */
"EXECIO 1 DISKR INDD (STEM LINE." /* Read a line */
IF RC = 2 THEN /* If end of file is reached, */
eof = 'YES' /* set the end-of-file (eof)
flag */
ELSE /* Otherwise, a record is read */
DO
IF INDEX(line.1,'AVAILABLE') ¬ = 0 THEN /* Look for records
marked "available" */
DO /* "Available" record found */
"EXECIO 1 DISKW OUTDD (STEM LINE." /* Write record to "available"
file */
avail_count = avail_count + 1 /* Increment "available"
counter */
END
END
END
"EXECIO 0 DISKR INDD (FINIS" /* Close INDD file that is currently
open */
"EXECIO 0 DISKW OUTDD (FINIS" /* Close OUTDD file if file is cur-
rently open. If the OUTDD file is
not open, the EXECIO command has
no effect. */
EXIT 0
- This exec opens the data set MY.WRKFILE and sets the current record
number to record 8 so that the next EXECIO DISKR command begins reading
at the eighth record.
"ALLOC DA('MY.WRKFILE') F(INDD) SHR REUSE"
"EXECIO 0 DISKR INDD 8 (OPEN" /* Open INDD file for input and set
current record number to 8. */
CALL READ_NEXT_RECORD /* Call subroutine to read record on
to the data stack. The next
record EXECIO reads is record 8
because the previous EXEC IO set
the current record number to 8. */
⋮
"EXECIO 0 DISKR INDD (FINIS" /* Close the INDD file. */
- This exec uses EXECIO to successively append the
records from 'sample1.data' and then from 'sample2.data' to the end
of the data set 'all.sample.data'. It illustrates the effect of residual
data in STEM variables. Data set 'sample1.data' contains 20 records.
Data set 'sample2.data' contains 10 records.
"ALLOC FI(MYINDD1) DA('SAMPLE1.DATA') SHR REUSE" /* input file 1 */
"ALLOC FI(MYINDD2) DA('SAMPLE2.DATA') SHR REUSE" /* input file 2 */
"ALLOC FI(MYOUTDD) DA('ALL.SAMPLE.DATA') MOD REUSE" /* output append
file */
/*******************************************************************/
/* Read all records from 'sample1.data' and append them to the */
/* end of 'all.sample.data'. */
/*******************************************************************/
exec_RC = 0 /* Initialize exec return code */
"EXECIO * DISKR MYINDD1 (STEM NEWVAR. FINIS" /* Read all records */
if rc = 0 then /* If read was successful */
do
/*****************************************************************/
/* At this point, newvar.0 should be 20, indicating 20 records */
/* have been read. Stem variables newvar.1, newvar.2, ... through*/
/* newvar.20 will contain the 20 records that were read. */
/*****************************************************************/
say "-----------------------------------------------------"
say newvar.0 "records have been read from 'sample1.data': "
say
do i = 1 to newvar.0 /* Loop through all records */
say newvar.i /* Display the ith record */
end
"EXECIO" newvar.0 "DISKW MYOUTDD (STEM NEWVAR." /* Write exactly
the number of records read */
if rc = 0 then /* If write was successful */
do
say
say newvar.0 "records were written to 'all.sample.data'"
end
else
do
exec_RC = RC /* Save exec return code */
say
say "Error during 1st EXECIO ... DISKW, return code is " RC
say
end
end
else
do
exec_RC = RC /* Save exec return code */
say
say "Error during 1st EXECIO ... DISKR, return code is " RC
say
end
If exec_RC = 0 then /* If no errors so far... continue */
do
/***************************************************************/
/* At this time, the stem variables newvar.0 through newvar.20 */
/* will contain residual data from the previous EXECIO. We */
/* issue the "DROP newvar." instruction to clear these residual*/
/* values from the stem. */
/***************************************************************/
DROP newvar. /* Set all stems variables to their */
uninitialized state */
/***************************************************************/
/* Read all records from 'sample2.data' and append them to the */
/* end of 'all.sample.data'. */
/***************************************************************/
"EXECIO * DISKR MYINDD2 (STEM NEWVAR. FINIS" /*Read all records*/
if rc = 0 then /* If read was successful */
do
/*************************************************************/
/* At this point, newvar.0 should be 10, indicating 10 */
/* records have been read. Stem variables newvar.1, newvar.2,*/
/* ... through newvar.10 will contain the 10 records. If we */
/* had not cleared the stem newvar. with the previous DROP */
/* instruction, variables newvar.11 through newvar.20 would */
/* still contain records 11 through 20 from the first data */
/* set. However, we would know that these values were not */
/* read by the last EXECIO DISKR since the current newvar.0 */
/* variable indicates that only 10 records were read by */
/* that last EXECIO. */
/*************************************************************/
say
say
say "-----------------------------------------------------"
say newvar.0 "records have been read from 'sample2.data': "
say
do i = 1 to newvar.0 /* Loop through all records */
say newvar.i /* Display the ith record */
end
"EXECIO" newvar.0 "DISKW MYOUTDD (STEM NEWVAR." /* Write
exactly the number of records read */
if rc = 0 then /* If write was successful */
do
say
say newvar.0 "records were written to 'all.sample.data'"
end
else
do
exec_RC = RC /* Save exec return code */
say
say "Error during 2nd EXECIO ...DISKW, return code is " RC
say
end
end
else
do
exec_RC = RC /* Save exec return code */
say
say "Error during 2nd EXECIO ... DISKR, return code is " RC
say
end
end
"EXECIO 0 DISKW MYOUTDD (FINIS" /* Close output file */
"FREE FI(MYINDD1)"
"FREE FI(MYINDD2)"
"FREE FI(MYOUTDD)"
exit 0
- Example of reading records from an input RECFM=VS
file and writing them to a new file having RECFM=VBS, then verifying
that the copy is good.
Note: Assuming input LRECL <=240.
/* REXX */
"ALLOC FI(INVS) DA('userid.test.vs') SHR REUSE"
ALLOCRC = RC
"ALLOC FI(OUTVBS) DA('userid.test.newvbs') SPACE(1) TRACKS " ,
" LRECL(240) BLKSIZE(80) RECFM(V B S) DSORG(PS) NEW REUSE"
ALLOCRC = MAX(RC, ALLOCRC)
execio_rc = 0 /* Initialize */
error = 0 /* Initialize */
IF ALLOCRC = 0 THEN
do
/******************************************************************/
/* When spanned records are read, each logical record is the */
/* collection of all spanned segments of that record on DASD. */
/******************************************************************/
"execio * DISKR INVS (STEM inrec. FINIS" /* Read all records */
if rc /= 0 then
error = 1 /* Read Error occurred */
end
ELSE
do
say 'File allocation error ...'
error = 1 /* Error occurred */
end
IF error = 0 then /* If no errors */
DO
"execio "inrec.0" DISKW OUTVBS (STEM inrec. FINIS" /* Write all
records read to the new file */
if rc=0 then
do
say 'Output to new VBS file completed successfully'
say 'Number of records copied ===> ' inrec.0
end
else
do
say 'Error writing to new VBS file '
error = 1 /* Error occurred */
end
END
/**********************************************************************/
/* Confirm the new output VBS file matches the input. */
/**********************************************************************/
if error = 0 then /* No error so far */
do
"execio * DISKR OUTVBS (STEM inrec2. FINIS" /* Read back
the newly created file */
if rc = 0 & inrec.0 = inrec2.0 then /* If read back OK */
do /* Compare */
match_cnt = 0
do i=1 to inrec2.0
if inrec2.i == inrec.i then
match_cnt = match_cnt+1
end
if match_cnt = inrec2.0 then
say 'New output VBS file matches input file - successful'
else
do
say 'New output VBS does not match input - error.'
say 'Num of records different ==> 'inrec2.0 -match_cnt
end
else
say 'Unable to verify that new output VBS matches input'
end
"FREE FI(INVS,OUTVBS)"
exit 0
- Example of reading a member of a RECFM=U file and
changing the first occurrence of the word 'TSOREXX ' within each record
to 'TSOEREXX' before rewriting the record.
Note: If a record is not
changed, it need not be rewritten.
/* REXX */
/*--------------------------------------------------------------------*/
/* Alloc my Load Lib data set having RECFM=U BLKSIZE=32000 LRECL=0 */
/*--------------------------------------------------------------------*/
/* Note that you cannot replace a PDS Load Library by a PDSE */
/* Program Library in this example. EXECIO can be used to read */
/* (DISKR) a file allocated to a member in a PDSE Program Library */
/* but it cannot update such a member, because EXECIO cannot */
/* open such a file for update (DISKRU) nor for write (DISKW). */
/*--------------------------------------------------------------------*/
"ALLOC FI(INOUTDD) DA('apar2.my.load(mymem)') SHR REUSE"
readcnt = 0 /* Initialize rec read cntr */
updtcnt = 0 /* Initialize rec update cntr */
error = 0 /* Initialize flag */
EOF = 0 /* Initialize flag */
do while (EoF=0 & error=0) /* Loop while more records and
no error
"execio 1 DISKRU INOUTDD (STEM inrec." '* Read a record */
if rc = 0 then /* If read ok */
do /* Replace 1st occurrence of
'TSOREXX ' in record by 'TSOEREXX
and write it back */
readcnt = readcnt + 1 /* Records read */
z = POS('TSOREXX ', inrec.1,1) /* Find target within rec */
if z /= 0 then /* If found, replace it */
do
inrec.1 = SUBSTR(inrec.1,1,z-1)|| ,
SUBSTR(inrec.1,z+LENGTH('TSOEREXX')) /*Replace it*/
"execio 1 DISKW INOUTDD (STEM inrec." /* Rewrite the update
made to the last record read */
if rc > 0 then /* If error */
error=1 /* Indicate error */
else
updtcnt = updtcnt + 1 /* Incr update count */
end
else /* Else nothing changed, nothing
to rewrite */
NOP /* Continue with next record */
end
else /* Else non-0 RC */
if rc=2 then /* if end-of-file */
EoF=1 /* Indicate end-of-file */
else
error=1 /* Else read error */
end /* End do while */
"execio 0 DISKW INOUTDD (FINIS" /* Close the file */
if error = 1 then
say '*** Error occurred while updating file '
else
say updtcnt' of 'readcnt' records were changed'
"FREE FI(INOUTDD)"
exit 0
|