Sunteți pe pagina 1din 11

BASIC PL/1 LOCATE MODE I/O

MODULE 12 Page 0 of
8
BASIC PL/1 LOCATE MODE I/O
MODULE 12
Locate Mode I/O
MODULE 12 Page 1 of
8
BASIC PL/1 LOCATE MODE I/O
FILES, BLOCKS AND BUFFERS
The records we read in our programs are of many diferent sizes. One
day we may be reading a fle with 26-byte records, another day a fle with
3000-byte records. When data is stored on disk, there is an overhead in
splitting it up into too-small pieces. If we took our fle of 26-byte records
and put them individually on disk, then the overhead taken up by the
"gaps" in between the records would be about 90% of the disk capacity.
In real life, therefore, we assemble our data into much larger "blocks"
before writing it to disk. Even though we are using 200-byte records,
we'll group them together in groups of, say, 30 - to make a block of 6000
bytes. This 6000-byte block will be the unit that we'll write to and read
from the disk. Obviously we have to remember that every time we read
from the disk we get 30 records instead of 1, and we have to break down
the block accordingly. As PL/1 programmers, we don't need to do this,
because PL/1 and MVS together sort all this out for us, and when we
READ the fle we just get one 200-byte record.
MVS goes even further than this, by trying to ensure that our program
never has to wait for the next record to be available. It does this by
reading extra blocks ahead of our requirement, so that when we come to
want the next record it's almost certain to be available for us. When we
open a fle, MVS sets up a number of "bufers" for us - normally about 5.
Each of these bufers is an area of storage the size of a single block,
and as soon as the fle is open, MVS starts to fll these bufers with the
frst few blocks from the fle. As we read through the fle, then as soon
as we've read the last record in a block, MVS goes of to read the next
block of the fle into the bufer we've just fnished with.
It takes a signifcant amount of time to move a record from a bufer into
the INTO area in our program, and so PL/1 provides an alternative way
of READing (and WRITEing) which doesn't involve moving the record
out of the bufer. It's called LOCATE mode, as opposed to the "MOVE"
mode we've been using so far.
MODULE 12 Page 2 of
8 - 2 -
- 2 -
BASIC PL/1 LOCATE MODE I/O
With LOCATE mode, PL/1 does not move the record from the bufer into
our program, but leaves it where it is in the bufer. Instead it tells us the
address in main storage of the record, and allows us to use that address
to access the data in the record.
MODULE 12 Page 3 of
8
BASIC PL/1 LOCATE MODE I/O
Example:
DCL POI FILE INPUT RECORD
ENV(RECSIZE(200) TOTAL);
DCL POI_PTR POINTER;
DCL 1 POI_REC BASED(POI_PTR),
3 CODE CHAR(2),
3 A_C_TYPE CHAR(7),
3 A_C_MODEL CHAR(),
!!!
READ FILE(POI) SET(POI_PTR)
In this coding we have declared a variable, POI_PTR, with a new data
type attribute, POINTER, and have added another new attribute,
BASED(POI_PTR), to the declaration of POI_REC.
A POINTER variable is a data item that can only hold one type of data -
address data. We can do no processing with address data, but we will
see other things that we can do with it that we couldn't do with other data
types.
The BASED attribute is what PL/1 calls a Storage Class attribute. It's
not concerned with the type of data we can put into a variable, but, like
DEF, is concerned with the way that variable is to exist in storage. We
will cover BASED in more detail later in the course, but for now we will
be adequately served by:
POI_REC has a POINTER variable on which it is BASED. At any time
that we refer to the BASED variable, PL/1 will look at the value of the
POINTER variable to discover where that BASED variable is in storage.
All that remains is to discover ways in which we can place an address
value into a POINTER variable. One of the ways is the one which you
see above in the READ statement.
Instead of saying to PL/1 - "go and fnd the next record from the fle and
place it in the storage occupied by my variable x" we are saying - "go
MODULE 12 Page 4 of
8 - 4 -
- 4 -
BASIC PL/1 LOCATE MODE I/O
and fnd the next record from the fle and place its address in the pointer
variable called x"
In the above case, after the READ, no data will have been moved from the fle
bufer into my program, but PL/1 will have set my variable POI_PTR to the
address of the data in the bufer. Remembering the meaning of BASED, we
can see that the coding:
IF POI_REC!CODE " #AA#
means "First fnd POI_REC. Do that by looking at the POINTER
variable POI_PTR, and its value will give the address of POI_REC.
Having found POI_REC, then the element CODE can be found at its
beginning."
So our reference to POI_REC.CODE will not be to the value in a piece of
storage in our program, but to two bytes of storage that are in the bufers
for fle POI. In this way we can still access the whole of the incoming
record without moving the data and without having to set up any storage
in our program.
In fact most of the input that we do in our PL/1 programs will be
done using BASED variables and the SET version of the READ
statement.
LOCATE STATEMENT
As well as the READ ... SET statement for input, there is a LOCATE
statement for output. This is much less frequently used, and will be left
until later in the course, where we will see a particular use for it.
MODULE 12 Page 5 of
8
BASIC PL/1 LOCATE MODE I/O
THE REWRITE STATEMENT IN LOCATE MODE
When we frst saw the REWRITE statement, it followed a READ ... INTO
statement, so the data for the record was in one of our variables. We
therefore specifed that variable in our REWRITE statement.
If we have executed a READ ... SET statement, then the data has not
been moved into our variable, but is still in the bufer. If we are dealing
with an UPDATE fle and wish to rewrite the last record at which we
looked, then we issue a REWRITE statement without a FROM option.
RE$RITE FILE(%%Y);
PL/1 assumes that we have made all the changes we need to directly in
the bufer, using the appropriate BASED variables, and so simply marks
that record for rewriting.
IMPORTANT. If the fle is blocked, as almost all will be, then
rewriting the record will be done by rewriting the complete block.
This means that if we have changed another record in the block,
even if we executed no rewrite statement for that record, the
changed data will still be written to the fle. If we do change the
data in the bufer for an UPDATE fle, then we should set it back to
its original value if we don't want the dataset changed.
MODULE 12 Page 6 of
8 - 6 -
- 6 -
BASIC PL/1 LOCATE MODE I/O
THE NULL BUILT-IN FUNCTION
This function takes no arguments, and returns an address which is not
the address of anything. It is the only value we can put into a POINTER
variable and check for later. (the only comparisons available for address
data are equals and not equals.
We can therefore code
DCL P PTR;
P " NULL;
IF P " NULL
THEN !!!
We will see more use for NULL in a later unit.
MODULE 12 Page 7 of
8
BASIC PL/1 LOCATE MODE I/O
POINTER ATTRIBUTE (ABBREV. PTR)
This is a data type attribute, which conficts with FIXED, DEC, BIN,
CHAR, BIT.
POINTER variables may be structure elements, but this is rarely
required in their basic use.
POINTERs can only hold "address data", and cannot be converted to
or from any other data type.
A variable can receive the POINTER attribute contextually through
the use of its name in the BASED attribute. This should not occur, as
British Airways standards demand that all variables in the program
be explicitly declared.
BASED ATTRIBUTE (1)
This attribute may be given only to a variable with a level number of 1 or
with no level number.
FORMAT& BASED(PTR_NAME)
PTR_NAME is the name of an element variable with the attribute
POINTER.
Efect: The BASED variable is given no storage of its own
by PL/1. Instead it relies on the programmer assigning to PTR_NAME a
valid address. Any reference to a variable with the BASED attribute will
involve reference to the value of the POINTER variable. The value of
the POINTER will give the address in storage where the BASED variable
will be found.
If a program attempts to refer to a BASED variable when the associated
POINTER variable does not have a value then an error may occur.
MODULE 12 Page 8 of
8 - 8 -
- 8 -
BASIC PL/1 LOCATE MODE I/O
READ ... SET STATEMENT
FORMAT& READ FILE(FNAME) SET(PNAME);
Rules:
FNAME must be a name with attributes FILE INPUT RECORD or FILE
UPDATE RECORD.
PNAME must be the name of a variable with attribute POINTER.
Efect:
The next record is read from the fle FNAME. The data is not moved from the
input bufer, but the address of the record in storage is placed in PNAME.
If the execution of the READ statement causes an end-of-fle situation, the
value of PNAME is undefned - and may not be used. Neither, therefore, may
any variables BASED on PNAME.
REWRITE STATEMENT
FORMAT 2& RE$RITE FILE(FNAME);
Rules:
FNAME must be a name with attributes FILE UPDATE RECORD.
The last operation on the fle FNAME must have been a READ ...
SET.
Efect:
The last record read is re-written to the fle. As no record area is
specifed in this form of the REWRITE statement, PL/1 assumes that the
changes to the record have been made to the copy of the record that is
in the bufer.
WARNING:
MODULE 12 Page 9 of
8
BASIC PL/1 LOCATE MODE I/O
Because of the way in which records are grouped together into blocks,
the block will be rewritten if any of the records in it had a PL/1 REWRITE
statement executed for them. The efect of this is that any changes
made in the bufer to other records will also be made on the dataset. If
you modify a record in the bufer for an UPDATE fle, but decide not to
write that modifcation to the dataset, then restore the original data
before moving on to the next record.
MODULE 12 Page 10
of 8 - 10 -
- 10 -

S-ar putea să vă placă și