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.