Unit 11.1 -- Copy Record from Input File to Output File
Prog
Copy eighty byte records from input file to output file
PED
to learn how to do simple sequential IO with the IBM MVS
macros
Concepts
For each file
GET dcbname,record-area (input)
PUT dcbname,record-area (output)
OPEN (dcbname,INPUT) (input-file)
CLOSE (dcbname,OUTPUT) (output-file)
For each file, we have a DCB statement
input format
dcb-name DCB DDNAME=ddname,MACRF=GM,BLKSIZE=nn,LRECL=mm,
DSORG=PS,EODAD=label
output format
dcb-name DCB DDNAME=ddname,MACRF=PM,BLKSIZE=nn,LRECL=mm,
DSORG=PS
ddname corresponds to either
FILEDEF (CMS)
or
DD statement (JCL/MVS)
SF
to continue a macro statement,
put a character in column 72 of line being continued
next line goes in column 16
Can also write
CLOSE (INFILE,,OUTFILE)
OPEN (INFILE,INPUT,OUTFILE,OUTPUT)
For JCL write
//GO.ddname DD * (input from JCL stream)
//GO.ddname DD SYSOUT=A (output to printer)
For CMS, write
filedef DISK ddname filename filemode a4
filedef DISK ddname filename filemode a5
Need to write
COPYFILE filename1 filemode1 a filename2 filemode2 a5
tp produce filename2 filemode2 which can be read by
assembler programs using these macros
43.ASS
43.JOB
43.EXE
Unit 11.1 -- Copy Record from Input File to Output File
In this unit, we learn about how to do I/O to and from
Files. These are done by macros described by your Data
Management Services Manual.
There are two sets of macros that can be used to do I/O
under CMS. There is one set we won't talk about. These are
the native macros associated with CMS. The reason we won't
talk about these is that real program development on an IBM
mainframe isn't done under CMS. CMS is a very late
invention of IBM. It is designed to support individual
users in the same manner a PC might. I.E., it is useful for
some program development, individual productivity and for
student or academic use.
The applications such as PAYROLL, accounting, etc. are done
under one of the many successors of the original IBM/360
operating system. These go under such names as OS/MVS,
OS/MVS/XA, etc. These are batch operating systems. That
means one doesn't interact with the programs the way one
might respond to prompts from a PASCAL program on a PC.
We will use the set associated with these operating systems.
CMS allows us to simulate these macros. This allows
programmers of applications for the "real" IBM mainframe
operating systems to develop their programs on the
relatively-friendly interactive CMS rather than being forced
to submit "jobs" to the mainframe operating system.
Since our IBM 4381 doesn't run OS/MVS, we will learn how to
simulate the OS/MVS I/O macros under the IBM operating
system.
Before proceeding with the technical details of the macros
and how to simulate them, we will divert ourselves to some
of the history of the IBM operating systems starting in the
1960's with the first card-oriented systems. What is a
card?
A card is a piece of thick paper in which holes were
punched. These were then fed into a machine called a card
reader that served as an input device.
One submits a job to the computer. A job is a sequence of
lines or "card" images. Some of these lines are Job Control
Language (JCL). JCL told the machine what programs to send
the various data, including programs that were. On the
sample output, these are the lines that begin with "//"
Other lines are the program itself which is input to the
ASSEMBLER. Last, but not least, are lines that are input to
the program after it has ASSEMBLED and loaded into memory.
These are the ones following the GO.SYSIN DD *
This is executed. When this happens, the ASSEMBLER is
loaded and fed the appropriate stuff. The resulting
executable is then loaded into memory. It is presented with
the "card images" that appear after GO.SYSIN DD *
These systems are descendant of the old card-based operating
systems. In the old days, before terminals were available,
the programmer would prepare his program using a device
called a keypunch and pieces of thin cardboard called
"cards." The user of the keypunch typed on a keyboard
similar to those on typrewriters or our current ter,minals
and microcomputers. The keypunch would very precisely make
rectangular holes in the "cards." Each letter corresponded
to a column where rectangular holes could be put. There
would be a different combination of rectangular holes for
each possible letter, number, or punctuation that could be
typed.
The programmer would type the JCL, the program and the data
using these devices. The cards would then be "read" into
the machine using a device called a cardreader. A file
corresponding to this input would be put into a special
location on the machine called the SPOOL. At the
appropriate time, the computer would process this collection
of CARD IMAGES.
Based, on what was in the JCL, the machine would dispatch
the collections of card images to the appropriate places,
the ASSEMBLER or other programming language statements to
the ASSEMBLER or compiler, the data to the executed ones.
However with JCL, one could do even more. One could
redirect the input of the program from the cards input to a
file on disk or a file on tape. That which would normally
go to a printer could be redirected to a disk file, a tape
or other location.
In TurboPascal, if we have a program that writes on
C:\BLAH\ZING\FOO.BAR, we would put this name in an "assign"
command and then read from a file:
assign(text_var,'c:\blah\zing\foo.bar'); If we changed our
minds and wanted the program to write to the terminal or
another file, we would have to modify the source program and
recompile. In the IBM world with JCL, the association of
the equivalent of a variable of type "text" with a file is
done by the JCL. The program is not responsible for this
connection in the IBM world.
The equivalent of such a "text" variable is the "DCB"
statement. You will note that the label is called "dcb-
name"
We use this name in every operation that refers to the file,
OPEN, CLOSE, READ, WRITE.
The next parameter is the ddname. This is a connection
between the DCB and the operating system.
In the case of a batch environment, our JCL would have
something like:
dcb-name DD ...
The "..." of the DD statement would the operating system
where to connect the file to, the printer, the card reader,
a disk file, or a tape.
Thus, there is a three way link:
OPEN
CLOSE ------> DCB statement --------> JCL -------> file
GET (dcb-name) ddname info on
PUT field DD statement
In the CMS world, there is again a three way connection.
However, here the connection between the ddname and a file
is made via a "FILEDEF" command. The FILEDEF command is
typed in just before the "LOAD" of the program.
OPEN
CLOSE ------> DCB statement --------> FILE -------> file
GET (dcb-name) ddname info on
PUT field FILE
statement
The format of the filedef command for our purposes is:
FILEDEF ddname DISK filename filemode A4
FILEDEF ddname DISK filename filemode A5
ddname is the name that appears after "DDNAME=" in our
argument list.
the word "DISK" tells CMS that the item is on DISK and not
tape or something. We give it the filename.
The filename and filemode designate the name of the file to
be input or output. For example, for the file "6
$ASSEMBLE", "6" is the filename and "ASSEMBLE" is the
filemode.
A4 or A5designates that the file is on current minidisk and
it is a simulated OS/360 file. Use A4 for files being read
from (input) and A5 for files being produced by a program
(output). We need to do thist to use the OS/MVS macros
(which is what I am teaching) with an ASSEMBLER| program
running under CMS.
If we want to get some initial data into a file to be read,
we prepare the input using XEDIT. However, prior to running
the program that will use this in OS/MVS mode, we type the
single command:
COPYFILE filename1 filemode1 A filename2 filemode2 A5 (RECFM
F LRECL 80 REPLACE
For example, if we edited and created the file "INPUT CMS"
we could write:
COPYFILE INPUT CMS A INPUT OSMVS A5 (recfm f lrecl 80 (RECFM
F LRECL 80 REPLACE
and then in using this with an ASSEMBLER program which had a
DCB line like
INDCB DCB DDNAME=INFILE,.....
we would write
FILEDEF INFILE DISK INPUT OSMVS A5
Let's look at the remainder of the DCB statement. Only the
"EODAD" field will require any thought other than copying it
when we do straightforward sequential I/O capabilities.
MACRF
(Macro-Form)
In many cases, card-images or other records are grouped into
blocks containing several card-images. For example, 400 80-
byte card-images are often grouped together into a 32,000-
byte block. It takes the computer much less time to read in
all 32,000 bytes at once than to do 400 separate reads of 80
bytes each. If the file is blocked, when we do the first
read, 32,000 bytes are read in. Then, each subsequent read
will cause 80 bytes of the buffer to be transferred to the
user area. Of course, after 400 reads, a new collection of
32,000 bytes will be read from the file.
When we use the "GM" macro-form, the fact that the file is
buffered is transparent to the user. The data is copied to
and from the user's record area as desired. There is
another option where the user receives a pointer into the
buffer. This saves the operating system, the time to move
the record to the user's area for each "GET" macro-call. We
leave this to you to read in your manual.
BLKSIZE
This stands for block size.
This tells the computer how many bytes are in each of the
blocks mentioned above. (In reading some files, this might
be part of the file and the OPEN macro will cause the
information to be copied into the DCB and we won't have to
speify it.)
LRECL
This stands for Logical Record Length which is how many
bytes are in each chunk processed by "GET" or "PUT"
DSORG
The "PS" stands for physically sequential. These are the
vanilla files that we read in one record at a time or write
out sequentially one record at a time. Other options are
random access or DCB.
EODAD
This is where we branch when an end of file is encountered
on input. Thus, instead of having a separate if checking
for end of file after each read of the file, there is an
implicit if checking for this after each read. When end of
file occurs, there is a branch to the appropriate label as
indicated by this paramter.
The functions of "GET" "PUT", "OPEN" and "CLOSE" should be
obvious by now. The OPEN will associate a "DCBname" with a
file. It also lets the machine know if we are writing
(OUTPUT) or reading (INPUT). It serves the same role as
"reset" or "rewrite" in Turbo Pascalin that it starts the
file at the beginning. (There are options to append to the
end of the file or update records in place, but that is
beyond the scope of this course, but may be in an M
problem.)
It is of the form:
OPEN (dcbname,{INPUT or OUTPUT})
We can include several files in one OPEN statement, like
this:
OPEN (dcbname1,INPUT,dcbname2,OUTPUT)
Remember that each dcbname must appear in the label field of
the appropriate DCB statement.
We can close similarly. We can usually leave out the
"INPUT" or "OUTPUT" designations from the "CLOSE" statement.
GET dcbname,record-area
retrieves LRECL bytes from the file and sticks it in record-
area. There better be at least that many bytes allocated in
record-area as nobody will check. Otherwise, whatever
follows will get clobbered.
And
PUT dcbname,record-area
will transfer LRECL bytes to the output area:
There are two little gotcha's that I have to tell you about
as we are simulating OS/MVS under CMS.
1.Type "GLOBAL MACLIB OSMACRO"
This enables the ASSEMBLER to find the needed macro
library for the GET, PUT, DCB, etc.
You only need to do this once per log in session after
the "READY" prompt.
2.If you need to continue a macro call, put something in
column 72. Any character (other than space) will do.
This is called a continuation character.
Unfortunately, the XEDIT will not normally let you enter
this character. In order to tell the editor to let you
do this, type
SET TRUNC 72
You type this on the bottom line, just after the "====>"
(wher e you would normally write "FILE".
Your program listings include the ASSEMBLY for the program.
When the DCB macro is expanded it produces a lot of junk; I
will let you see it for yourself when you assemble your
programs..
You also see a CONSOLE LOG when the program was run.
I also show you an example of how this output will look if
you were to run it using MVS/JCL and the IBM operating
system.
Looking at the ASSEMBLY listing, we start off with the IBM
convention.
We then open the input files. Note that we use the names
INDCB and OUTDCB which are in the label field of the DCB.
The loop is a simple loop that reads a record and writes a
record. Notice again we use the label field on the DCB
statements to refer to the file. The "EODAD=EOF" on the
INDCB DCB statement will cause the loop to end on end of
file--it is not an infinite loop as it appears.
AT EOF, we close the files and return using the IBM
convention.
Looking at the console log, observe that we copy some dummy
file (PROFILE EXEC) to "test input" Note the "(recfm f
lrecl 80". That causes the input file to be fixed format
and record size 80 to match the expectation of the program.
We then use filedef to define infile. Notice that the
second word on the filedef is the name that appears in the
DDNAME parameters of the DCB. That is, "INFILE" appears in
the first filedef and in the DDNAME parameter of the first
DCB. Likewise, OUTFILE appears in the second filedef and in
the DDNAME parameter of the second DCB.
We do a load. The "(START" means that the program will just
run without stopping for us to set breakpoints and type
"START" manually. This is the first time we didn't have to
put a break point. In all other programs, the only way we
could determine the results of the program was by inspecting
memory locations as we had no way to output the results.
After it is finished, we type the "test output"
Ignore the "CP SPOOL CONSOLE STOP" That just stopped the
logging of the console session into a file so that I could
print it out.
A shortcut to avoid typing the FILEDEF commands and the COPY
commands is to
put them into an EXEC file. Simply type everything that you
would like to in order to run your program into a file whose
file type is EXEC.
Include the following line at the beggining
/* */
Also put double quotes around any left or right parentheses.
Then type the file name for the exec file and the commands
in the EXEC file will be executed as if you typed them in.