• Aucun résultat trouvé

FIXED BIN BASED{P);

Dans le document OS PL/I (Page 105-108)

ALLOCATE X;

X X

+

1;

The ALLOCATE statement sets a value in the pointer variable P so that the

reference X applies to allocated storage.

The references to X in the assignment statement are implicitly locator-qualified by P. References are explicitly locator-qualified as follows:

Q->X = Q->X + 1~

This assignment statement has the same effect as that of the previous example. A based variable can be declared without naming a pointer variable; in this case any reference to the based v~riable must always be explicitly locator-qualified.

(Note that PL/I allOWS a more general form of locator qualification than is described here; see "Multip1e Locator Qualification" at the end of this chapter.

However, the general form is not essential to an understanding of the remainder of this chapter.)

POINTER VARIABLES

A pointer variable is declared contextually i f i t appears in the declaration of a based variable, if i t appears as a locator

qualifier, or if i t appears in the SET option of an ALLOCATE, LOCATE, or READ

92 OS PL/I CKT AND OPT LRM PART I

statement. I t can also be declared explicitly as in the following example:

DeL Q POINTER;

Because Q is a variable i t must have a storage class; in this case, AUTOMATIC is applied by default. Note that a pOinter variable is a program control variable and therefore cannot be manipulated in the same way as arithmetic values. Pointer

variables can be collected in arrays and structures.

Pointer Expression

A pOinter expression is either a pOinter variable, which can be qualified or subscripted, or a function reference that returns a pOinter value.

A pointer expression can be used in the following ways:

1. As a locator qualifier, in association with a declaration of a based

variable.

2. In a comparison operation, for example in a IF statement (pointer values can be compared whether equal or not equal) •

3. As an argument in a procedure reference.

Setting Pointer Variables

,~

Before a reference is made to a pointer-qualified variable, the pOinter must have a value. A pointer value is obtained from any of the following:

1. The NULL built-in function.

2. The ADDR built-in function.

3. A READ or LOCATE statement.

4. An ALLOCATE statement.

All pOinter values are originally derived from one of these three methods. Such values can then be manipulated by

assignment that copies a pOinter value to a pOinter variable: by locator conversion that converts an offset value to a pOinter value, or vice versa; by passing the

pOinter value as an argument in a procedure reference; and by returning a painter value from a function procedure.

ADDR BUILT-IN FUNCTION

The ADDR built-in function returns a pOinter value that identifies the first byte of a variable. The variable can have any data type or organization and any storage class. For example:

P = ADDR(X);

where P is a pointer variable and X is any connected variable. The argument to the built-in function can be a subscripted qualified reference. For example:

DCL A(3,2) CHARACTER(S) BASED(P), B CHAR(S) BASED(Q),

C(3,2) CHARACTER(S);

P

=

ADDR(C);

Q ADDR(A(2,1»;

In this example, the arrays A and C refer to the same storage. The elements Band C(2,1} also refer to the same storage.

Notice that when a based variable is overlaid in this way no new storage is allocated - the based variable uses the same storage as the variable on which i t is overlaid (A(3,2) in the example).

This overlay technique can be achieved by use of the DEFINED attribute, but an important difference is that for DEFINED the overlay is permanent. When based

variables are overlaid, the association can be changed at any time in the program by assigning a new value to the pointer

variable. Note that although PLII does not permit the overlay of variables with

different data types, for example,

overlaying an integer with a bit string or overlaying a character string with a bit string, i t is possible in this

implementation.

However, i t should be understood that this type of programming is invalid use of PL/I, and the following points should be noted:

1. Unless the length of the bit string is a multiple of eight, data in the base variable may be corrupted when an assignment is made to the based variable when running under the optimizing compiler since this compiler produces optimum code from valid language.

2. Incompatibilities between the

attributes of the BASED variable and the attributes of the base variable, that is the variable being overlaid,

will be detected only when running under the checkout compiler with the NOCOMPATIBLE option.

The ADDR built-in function does not supply any information on the organization of a variable. Therefore, if the variable is an aggregate, i t should be in connected storage if i t is to be referenced as an entity. For example, if the variable is a cross-section of an array, the elements must not be interleaved. Furthermore, in this implementation, if the variable is a varying-length string or an area, control information is an integral part of the variable. A varying-length string is

prefixed by a two-byte length field, and an area is prefixed by 16 bytes of control intormation. Thus if the ADDR function is performed on these types of variable, the pOinter value identifies the start of the control information.

Other rules that apply to the use of the ADDR function are given in section G,

"Built-in Functions".

BASED VARIABLES AND INPUT/OUTPUT

Based variables can be transmitted using either stream-oriented or record-oriented transmission.

In the list-directed form of stream-oriented transmission, provided the based variables are locator-qualified (implici~ly

or explicitly), they are treated in the same way as other types of variable. For example:

GET LIST (P->X);

For data-directed transmission, however, only a based variable that has been associated with a locator expression in a declaration can be transmitted. For example:

DCL Y BASED(Q), Z BASED;

PUT DATA(Y);

The variable Z cannot be transmitted in a PUT DATA or GET DATA (that is, data-directed I/O) statement. Chapter 11

discusses the techniques and facilities of stream-oriented transmission.

Record-oriented transmission provides two processing modes: move mode, which moves data into or out of an allocated generation of a variable either directly or indirectly via a buffer; or, locate mode,

Chapter 8: Storage Control 93

which only moves the data into or out of a buffer and identifies the storage allocated within the buffer. Although based

variables can be transmitted using either mode, they are designed to be used with locate mode. Based variables are used in locate mode to describe the contents of a buffer, and therefore allow data to be processed while i t is in the buffer. Note that locate mode applies only to BUFFERED files: also, the files must be SEQUENTIAL, except for INPUT and UPDATE files

associated with key-sequenced VSAM d~ta

sets. Chapter 12, "Record-Oriented

Transmission," discusses the two modes more fully.

READ with SET Statement

In locate mode, the READ statement has the form:

READ FILE(file-expression) SET(element-pointer-variable):

This statement places a record in a buffer and identifies its location by setting the specified pointer variable. Any based variable qualified by this pOinter variable describes the contents of the buffer. For example:

DCL X CHAR(20) BASED(P), Y(20) CHAR (1) BASEDCP);

READ FILE(IN) SET(P):

In this program segment, a record is read into a buffer and the pOinter variable P identifies its location. The record in the buffer is treated simultaneously by the based variable X as a fixed-length

character string and by the based variable Y as an array of single characters. Note that P is declared contextually as a

pointer variable and that a reference to X or Y is implicitly qualified by P.

The next I/O operation on the file (including closing the file) frees the buffer.

LOCATE statement

The LOCATE statement complements the READ with SET statement and is used for output from a buffer. The form is:

LOCATE based-variable

94 OS PL/I CKT AND OPT LRM PART I

FILE (file-expression)

[SET (element-pointer-variable)]:

This statement allocates storage in a

buffer for a specified based variable. The SET option need only be specified if the based variable has not been associated with a pointer variable in a declaration.

The LOCATE statement operates

differently from all other transmission statements. Because the statement sets a pOinter to a storage address, there is nothing to transmit until values have been assigned to that storage. The LOCATE statement transmits the previous record

(i.e., the contents of storage obtained by a previous LOCATE statement), frees the storage for that record, and allocates storage for the next record. The current record is also transmitted if a WRITE or CLOSE statement is executed for the same fi1e. The following example shows the use of the LOCATE statement:

DCL 1 STR BASED(P), 2 NAME CHAR(20), 2 RATE FIXED(5,2):

OUTPUT:LOCATE STR FILE(OUT):

/*ASSIGN VALUES TO STR*/

GO TO OUTPUT:

Note: Because of the method of operation of the LOCATE statement, some care is

necessary when using i t with device-associated files, where a number of files are grouped together; no transmission can take place after anyone of the group has been closed. (See "Device-associated Fi1es," in chapter 12.)

By using locate mode the programmer can specify that a number of different forms of record be held in the same file. For

example:

DCL 1 STR1 BASED(Q), 2 CODE CHAR (1 ) , 2 X CHAR(30).

1 STR2 BASED(Q), 2 CODE CHAR(l), 2 XeS) FIXED BIN:

READ

FILE(IN) SET(Q):

IF STR1.CODE= '2' THEN DO:

I=Q->STR2.X(1):

END;

In this program segment each based structure has an element CODE that

identifies the structure. A record is read and its location is set in Q. Depending on

the value of CODE, the record can be

Dans le document OS PL/I (Page 105-108)