This chapter explains how label prefixes and DECLARE statements are used for declarations, and also describes the attributes that can be used in a DECLARE statement.
All variables in an Open PL/I program (except those under the control of the DEFAULT statement) must be declared. Each name, except the name of a built-in function, must be declared using a DECLARE statement (or if it is a label, by using the label as a statement prefix).
Each declaration is associated with a scope or region of the program in which a reference to the associated name is valid. The scope of a declaration includes the block in which it is declared and all nested blocks, except those in which the name has been redeclared.
Identifier attributes used in DECLARE statements are specified by either keyword or syntax. A name declared with the EXTERNAL attribute has the same scope rule as any other name, except that the object identified by that name is unique throughout the entire program. All declarations of a given name that have the EXTERNAL attribute identify the same object. Only files, static variables, and names of external procedures can have the EXTERNAL attribute. Files and procedures acquire the attribute by default, but static variables have internal scope unless they are explicitly declared with the EXTERNAL attribute.
A given name cannot be declared more than once within the same block, unless it is declared as the name of a structure member. In that case, the name may be redeclared within the same block, provided no two members at the same level of the same structure have the same name. (See the section Scope.)
A label prefix declares a name as a procedure name, format name, or statement label, depending on the type of statement to which the prefix is attached.
A label prefix on a PROCEDURE statement declares a name as a procedure name. The name is declared in the block that contains the PROCEDURE statement, and its scope is that containing block and all blocks contained by the procedure. The declaration lists each parameter referenced by the PROCEDURE statement, as well as the data type specified by any RETURNS option in the PROCEDURE statement. For example:
E: PROCEDURE(A,B) RETURNS(POINTER); DECLARE A FIXED BINARY; DECLARE B FLOAT DECIMAL;
In this example, E is declared as a procedure name in the block that contains the PROCEDURE statement. The attributes of that declaration are RETURNS(pointer) and ENTRY(fixed binary, float decimal).
The label prefix on a FORMAT statement declares a name as a format name. The name is declared in the block that contains the FORMAT statement and all contained blocks. A format name is not a statement label and cannot be used in a GOTO statement. A format name can be used only in a format statement, as described in the section FORMAT Statement.
The label prefix of a PROCEDURE or FORMAT statement cannot be sub- scripted.
A label prefix attached to statements other than PROCEDURE or FORMAT statements declares a name as a statement label. The declaration is established in the block that contains the statement to which the prefix is attached. For example, a label prefix attached to a BEGIN statement is declared in the block that contains the BEGIN statement and its scope is that containing block and all blocks contained by the BEGIN statement.
The label prefix of a PROCEDURE or FORMAT statement cannot be sub- scripted; however, label prefixes attached to statements other than PROCEDURE or FORMAT may be subscripted by a single optionally signed integer constant. Within its scope, all occurrences of a given name used in this manner must be subscripted, and all such prefixes collectively constitute a declaration of the name as an array of statement labels. For example:
GOTO CASE(K); CASE(1): . . . CASE(2): . . . CASE(3): . . . CASE(6): . . .
In this example, CASE is declared as an array of statement labels whose bounds are (1:6) and whose fourth and fifth elements are undefined. Defining arrays with undefined elements is not recommended, as it produces unpredictable results.
An array of statement labels cannot be used as an array value, but its elements can be used in any context that permits a statement label.
Procedure names, format names, and statement labels cannot be declared in a DECLARE statement in the same block, except that the names may be used as the structure member names.
Names of external procedures that are part of another program module must be declared by a DECLARE statement if they are to be referenced by the current program module. (For more information, see the section Modules.) Only external procedure names can be declared by a DECLARE statement.
A DECLARE statement declares one or more names by giving the attributes or properties of the named objects. A DECLARE statement is not an executable statement. It may appear as a part of a WHEN or OTHERWISE clause in a SELECT statement; anywhere within a procedure or BEGIN block, except as the THEN clause or ELSE clause of an IF statement; or as an ON-unit of an ON statement.
For the sake of readability, all DECLARE statements belonging to a given block should be placed at the beginning of that block, rather than among the executable statements.
This section describes the recommended forms of the DECLARE statement within the following statement categories: simple declarations, factored declarations, and structure declarations.
A simple declaration defines a single name and describes its attributes. Its recommended form is:
DECLARE name a⊂1 a⊂2 a⊂n;
where name is the declared name and a1 through an are attributes. For example:
DECLARE A FIXED BINARY(15); DECLARE B CHARACTER(10) VARYING STATIC INITIAL('ABC'); DECLARE C DIMENSION(5) FLOAT DECIMAL(7);
The last statement in this example could also be given without the keyword DIMENSION by using the following format:
DECLARE C(5) FLOAT DECIMAL(7);
Factored declarations define two or more names having the same attributes. The recommended form of a factored declaration is:
DECLARE (name-1[,name-2]…)a⊂1 a⊂2…a⊂n;
where each name is declared to have all of the attributes a⊂1 through a⊂n. In factored declarations, the names must be enclosed in parentheses.
DECLARE (A,B,C) FIXED BINARY(15); DECLARE (P,Q) POINTER STATIC INITIAL(NULL); DECLARE (X,Y)(5) FLOAT DECIMAL(7);
The last example is equivalent to the following statement:
DECLARE (X,Y) DIMENSION(5) FLOAT DECIMAL(7);
The bounds must be the first attribute in an attribute list if they appear without the DIMENSION keyword.
The declaration of a structure defines the organization of the structure and the names of members at each level of the structure. The general form of this declaration is:
DECLARE 1 structure_name a⊂1 a⊂2 … a⊂n, k member_name-1 a⊂1 a⊂2 … a⊂n, k member_name-2 a⊂1 a⊂2 …. a⊂n, . . . k member_name–m a⊂1 a⊂2 … a⊂n;
where each member_name specifies a member of the structure preceded by a level-number, k, and where the level-number of each member must be greater than the level-number of its containing structure, equal to level-numbers of members at the same level, and less than the level-numbers of members it contains. The major structure name is declared as structure level 1.
The only attributes given to the structure itself are storage class, ALIGNED, UNALIGNED, DIMENSION, REFER, and UNION. Each member is declared to have all attributes following its name up to the next comma or up to the end of the statement. For example:
DECLARE 1 S STATIC, 2 A(5) FLOAT DECIMAL(7), 2 B FIXED BINARY(15), 2 C, 3 D POINTER, 3 E CHARACTER(10) INITIAL('ABC');
In this example, S is a static structure with members A, B, and C. C is a substructure with members D and E. Initial attributes can be given to elementary members of static structures, but not to structures themselves.
Following is the general form of the DECLARE statement:
DECLAREd⊂1[,d⊂2 …];
or
DCL d⊂1 [,d⊂2 …];
where each d is:
[k]name a⊂1 a⊂2 … a⊂n
or
[k](d⊂1[,d⊂2]…)a⊂1 a⊂2 … a⊂n
where k is an optional level number, each a is an attribute, and name is a name to be declared.
DECLARE ((A FIXED, B FLOAT) DECIMAL, C BIT) STATIC; DECLARE 1 S STATIC, 2 (A FIXED, B FLOAT) INITIAL(0);
These examples illustrate more factored declarations, as indicated by the fact that the DECLARE statements contain parenthetical lists of names. Factored declarations can be transformed into nonfactored declarations by copying the level number and attribute list of the innermost set of parentheses onto each name contained within the parentheses, removing the parentheses, and repeating this process with the next set of parentheses.
After defactoring, the previous examples are:
DECLARE A FIXED DECIMAL STATIC; DECLARE B FLOAT DECIMAL STATIC; DECLARE C BIT STATIC; DECLARE 1 S STATIC, 2 A FIXED INITIAL(0), 2 B FLOAT INITIAL(0);
Factored declarations, other than as shown in the recommended form (see the section Factored Declarations) are generally more difficult to read than their unfactored equivalents.
If defactoring produces more than one level number for a given name, even if the level numbers are equal, the factored declaration is invalid and causes the Compiler to issue an error message.
Specification of duplicate attributes containing more than a simple keyword is also invalid, even when the attributes are exact duplicates.
If the attributes specified for a name in a DECLARE statement are incomplete, the missing attributes can be supplied either by the Compiler or by the user with the DEFAULT statement.
The Compiler supplies the required additional attributes, as follows:
Specified | Missing | Supplied |
---|---|---|
binary | fixed | float | fixed |
decimal | fixed | float | fixed |
fixed | binary | decimal | decimal |
float | binary | decimal | decimal |
static | internal | external | internal |
bit | length | length of one |
character | length | length of one |
area | size | size of 1000 |
Defaults are also supplied for the following conditions.
You can change Compiler-supplied defaults, or you can apply a completely new set of default attributes, using the DEFAULT statement. The DEFAULT statement is explained in the section DEFAULT.
After default attributes have been supplied, each declaration is checked by the Compiler for consistency and completeness.
If no data type is specified, either explicitly or by the DEFAULT statement, the declaration is invalid and incomplete. The Compiler issues an error message and supplies a type of Fixed Binary(15) for names beginning with any of the letters I through N, and Float Decimal(6) for names beginning with any other alphabetic character.
A declaration is inconsistent and invalid if it specifies more than one data type or more than one storage class. Table 4-1 lists the valid data types. Table 4-2 lists the valid storage classes.
Fixed Binary(p) |
Fixed Decimal(p[,q]) |
Float Binary(p) |
Float Decimal(p) |
Picture |
Character(n) [Varying] |
Bit(n)[Aligned] |
Pointer |
Offset |
Area |
Label |
Entry [returns][variable] |
File [variable] |
Builtin |
Structure |
automatic |
based or based(pointer-reference) |
static internal |
static external |
defined(reference) |
parameter |
member of structure |
A declaration is also inconsistent and invalid if it violates the following attribute-specific restrictions:
This section describes, in alphabetical order, the attributes that are permitted in a DECLARE statement.
The discussion of each attribute assumes that the attributes have been made complete by the application of defaults, as described in the section Defaults.
Each attribute discussed in this section falls into one of the following categories:
Note: File description attributes specified in a DECLARE statement apply to all openings of the file control block associated with the file constant. For further discussion of these attributes, see the sections Input and Output and OPEN Statement.
ALIGNED is a data type attribute that controls the storage boundary of data.
ALIGNED is an optional part of the data type specification. Its presence allows the Compiler to align the data on an implementation-defined storage boundary, with the possible side effect that more bits or bytes of storage are used than specified by the declared length.
For more information on this attribute, see the sections ALIGNED and UNALIGNED Attributes and Bit-String Data. For more information on data alignment in general, see your Open PL/I User's Guide.
The ANY attribute specifies that the corresponding argument for a parameter can be of any data type. The ANY attribute is applicable only to the declaration of entry names and is valid only in a parameter descriptor. ANY is not valid as an attribute in a PROCEDURE or ENTRY statement.
For more information about the ANY attribute, see the section ENTRY.
AREA is a non-computational data type attribute used to define a region of storage in which based variables can be allocated and freed. The format is:
AREA[(exp[REFER(variable)])]
or
AREA(*)
For a complete description of area data and the use of the AREA attribute, see the section Area Data.
Abbreviation: AUTO
AUTOMATIC is a storage class attribute that specifies that the declared name is a variable that is allocated storage with each activation of its containing procedure or BEGIN block.
The AUTOMATIC attribute is supplied by default to any name of a non-parameter variable that is not a member of a structure and that has no storage class.
For more information on this attribute, see the section Automatic Storage.
BASED is a storage class attribute that specifies that the declared name is a based variable. Its format is:
BASED[(r)]
In the optional form, r is a reference to a locator variable or a locator-valued function that serves as the default (implicit) locator qualifier for unqualified references to the name.
For more information on this attribute, see the section Based Variables.
Abbreviation: BIN
BINARY is an arithmetic data type attribute that specifies that the base is binary. Its format is:
BINARY[(p)]
The precision p may be supplied with the BINARY attribute or with the FIXED or FLOAT attribute, but it cannot be specified twice. The precision p must be a positive integer. If no precision is specified, a default precision is supplied. For information on the default precisions, see your Open PL/I User's Guide and the section DEFAULT Statement in this manual.
If BINARY is specified without FIXED or FLOAT, FIXED is assumed.
When used with FIXED, BINARY specifies integer arithmetic values that contain at least p bits.
When used with FLOAT, BINARY specifies floating-point arithmetic values that have a mantissa that contains the equivalent of at least p bits.
For more information about the BINARY attribute, see the section Arithmetic Data.
BIT is a bit-string data type attribute that identifies a variable as a bit-string variable. Its format is:
BIT[(n)]
Length n is an extent expression or integer constant, depending on the storage class of the declared name. The length n must be a non-negative integer constant or an expression that evaluates to a non-negative integer. A default length of 1 is supplied if no length is given.
For more information on BIT, see the chapter Storage Classes and the section Bit-String Data.
BUILTIN is an entry name attribute that indicates that the declared name is a built-in function. Unless an empty argument list is used in a reference to a built-in function having no parameters, the function must be declared with the BUILTIN attribute.
BUILTIN can be used to redeclare a built-in function name that was declared as something else in an outer block. The declared name must be one of the names given in the chapter Open PL/I Built–Ins.
Abbreviation: CHAR
CHARACTER is a character-string data type attribute that identifies a variable as a character-string variable. Its format is:
CHARACTER[(n)]
Length n is an extent expression or integer constant, depending on the storage class of the declared name. The length n must be a non-negative integer constant or an expression that evaluates to a non-negative integer. A default length of 1 is supplied if no length is specified. For a discussion of storage classes, see the section Character-String Data and the chapter Storage Classes.
Abbreviation: COND
CONDITION is an attribute that indicates that the declared name is a condition name. Its format is:
CONDITION
Condition names can be used only in ON, SIGNAL, or REVERT statements. The default scope of condition name is external. Note that a name that appears with the CONDITION condition in an ON, SIGNAL, or REVERT statement is contextually declared to be a condition name.
For more information about the usage of condition name, see the section ON CONDITION(name).
Abbreviation: CONN
The CONNECTED attribute may be used only for parameters. It cannot be specified for a member of a structure and it cannot be specified for CONTROLLED parameters. The CONNECTED attribute asserts that any argument passed to the parameter is in connected storage.
Abbreviation: CTL
CONTROLLED is a storage class attribute that specifies a variable whose storage is dynamically allocated and freed in generations. Its format is:
CONTROLLED
For more information on this attribute, see the section Controlled Variables.
Abbreviation: DEC
DECIMAL is an arithmetic data type attribute that specifies that the base is decimal. Its format is:
DECIMAL[(p[,q])]
The precision p,q (q is optional and represents fractional digits) may be supplied with the DECIMAL attribute or with the FIXED or FLOAT attribute, but it cannot be specified twice. The precision p and the scale q (if specified) must be positive integers. If a precision or scale is not specified, a default is assumed. For more information on default precisions, see your Open PL/I User's Guide and the section DEFAULT.
If DECIMAL is supplied without FIXED or FLOAT, FIXED is the default. If FIXED or FLOAT is specified without BINARY or DECIMAL, DECIMAL is the default.
When used with FIXED, DECIMAL specifies fixed-point arithmetic values that contain at least p decimal digits. If q is specified, p minus q digits are integral digits and q digits are fractional digits. If q is omitted, q = 0 is assumed. These values are integers containing at most p decimal digits.
When used with FLOAT, DECIMAL specifies floating-point arithmetic values whose mantissa contains the equivalent of at least p decimal digits. In this case, q cannot be specified.
For more information about the DECIMAL attribute, see the section Arithmetic Data.
Abbreviation: DEF
DEFINED is a storage class attribute that specifies that the declared name is a defined variable that shares storage with a basis variable. Its format is:
DEFINED(r)
where r is the basis variable.
For more information about this attribute, see the section Defined Variables.
Abbreviation: DIM
DIMENSION is an attribute that specifies that a declared name is an array and defines the number and extent of its dimensions. Its format is:
DIMENSION(b1[,b2]…)
Each b represents one bound pair, which specifies the number of elements in a single dimension of the array. Each bound pair specifies an optional lower bound (lb) and a requisite upper bound (hb) for that dimension. A bound pair can be specified as follows.
* | The asterisk format of a bound pair, when used to define a parameter for a procedure or function, specifies that both the upper and lower bound of this dimension are to be taken from the corresponding array argument. If one bound pair is specified as asterisks, all bound pairs must be specified as asterisks. |
lb:hb | This format specifies the minimum and maximum subscripts that can be used for the dimension. lb is an extent expression or optionally signed integer constant, depending on the storage class of the array, which specifies the lower bound of the dimension. Like lb, hb is either an extent expression or an optionally signed integer constant, depending on the storage class. It specifies the upper bound of the dimension. |
hb | This format specifies only the upper bound of the dimension. The lower bound is assumed to be 1. |
For example:
DECLARE X(5) FLOAT; DECLARE Y DIMENSION(5) FLOAT;
In this example, both X and Y are arrays of five floating-point values.
The DIMENSION attribute is normally written immediately after the variable's name and is written without the DIMENSION keyword.
When specified with the FILE or ENTRY attributes, DIMENSION causes the associated name to become a variable rather than a named constant.
DIRECT is a file description attribute that indicates that a file can be accessed nonsequentially, that is, by key or by relative record number.
The DIRECT attribute may be given either in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable.
ENTRY is a data type attribute that declares a constant or variable whose value is an entry point, and describes the attributes of the parameters, if any, that are declared for the entry point. Its format is:
ENTRY [([parameter-list])]
where parameter-list is:
()|parameter-descriptor[,parameter-descriptor]...
where parameter-descriptor is:
attribute[attribute] ... |*|,|structure-descriptor
where structure-descriptor is:
1 [attribute] ... ,level[attribute] ... [,level[attribute]] ...
An arbitrary parameter-descriptor can be indicated by use of an asterisk ( * ) or by a blank parameter-descriptor position, as indicated by the commas. For example,
ENTRY(FIXED BIN, , FLOAT /* Three parameters. The second is of any data type. */ ENTRY(FIXED BIN, * ,FLOAT)/* Three parameters. The second is of any data type. */ ENTRY(, , ,) /* Four parameters of any data type. */ ENTRY() /* No parameters allowed. */ ENTRY /* Any number of parameters is allowed. */
The ENTRY attribute without the RETURNS option has an implicit RETURNS data type. It is determined by the I–n rule. External entries with the implicit RETURNS can be called as functions or procedures.
Open PL/I does not require that if any entry statement in a multiple entry procedure has a RETURNS option, then all entries must have one.
ENTRY can be used with or without the VARIABLE attribute. Used without the VARIABLE attribute, the ENTRY attribute declares a constant that is the name of an external procedure. In this case, each p is a list of attributes that is either identical to the attributes specified for the corresponding parameter in the external procedure, or is ANY. For example:
DECLARE E ENTRY(FIXED BINARY(15), POINTER);
In this example, E refers to a procedure that accepts a fixed binary and a pointer argument.
Used with the VARIABLE attribute, the ENTRY attribute specifies that the declared name is a variable of the data type entry, which can be assigned any procedure name. When the entry variable is called, it must hold an entry value that designates a PROCEDURE statement whose parameters have attributes that are identical (unless the attribute is ANY) to the corresponding attributes given by p1, p2, and so forth. Using the declaration for E from the previous example, a compatible procedure declaration would be as follows:
E: PROCEDURE(X,Y); DECLARE X FIXED BINARY(15); DECLARE Y POINTER;
If a PROCEDURE statement has one or more parameters that are structures, the ENTRY attribute used to declare the procedure name must have a set of attributes for each member of the structure, including all substructures, as shown in the following example:
DECLARE E ENTRY(1,2 FIXED, 2 FLOAT, POINTER);
In the previous example, E is a procedure having two parameters; the first parameter is a structure with two members, and the second parameter is a pointer. The parameter attributes given in the ENTRY attribute include the level numbers and attributes of all members, as well as the level number and attributes of the parameter structure.
All string lengths or array bounds given in an ENTRY attribute must be exactly the same as those given in the parameters of the PROCEDURE statement. Programs that violate this rule may produce unpredictable results.
The ENTRY attribute can be used with the ANY, OPTIONS(VARIABLE), RETURNS(returns_descriptor), and VALUE options according to the following format:
DECLARE entry_nameENTRY[(parameter_descriptor[VALUE]…)] [OPTIONS(VARIABLE)] [RETURNS(returns_descriptor)];
The RETURNS attribute is required for entry points that are invoked by function references and is invalid for procedures invoked by CALL statements. Parameter descriptors are not allowed if the ENTRY attribute is within a RETURNS descriptor.
The parameter descriptor lists attributes for each parameter and must include either the data type of the parameter or the attribute ANY. The VALUE attribute indicates that the corresponding argument is to be passed by immediate value. The OPTIONS(VARIABLE) option indicates that the specified external procedure can be invoked with a variable number of arguments. The following options can be specified as part of the OPTIONS(VARIABLE) attribute when declaring an ENTRY:
The RETURNS(retums_descriptor) option gives the data type attributes of the function value returned for an entry invoked as a function reference. The VARIABLE attribute is not valid in a parameter descriptor or in a RETURNS descriptor.
The VALUE attribute can be used in an ENTRY declaration in conjunction with the data types Fixed Binary, Pointer, Character, Aligned Bit, Entry, or Float Binary. For more information, see the section VALUE.
If the ANY attribute is included as a parameter descriptor, the argument that corresponds to that parameter descriptor can be of any data type. If the argument is a variable, its address is passed to the called procedure. If the argument is a constant or an expression, a dummy argument is created and its address is passed to the called procedure. The following conversions take place when creating the dummy argument:
Written Data Type | Dummy Data Type |
---|---|
Bit (Unaligned) | Bit(n) Aligned, where n is the length of the string |
Fixed Binary or Fixed Decimal(p,O) | Fixed Binary(31) |
Char Varying | Char(n), where n is the length of the string |
For more information, see the chapter Storage Classes and your Open PL/I User's Guide.
The OPTIONS(VARIABLE) attribute is used to indicate that it is valid for a discrepancy to exist between the number of parameter descriptors in the declaration of the procedure and the number of arguments in the argument list used to call the procedure.
The following rules apply when using the OPTIONS(VARIABLE) option:
The following examples show how the ENTRY attribute can be used with the VALUE, ANY, OPTIONS(VARIABLE), and RETURNS(retums_descriptor) options. For a further description of these options, refer to each option by name within this chapter.
The following example causes the value of A to be converted to Fixed Binary(31) and the immediate value (25) to be passed directly to P5, followed by an immediate value representing the address of A:
DECLARE P5 ENTRY (FIXED BIN(31) VALUE, POINTER VALUE), A FIXED BIN(15), B POINTER; A = 25; B = ADDR (A); CALL P5(A,B);
The following example illustrates the use of the ENTRY attribute with the OPTIONS( VARIABLE) and ANY options:
DECLARE P1 ENTRY (FIXED BINARY(15), ANY) OPTIONS(VARIABLE), A FIXED BINARY(15), B FLOAT BINARY(23), C CHARACTER(1); CALL P1(A, B); CALL P1(A, C, B);
In the previous example, the second parameter descriptor is declared as ANY. In the first call to P1, B, a Float Binary(23) variable is the second argument passed; in the second call to P1, C, a Char(1) variable is passed. In both calls, the variable is passed by reference. Since the OPTIONS(VARIABLE) attribute is used, the second call to P1 passes argument three, B, using the attribute for parameter descriptor two, ANY. In the second call, the variable B is passed by reference.
The following example illustrates a procedure called with some arguments omitted.
DECLARE P2 ENTRY (FIXED BINARY(15), FIXED BINARY(15), FIXED BINARY(15)) OPTIONS(VARIABLE), (A,B) FIXED BINARY(15); CALL P2(A, ,B);
In the previous example, the arguments to be passed are A, a missing argument, and B. This configuration causes the address of A to be passed, followed by a null value, followed by the address of B.
The following example illustrates a procedure called with more arguments than there are parameter descriptors:
DECLARE P3 ENTRY (FIXED BINARY(15),FIXED BINARY(15)) OPTIONS(VARIABLE), (A,B) FIXED BINARY(15), C FLOAT BINARY(31); CALL P3 (A, B, ,); CALL P3 (A, B, C);
In the previous example, the first call to P3 is declared with two parameter descriptors and called with four arguments, the last two being null. The addresses of the last two arguments will be represented by null values. The second call to P3 passes C as a Fixed Binary(15), since it is a trailing argument and is passed with the attribute of the last parameter descriptor. This configuration requires that C be converted from Float Binary to Fixed Binary, and that the address of the resulting temporary be passed.
The following example illustrates constants and expressions being passed with the ANY option:
DECLARE P4 ENTRY (ANY,ANY), ( A, B ) FIXED BINARY(15); CALL P4( 3, 'ABC'); CALL P4( '1'B, AB );
In the first call to P4, the constant 3 will be converted to Fixed Binary(31) and the address of the temporary variable containing the converted value will be passed as the first argument; the character-string constant 'ABC' will be converted to Character(3) and its temporary address passed as the second argument. In the second call to P4, the bit-string constant '1' B will be converted to Bit(1) Aligned, AB will be converted to Fixed Binary(31), and the respective addresses of the temporaries will be passed to P4.
The following example illustrates the use of the RETURNS(retums_descriptor) option:
DECLARE F ENTRY(FIXED) RETURNS(POINTER); DECLARE G ENTRY(FLOAT) RETURNS(CHARACTER(32)VARYING);
In this example, F is declared as the name of a function procedure that returns pointer values. G is declared as the name of a function procedure that returns varying character-string values whose maximum length is 32 characters.
Abbreviation: ENV
The ENVIRONMENT attribute and its options specify many record characteristics that are not part of the PL/I language. Its format is:
ENVIRONMENT(options–list)
options-list can contain any of a number options specifying record characteristics. For example,
ENVIRONMENT(VSAM KEYLOC(1) KEYLENGTH(12));
The available options are detailed in the section Record I/O. The ENVIRONMENT attribute is not supported for use with a STREAM file.
Abbreviation: EXCL
The EXCLUSIVE attribute specifies that the records in a file can be locked when accessed by one process to prevent access by another process. When the EXCLUSIVE attribute is used, the entire file is locked.
Abbreviation: EXT
EXTERNAL is a scope attribute that specifies that the declared name has external scope. This means that all declarations of this name anywhere in the program that also have the EXTERNAL attribute identify the same object.
The EXTERNAL attribute can be used only in the declaration of variables whose storage class is STATIC or CONTROLLED. (It can be redundantly specified for variables of storage classes GLOBALDEF and GLOBALREF, which are implicitly EXTERNAL STATIC.) If EXTERNAL is specified for a variable and no storage class attribute is specified, STATIC is supplied by default. Its format is:
EXTERNAL[(global_name)]
global_name is either a character-string constant or a %REPLACE name for a character string constant. global_name is used by the linker when references are made to the entry. Open PL/I makes no restrictions on the contents of global_name, but the underlying operating system may have restrictions.
EXTERNAL must be specified when the entry is declared in another module. EXTERNAL(global_name) is specified as an option either on a PROCEDURE statement or on an ENTRY statement.
By using the EXTERNAL(global_name) option, an alternative name can be specified for an external entry constant. Instead of the usual entry constant name, the alternative name (global_name) is used to invoke the procedure at the entry point.
OZS: PROCEDURE; DECLARE PROC1 ENTRY; DECLARE ALSO_PROC1 ENTRY EXTERNAL('PROC1'); DECLARE PROC2 ENTRY EXTERNAL('ILL.EGAL'); CALL PROC1; CALL ALSO_PROC1; CALL PROC2; END OZS; /*======== A SEPARATE MODULE ========*/ PROC1: PROCEDURE; PROC2: ENTRY EXTERNAL('ILL.EGAL'); END PROC1;
In this example, the program declares explicitly the entry constants PROC1 and PROC2.
FILE is a data type attribute. Used without the VARIABLE attribute, it specifies that the declared name is a file identifier having external scope and an associated file control block that can be used to perform I/O on files and devices known to the operating system. In this case, the EXTERNAL attribute and any of the file description attributes RECORD, STREAM, INPUT, OUTPUT, UPDATE, KEYED, DIRECT, SEQUENTIAL, and PRINT may also be specified. Any file description attributes specified in the declaration are merged with attributes supplied by the OPEN statement or attributes implied by the I/O statement that implicitly opens the file control block.
Used with the VARIABLE attribute, FILE specifies that the declared name is a file variable that can be assigned file values. In this case, the file description attributes cannot be supplied because a file variable has no associated file control block until a file value is assigned to it. File description attributes are attributes of a file control block and are not attributes of a file value or file variable.
Some attributes for a name declared implicitly can be determined from the context in which the name appears. These cases are called contextual declarations. A name that appears in a FILE option, or in an ON, SIGNAL, or REVERT statement for a condition that requires a file name, is given the FILE attribute. For example,
OPEN FILE(F); WRITE FILE(W) FROM(BUF); READ FILE®) INTO(BUF); CLOSE FILE©);
In all four above cases the names used with the FILE option will be implicitly declared as having File data type.
FIXED is an arithmetic data type attribute that defines a fixed-point arithmetic variable. Its format is:
FIXED[(p[,q])]
The precision p,q (q is optional and represents fractional digits) may be supplied with this attribute or with the BINARY or DECIMAL attribute, but it cannot be specified twice. The precision p and the scale q (if specified) must be positive integers. If a precision or scale is not specified, a default is assumed. If FIXED is specified without BINARY or DECIMAL, DECIMAL is assumed. For details on precisions, see your Open PL/I User's Guide and the section DEFAULT in this manual.
When used with BINARY, FIXED specifies integer arithmetic values that contain at least p bits. In this case, q must not be specified.
When used with DECIMAL, FIXED specifies fixed-point arithmetic values that contain at least p decimal digits. If q is specified, p minus q digits are integral digits and q digits are fractional digits. If q is omitted, q = 0 is assumed. These values are integers containing at least p decimal digits.
See the section Arithmetic Data.
FLOAT is an arithmetic data type attribute that defines a floating-point arithmetic value. Its format is:
FLOAT[(p)]
The precision p may be supplied with this attribute or with the BINARY or DECIMAL attribute, but it cannot be specified twice. The precision p must be a positive integer. If a precision is not specified, a default precision is assumed. for information on the Open PL/I default precisions, see your Open PL/I User's Guide and the section DEFAULT in this manual.
If FLOAT is specified without BINARY or DECIMAL, DECIMAL is the default. If BINARY or DECIMAL is supplied without FIXED or FLOAT, FIXED is the default.
When used with BINARY, FLOAT specifies floating-point arithmetic values whose mantissa contains the equivalent of at least p bits.
When used with DECIMAL, FLOAT specifies floating-point arithmetic values whose mantissa contains the equivalent of at least p decimal digits.
See the section Arithmetic Data.
GLOBALDEF is a storage class and scope attribute that declares an external variable or external file constant and causes storage to be allocated for the variable or constant. Its format is:
GLOBALDEF [(name)]
where name is an identifier that is accepted as legal syntax for compatibility with other Open PL/I extensions, but is ignored, having no effect.
For variables, the GLOBALDEF attribute implies the EXTERNAL and STATIC attributes. For file constants, it implies the EXTERNAL attribute. A given variable or file constant may be declared with the GLOBALDEF attribute in only one procedure.
GLOBALREF is a storage class and scope attribute that declares a global symbol, which is defined in an external procedure either with the GLOBALDEF attribute or, if the external procedure is written in another programming language, with its equivalent in that language. Its format is:
GLOBALREF [(name)]
where name is an identifier that is accepted as legal syntax for compatibility with other Open PL/I extensions, but is ignored, having no effect.
The GLOBALREF attribute implies the EXTERNAL and STATIC attributes. A variable may be declared with the GLOBALREF attribute in as many procedures as desired. Unlike GLOBALDEF, GLOBALREF does not cause actual storage to be allocated for the external variable, but allows access to the storage that was allocated by some other external procedure.
If GLOBALREF is present, any INITIAL attribute for the variable is ignored.
P1: PROCEDURE; P2: PROCEDURE; DECLARE DECLARE XVAR FIXED BIN(15) XVAR FIXED BIN(15) GLOBALDEF; GLOBALREF; XVAR = 23; IF XVAR > 0 THEN XVAR = 100; CALL P2; . . . . . .
In this example, XVAR is declared with the GLOBALDEF attribute in procedure P1 and is assigned storage as a result. The value 23 is assigned to XVAR. Procedure P2 has declared XVAR with the GLOBALREF attribute and will access the same memory location allocated by P1 . Procedure P2 can test and/or change the value of XVAR.
Abbreviation: INIT
INITIAL is a storage class attribute that specifies the initial value of a variable or member of a structure. The INITIAL attribute has two formats. The first specifies an initial constant, expression, or variable whose value is assigned to a variable when storage is allocated to it. The second format specifies that the CALL option invokes a procedure to perform initialization at allocation. The variable is initialized by assignment during the execution of the called routine, rather than by the routine being invoked as a function that returns a value to the point of invocation. The formats of the INITIAL attribute are:
INITIAL(item[,item]…)
where item is:
*|constant|variable|expression|iteration-spec
where iteration-spec is:
(iteration-factor) iteration-item
where iteration-item is:
*|constant|variable|expression
where iteration-factor is:
*|expression
where constant is:
arithmetic-constant|bit-constant|character-constant| entry-constant1 label-constant
In the context of item or iteration-item, asterisk ( * ) specifies that the element is to be left uninitialized.
In the context of iteration-factor, asterisk (* ) specifies that the entire array is to be initialized with the iteration-item.
For static variables, any value specified in an INITIAL attribute is assigned at the time the program is first loaded into memory for execution.
For automatic variables, which are allocated at each activation of the declaring block, any specified initial value is assigned at the time of each allocation.
For based and controlled variables, which are allocated at the execution of ALLOCATE statements, any specified initial value is assigned at the time of each allocation.
The INITIAL attribute may not be used with variables of storage classes other than those mentioned above.
Only constant values with no operations can be specified in the INITIAL attribute for static variables, with the following exceptions:
DECLARE STRING CHAR(5) STATIC INIT ('LIA' || 'NT');
INITIAL CALL entry(arg[,arg]…)
The INITIAL call cannot be used to initialize static data.
The following example will initialize all elements of 3x3 matrix A with the exception of its diagonal elements A (1,1), A(2,2), and A(3,3):
DECLARE A(3,3) FIXED BIN INIT(*,(3)0,*,(3)0,*);
The following example will initialize all elements of array B to the value of the expression (X+10 ) where X is a procedure parameter.
SUB; PROCEDURE(X); DECLARE X FIXED BIN(15); DECLARE B(5) FLOAT BIN INIT((HBOUND(B,1))(X+10));
The following example demonstrates the usage of asterisk repeat factor and will initialize the entire array Z to the value of 1.0.
SUB1: PROCEDURE(DIM); DECLARE DIM FIXED BIN(15); DECLARE Z(DIM) FLOAT BIN(23) INIT((*)1.0);
The INITIAL CALL is used to initialize automatic, based, or controlled variables by calling an external entry. The following is an example.
TEST: PROCEDURE OPTIONS(MAIN); /* Initialize all elements of array TEN */ DECLARE TEN(10) FIXED BIN(15) INIT CALL INITIALIZE(ADDR(TEN),HBOUND(TEN,1)); INITIALIZE: PROCEDURE(P,DIM); DECLARE P POINTER, DIM FIXED BIN(15); DECLARE I FIXED BIN, ARRAY(1000) FIXED BIN(15) BASED; DO I = 1 TO DIM; P->ARRAY(I)=75; END; END INITIALIZE; END TEST;
INPUT is a file description attribute that specifies that a file will be used for input.
The INPUT attribute may be given in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable.
File description attributes specified in a DECLARE statement apply to all openings of the file control block associated with the file constant. See the sections Input and Output and OPEN.
Abbreviation: INT
INTERNAL is a scope attribute that limits the scope of a variable to the block in which it is defined.
The INTERNAL attribute may be given with any storage class attribute or to parameters, but it has no significance since these variables always have internal scope. If STATIC is used without INTERNAL or EXTERNAL, INTERNAL is the default.
Abbreviation: IRRED
IRREDUCIBLE is an attribute sometimes used by IBM mainframe PL/I programs. It is not needed by Open PL/I. It is simply parsed and otherwise ignored.
KEYED is a file description attribute that indicates that records in a specified file may be accessed randomly. The KEYED attribute implies the RECORD attribute.
KEYED may be given in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable. For more information, see the section OPEN.
LABEL is a data type attribute that specifies label values. When used in the declaration of a name, it specifies that the declared name is a label variable. When used in an ENTRY attribute, it specifies that the corresponding parameter is a label variable, and when used in a RETURNS attribute, it specifies that the procedure returns label values.
For a discussion of label values, see the section Label Data.
LIKE specifies that the variable being declared has the same structure as the referenced variable. Its format is:
LIKE reference
where reference is a reference to a structure variable.
The variable being declared must be a structure variable. LIKE causes it to have exactly the same members, in name and attributes, as the referenced structure variable. Only the level numbers are changed as needed to adapt to the variable being declared.
In the following example, structure members are duplicated from one declaration to another by way of the LIKE attribute:
DECLARE 1 TEMPLATE BASED, 2 NAME CHAR(45), 2 SALARY FIXED BIN(15), 2 EMP_NO FIXED BIN(15); DECLARE 1 EMPLOYEE_INFO(1000) LIKE TEMPLATE;
Duplication of the members from TEMPLATE expands the declaration of EMPLOYEE_INFO, with the result that the declaration of EMPLOYEE_INFO is equivalent to:
DECLARE 1 EMPLOYEE_INFO(1000), 2 NAME CHAR(45), 2 SALARY FIXED BIN(15), 2 EMP_NO FIXED BIN(15);
The referenced variable can be a major or a minor structure. It may be qualified, but may not be pointer-qualified. The following restrictions apply to the referenced variable:
The function of the LIKE attribute is similar to that of the TYPE attribute . With LIKE, the storage class of the referenced structure is not carried over to the created structure (same as TYPE). However, neither are the alignment attributes and/or dimensions of the referenced variable carried over (unlike TYPE). Only the alignment and dimensions of substructures and elements of the referenced variable are carried over.
The OFFSET attribute defines a locator data type used to specify the relative location of a based variable within an area. The format is:
OFFSET[(area–variable)]
For a complete description of offset data and the use of the OFFSET attribute, see the sections Offset Data and Area Data.
OPTIONS(DESCRIPTOR) is an entry name attribute. It specifies that argument descriptors will be passed to this entry by callers. This is the default for entry names. Argument descriptors are used to pass specific details about actual parameters in cases where parameter declarations contain CHAR(*) or DIMENSION(*) attributes.
OPTIONS(NODESCRIPTOR) is an entry name attribute. It specifies that argument descriptors will not be passed to this entry by callers. Argument descriptors are used to pass specific details about actual parameters in cases where parameter declarations contain CHAR(*) or DIMENSION(*) attributes. The OPTIONS(NODESCRIPTOR) attribute is normally used to suppress the generation and passing of the descriptor(s) to a non-PL/I procedure.
Note:
OPTIONS(ASM) and OPTIONS(COBOL) are equivalent to OPTIONS(NODESCRIPTOR).
OPTIONS(VARIABLE) is an entry name attribute that indicates, for an ENTRY descriptor, that a specified external procedure can be invoked with a variable number of arguments; a discrepancy may exist between the number of parameter descriptors in the declaration of the procedure and the number of arguments in the argument list used to call the procedure.
OPTIONS(VARIABLE) attribute is parsed and is otherwise ignored. It is an invalid attribute for a PROCEDURE or ENTRY statement, as opposed to the ENTRY attribute.
For more information on OPTIONS(VARIABLE), see the section ENTRY.
OUTPUT is a file description attribute that indicates that data should be written to, and not read from, the associated file or device.
The OUTPUT attribute may be given in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable.
For more information, see the section OPEN.
Abbreviation: PIC
PICTURE is a data type attribute that specifies pictured values. Its format is:
PICTURE'p'
The picture 'p' contains an image of the data and specifies the editing to be performed each time a value is assigned to a pictured variable. It also governs the conversion of pictured values to fixed-point decimal values.
For a discussion of pictured data and the picture characters, see the section Picture Data.
Abbreviation: PTR
POINTER is a data type attribute that specifies pointer values. A pointer value is the address of a variable and is discussed in the section Pointer Data.
Abbreviation: POS
POSITION is an attribute that is used in conjunction with the DEFINED attribute. It specifies the bit or character within the basis variable at which the defined variable is to begin. Its format is:
POSITION(expression)
where expression is an integer expression that specifies the position relative to the start of the basis variable. The range of the expression is from 1 to n, where n is defined as:
n = basis_length – defined_length+1
where basis_length is the length of the basis variable in bits or characters and defined_length is the length of the defined variable in bits or characters.
Both the defined variable and the basis variable must be fixed-length bit strings, fixed-length character strings, pictured variables, or aggregates containing any of these data types.
In the following example, the two DO-groups accomplish the same purpose. The second makes use of the POSITION attribute:
DECLARE X CHARACTER(200); DECLARE Y CHARACTER(1) DEF X POS(I); DO I = 1 to 200; IF SUBSTR(x,i,1) = '?' THEN CALL ERROR(); DO I = 1 to 200; IF Y = '?' THEN /* Uses position attributes */ CALL ERROR();
PRINT is a file description attribute used to declare a print file.
PRINT may be given in the declaration of a file constant or in an OPEN statement, but it must not be specified in the declaration of a file variable. For more information, see the section OPEN.
The READONLY attribute is parsed and is otherwise ignored. This is a compatibility feature to allow Open PL/I programs written for other systems to compile without error.
REAL is an arithmetic data type attribute. It specifies that the associated variable is used for real numbers (that is, single-part numbers, as opposed to complex). Arithmetic variables are assumed to be REAL by default.
RECORD is a file description attribute that indicates that data in an input or output file is made up of separate records, and that the file will be processed by record I/O statements.
RECORD may be given in the declaration of a file constant or may be given in an OPEN statement. It must not be specified in the declaration of a file variable. For more information, see the section OPEN.
Abbreviation: RED
REDUCIBLE is an attribute sometimes used by IBM mainframe PL/I programs. It is not needed by Open PL/I. It is simply parsed and otherwise ignored.
REFER is an attribute of a based structure that specifies that the value of one member is used to determine the amount of storage space allocated for another member of the same structure. Its format is:
expressionREFER(variable)
where expression is evaluated and converted to Fixed Binary (15) and is the initial extent when the based structure is allocated. Variables used in the expression being evaluated as operands must not belong to the member containing the REFER attribute.
variable must be a variable contained by the structure being allocated and defined prior to the extent whose size it determines. For example:
DECLARE 1 STRUC BASED(P), 2 I FIXED BINARY, 2 A CHARACTER(20 REFER(I));
Multiple REFER attributes are allowed in the declaration of a structure.
RETURNS is an entry name attribute that specifies that the entry value designates a function procedure that returns a value of data type t, where t is a list of attributes that specify a data type. Its format is:
RETURNS[(t)];
For example:
DECLARE F ENTRY(FIXED) RETURNS(POINTER); DECLARE G ENTRY(FLOAT) RETURNS(CHARACTER(32)VARYING);
In this example, F is declared as the name of a function procedure that returns pointer values. G is declared as the name of a function procedure that returns varying character-string values whose maximum length is 32 characters.
Any string length given in a RETURNS attribute must be an integer constant. The only attributes that can be given in a RETURNS attribute are data type attributes. DIMENSION or level numbers cannot be given, because functions cannot return arrays or structures.
For more information on the RETURNS attribute, see the section ENTRY.
Abbreviation: SEQL
SEQUENTIAL is a file description attribute that indicates that records in the file will be accessed sequentially.
SEQUENTIAL may be given in the declaration of a file constant or in an OPEN statement. It must not be specified in the declaration of a file variable. For more information, see the section OPEN.
STATIC is a storage class attribute that specifies that the storage for the declared variable is allocated by the Compiler and/or linker prior to program execution and remains allocated throughout program execution. The default attribute is AUTOMATIC.
See the section Static Storage.
STREAM is a file description attribute that indicates that the file consists of ASCII characters and will be processed using the GET and PUT statements.
The STREAM attribute may be given in the declaration of a file constant or in an OPEN statement, but it cannot be specified in the declaration of a file variable. For more information, see the section OPEN.
The TYPE attribute allows a declaration to inherit structure members and attributes from another declaration. It has the following format, where reference is a reference to a variable:
TYPE(reference)
If, for example, a variable INTEGER is declared as fixed binary, another variable that needs to be declared as fixed binary can be declared as TYPE (INTEGER) instead. For example:
DECLARE INTEGER FIXED BIN(31); /* TYPE DEFINITION */ DECLARE CODE TYPE(INTEGER); /* TYPED VARIABLE */
In this example, Open PL/I copies the attributes from INTEGER to CODE, which makes the declaration of CODE become the following:
DECLARE CODE FIXED BIN(31);
In the previous example, INTEGER is referred to as a type definition and CODE is referred to as a typed variable. A type definition is a normal variable declaration. It can be given the based storage class, because storage will not be allocated for the type definition.
In the following example, structure members are duplicated from one declaration to another by way of the TYPE attribute:
DECLARE 1 TEMPLATE BASED, /* TYPE DEFINITION */ 2 NAME CHAR(45), 2 SALARY FIXED BIN(15), 2 EMP_NO FIXED BIN(15); DECLARE EMPLOYEE_INFO TYPE(TEMPLATE); /* TYPED VARIABLE */
Duplication of the members from TEMPLATE expands the declaration of EMPLOYEE_INFO, with the result that the declaration of EMPLOYEE_INFO is now:
DECLARE 1 EMPLOYEE_INFO 2 NAME CHAR(45), 2 SALARY FIXED BIN(15), 2 EMP_NO FIXED BIN(15);
The TYPE attribute can be used in any of the following locations:
The following example illustrates all uses of the TYPE attribute:
/*----------- TYPE DEFINITION -----------*/ /* (LINE MAY ALSO BE USED AS A VARIABLE) */ DECLARE LINE CHAR(80) VARYING; /*---------------------------------------*/
/* VARIABLE DECLARATION */ DECLARE FORMAT_LINE TYPE(LINE); /* PARAMETER DECLARATION */ DECLARE PARAM TYPE(LINE); /* PARAMETER DESCRIPTOR */ DECLARE WRITE_LINE ENTRY(TYPE(LINE)); /* RETURNS OPTION IN PROCEDURE STATEMENT */ GET_LINE: PROC RETURNS(TYPE(LINE)); /* RETURNS OPTION IN ENTRY STATEMENT */ READ_LINE: ENTRY RETURNS(TYPE(LINE)); /* RETURNS ATTRIBUTE IN DECLARE STATEMENT */ DECLARE GET_LINE ENTRY RETURNS(TYPE(LINE));
A typed variable can inherit only the following attributes from its type definition (storage class is not inherited):
The TYPE attribute can be used to declare a function that returns an aggregate (that is, array or structure) result. For example:
/* TYPE DEFINITION */ DECLARE ARRAY(10) CHAR(80), 1 STRUCTURE, 2 LEVEL1 BINARY(15) 2 LEVEL2 BINARY(15) DECLARE FUNCTION1 ENTRY RETURNS(TYPE(ARRAY)); FUNCTION2 ENTRY RETURNS(TYPE(STRUCTURE));
Note: All extents in the type definition of the function must have constant values. For example, the dimension attribute of ARRAY (10) in the preceding declaration could not be a variable.
The TYPE attribute also allows an aggregate variable to be passed by value in one of the following two situations:
DECLARE XARR(10) FIXED BIN(15) YYR TYPE( XARR ), RTE ENTRY( TYPE(XARR) ), FCA ENTRY RETURNS( TYPE(XARR) ); CALL RTE( (XARR) ); /* CASE 1 */ CALL RTE( (YYR) ); /* CASE 1 */ CALL RTE( (FCA()) ); /* CASE 2 */
The parameter in the called routine must have the same TYPE attribute as the argument. In the above example, RTE's parameter has the attribute TYPE (XARR) (see the third line). This TYPE attribute is the same TYPE attribute that is used by the arguments in the subsequent calls to RTE (see the last 3 lines).
All extents in a type definition must have constant values when an aggregate variable is passed by value. For example, in the preceding program fragment, XARR. could not be declared as:
DECLARE N FIXED BINARY(31) INIT(10); DECLARE XARR(N) FIXED BIN(15), . . .
Dimensions (array bounds) can be specified on either the type definition or the typed variable, but not on both. For example, the following declaration of an array of arrays is invalid:
DECLARE XXX(10) CHAR(80), /* VALID */ YYY TYPE( XXX ), /* VALID */ ZZZ(10) TYPE( XX ); /* INVALID -- ARRAY OF ARRAYS */
Any extent expressions are inherited by a typed variable from that typed variable's type definition, as illustrated by the following example. A typed variable's dimensions and element lengths are dependent on the current values of the extent expressions.
/* TYPE DEFINITION */ DECLARE CHARX(N,N) CHAR( LENGTH(STRING) ) BASED, N FIXED BINARY(15), STRING CHAR(80) VARYING; /* TYPED VARIABLE */ DECLARE ARRAY TYPE(CHARX) BASED;
The evaluation of extents when the array is referenced follows the same rules that apply to the evaluation of based variables. In the following example, the variable array is declared in a different block from CHARX:
/*--------------------------------------------------*/ START: PROCEDURE; DECLARE CHARX(N,N) CHAR( LENGTH(STRING) ) BASED, N FIXED BINARY(15), STRING CHAR(80) VARYING; . . . /*--------------------------------------------------*/ NEXT: PROCEDURE; DECLARE ARRAY TYPE(CHARX) BASED, N FIXED BINARY(15), STRING CHAR(80) VARYING; . . . END NEXT; /*--------------------------------------------------*/ . . . END START; /*--------------------------------------------------*/
In the preceding example, Open PL/I uses the declarations in procedure NEXT to evaluate the extent expressions of ARRAY. Declarations in the current block are always used to evaluate extent expressions, even for variables that have not been declared with the TYPE attribute. (In the preceding example, if procedure NEXT did not declare N and STRING, those variable declarations in procedure START would be used.)
If the REFER option is used in a type definition, the following are true:
For example, in the following program fragment, VAR1 is a type definition, and VAR2 is a corresponding typed variable. The BASED attribute and a REFER option are specified in the declaration of VAR1. Therefore, the BASED attribute must be specified in the VAR2 declaration.
DECLARE N FIXED BIN(15); /* TYPE DEFINITION: */ DECLARE 1 VAR1 BASED, 2 SIZE FIXED BIN(15), 2 ITEMS( N REFER(VAR1.SIZE) ) CHAR(80); DECLARE VAR2 TYPE(VAR1) BASED;
when expanded yields:
DECLARE 1 VAR2 BASED, 2 SIZE FIXED BIN(15), 2 ITEMS (N REFER (VAR2.SIZE)) CHAR(80);
For example, in the previous program fragment, VAR1.ITEMS cannot be used as a type definition.
For example, in the previous program fragment, VAR1.SIZE is the reference in the REFER option and must be a member of VAR1, the type definition. In addition, the expanded form of the VAR2 declaration contains a substitution of VAR2.SIZE for VAR1.SIZE as the REFER(reference).
The reference in TYPE(reference) cannot:
For example, the following declarations are invalid:
DECLARE MYFILE FILE STREAM OUTPUT PRINT; DECLARE ZZZ TYPE( P -> Q ); /* INVALID - POINTER-QUALIFIED */ DECLARE URFILE TYPE( MYFILE ); /* INVALID - MYFILE IS CONSTANT */ DECLARE XXX TYPE( AAA(8) ); /* INVALID - HAS SUBSCRIPT LIST */ DECLARE YYY TYPE( FUN( ) ); /* INVALID - HAS ARGUMENT LIST */
The type definition cannot have the TYPE attribute, nor can it be any of the following:
For example, the following declarations are invalid:
EXPROC: PROCEDURE( XYZ ); DECLARE XYZ FIXED BIN(15), AAA TYPE( XYZ );/* INVALID - XYZ IS A PARAMETER */ DECLARE INT FIXED BIN(15), B TYPE(INT), Y TYPE(B); /* INVALID - B IS TYPED */ DECLARE 1 STRUCA, 2 PROG TYPE (INT), 2 NAMES CHAR(80); STRUCT1 TYPE(STRUCA), STRUCT2 TYPE(STRUCT1.NAMES); /* INVALID - NAMES IS IN TYPED STRUCTURE */
The reference in TYPE(reference) must not directly or indirectly refer to the variable that is declared, because then a circular definition will be created.
For example, the following declarations are invalid:
DECLARE 1 PROG, 2 MOD CHAR(80), 2 INT FIXED BIN(15), 2 STRUCZ TYPE(PROG);/* INVALID - DIRECTLY CIRCULAR */ DECLARE 1 STRUCA, 2 MOD CHAR(80), 2 INT FIXED BIN(15), 2 STRUCA TYPE(STRUCB); /* INVALID - INDIRECTLY CIRCULAR */ DECLARE 1 STRUCB, 2 MOD CHAR(80), 2 INT CHAR(80), 2 STRUCA TYPE(STRUCA); /*INVALID - INDIRECTLY CIRCULAR */
The following declarations are examples of other ways the TYPE attribute can be used:
DECLARE INT FIXED BIN(31); /* DEFINE AN OPERATION ON CHARACTERS */ DECLARE RADIANS ENTRY( TYPE(INT), TYPE(INT) ) RETURNS( TYPE(INT) ); /* DEFINE ABSTRACT DATA TYPE */ DECLARE 1 LIST, 2 HEAD POINTER, 2 TAIL POINTER; /* DEFINE OPERATION ON 'LISTS' */ DECLARE EXTEND_LIST ENTRY( TYPE(LIST),POINTER ) RETURNS( TYPE(LIST) ); /* DEFINE AN ABSTRACT DATA TYPE */ DECLARE 1 COMPLEX_INTEGER, 2 REAL TYPE( INTEGER ), 2 IMAGINARY TYPE( INTEGER ); /* DEFINE OPERATIONS ON COMPLEX_INTEGER */ DECLARE (CIADD, CISUB, CIDIV, CIMUL) ENTRY( TYPE(COMPLEX_INTEGER), TYPE(COMPLEX_INTEGER) ) RETURNS( TYPE(COMPLEX_INTEGER) );
Abbreviation: UNAL
UNALIGNED is a data type attribute that controls the storage boundary of data.
UNALIGNED is an optional part of the data type specification. Its presence allows the Compiler to align the data at the next available bit or byte, rather than on implementation-defined storage boundaries. This can reduce storage requirements.
For more information on these attributes, see the sections ALIGNED and UNALIGNED Attributes and Bit-String Data. For more information on data alignment in general, see your Open PL/I User's Guide.
UNION is an attribute applied to a structure, which causes all immediate members of that structure to occupy the same memory locations. An immediate member is any member having a level number greater than its containing structure, equal to the level number of its fellow members, and less than the level of members it contains. Typically, an immediate member has a level number that is one greater than its containing structure.
All members of a UNION will start at the same address. If extra bytes are required for proper alignment of one member, those bytes will appear before the beginning of the structure, that is, before all other members. The size of the UNION will be the size of its largest member.
In the following example, the 30-character ADDRESS_STRING and the members of ADDRESS_PIECES occupy the same memory. Changing ADDRESS_PIECES.CITY changes ADDRESS_STRING:
DECLARE 1 ADDRESS UNION, 2 ADDRESS_STRING CHARACTER(30), 2 ADDRESS_PIECES, 3 NUMBER CHARACTER(6), 3 STREET CHARACTER(12), 3 CITY CHARACTER(12);
In the following example, the data can be examined as 16 individual bits or as a single entity comprising one fixed binary number.
1 NUMBER UNION, 2 FIXED_NUM FIXED BINARY(15), 2 FIXED_NUM_BIT BIT(16);
Note: Code based on a particular representation of data types is highly machine-dependent and should be used cautiously.
For further information on the UNION attribute as a storage sharing mechanism, see the section Storage Sharing.
UPDATE is a file description attribute that indicates that the file with which it is associated is to be used for both input and output.
UPDATE may be given in the declaration of a file constant or in an OPEN statement, but it must not be specified in the declaration of a file variable. For more information, see the section OPEN.
VALUE can be used as an attribute in an ENTRY declaration, or can be applied to a parameter.
The VALUE attribute may only be applied to a parameter and parameter descriptors of the following types:
Fixed Binary(n) | where n ≤ 31 | |
Float Binary(n) | where n ≤ 23 | when calling PL/I |
Float Binary(n) | where n ≤ 52 | when calling non-PL/I |
Aligned Bit(n) | where n ≤ 32 | |
Character | ||
Pointer | ||
Entry |
The VALUE attribute is ignored if it is applied to a variable that is not a parameter.
If a parameter is multi-positional (appears in one or more of the PROCEDURE and ENTRY statements in a particular procedure) it may not have the VALUE attribute applied to it.
When a procedure is called from an Open PL/I procedure, the VALUE attribute should be applied only to a parameter whose corresponding parameter descriptor was also declared with VALUE in the calling procedure's ENTRY declaration in the called procedure. For example:
P: PROCEDURE( A, B, Q); DECLARE A FIXED BIN(31) VALUE, (B,C) FIXED BIN(15), Q POINTER VALUE, X FIXED BIN(15) BASED (Q); B = A + 2; A = 2 * B; C = X; ALLOCATE X SET(Q); X = A + C; END;
In this example, the value passed by A is incremented by 2 and returned to the calling procedure through B. The assignment of 2 * B to A does not affect the calling procedure; the value of the first argument of the CALL is unchanged by the assignment to A in the called procedure. Similarly, the value of the argument in the calling procedure that corresponds to Q is not changed by the ALLOCATE statement.
VARIABLE is an entry name attribute that specifies that the declared name is a file or entry variable rather than a file name or procedure name.
See the sections Entry Data, File Data, and ENTRY.
Abbreviation: VAR
VARYING is a character-string data type attribute that specifies that the string values may have any length that does not exceed the declared length.
For more information on this attribute, see the section Character-String Data.
Copyright © 2009 Micro Focus (IP) Ltd. All rights reserved.