Previous | Contents | Index |
You can specify an array variable as the target of an assignment statement in the following cases:
array-variable = expression; |
This is valid where the expression yields a scalar value. Every element of the array is assigned the resulting value. The array variable must be a connected array whose elements are scalar. You can use the asterisk in an assignment:
array-variable (*,...) = expression; |
You can use a single asterisk regardless of how many dimensions an array has, or you can use an asterisk for each dimension.
Note that the arithmetic operators, such as the plus sign (+) and the minus sign (-), cannot have arrays as operands. An assignment of the following form is invalid:
ARRAYC = ARRAYA + ARRAYB; |
The following assignment is valid where the specified array variables have identical data-type attributes and dimensions:
array-variable-1 = array-variable-2; |
Each element in array-variable-1 is assigned the value of the corresponding element in array-variable-2. In this type of assignment, both arrays must be connected. The actual storage they occupy must not overlap, unless the arrays are identical.
All other specifications of an array variable as the target of an
assignment statement are invalid.
4.1.5 Order of Assignment and Output for Multidimensional Arrays
When a multidimensional array is initialized, or when it is assigned values without references to specific elements, PL/I assigns the values in row-major order. In row-major order, the rightmost subscript varies the most rapidly. For example, an array can be declared as follows:
DECLARE TESTS (2,2,3); |
If TESTS is specified in a GET statement or in a declaration with the INITIAL attribute, values are assigned to the elements in the following order:
When an array is output with a PUT statement, PL/I uses the same order to output the array elements. For example:
PUT LIST (TESTS); |
This PUT statement outputs the contents of TESTS in the order
previously shown.
4.1.5.1 Using GET and PUT Statements with Array Variables
When you specify an array variable name in the input-target list of a GET LIST or GET EDIT statement, elements of the array are assigned values from the data items in the input stream. For example:
DECLARE VERBS (6) CHARACTER (15) VARYING; GET LIST (VERBS); |
When this GET LIST statement executes, it accepts data from the default input stream. Each input field delimited by blanks, tabs, or commas is considered a separate string. The values of these strings are assigned to elements of the array VERBS in the order VERBS(1), VERBS(2),...VERBS(6). If a multidimensional array appears in an input-target list, input data items are assigned to the array elements in row-major order.
An array can also appear, with similar effects, in the output-source
list of a PUT statement.
4.1.6 Passing Arrays as Arguments
You can pass an array variable as an argument to another procedure. Within the invoked procedure, the corresponding parameter must be declared with the same number of dimensions. The rules for specifying the bounds in a parameter descriptor for an array parameter are as follows:
For example:
DECLARE SCAN ENTRY ((5,5,5) FIXED,(*) FIXED), MATRIX (5,5,5) FIXED, OUTPUT (20) FIXED; CALL SCAN (MATRIX,OUTPUT); |
The procedure SCAN receives two arrays as arguments. The first is a three-dimensional array whose bounds are known. The second is a one-dimensional array whose bounds are not known. The procedure SCAN can declare these parameters as follows:
SCAN: PROCEDURE (IN,OUT); DECLARE IN (*,*,*) FIXED, OUT (*) FIXED; |
An array whose storage is unconnected cannot be passed as an argument.
Arrays are always passed by reference.
4.1.7 Built-In Functions Providing Array Dimension Information
PL/I provides the following built-in functions that return information about the dimensions of an array:
For the first dimension of an array X, the relationship of these functions can be expressed as follows:
DIMENSION (X,1) = HBOUND (X,1) - LBOUND (X,1) + 1
The procedure that follows uses the HBOUND and LBOUND built-in functions:
ADDIT: PROCEDURE (X); DECLARE X (*) FIXED BINARY, (COUNT,I) FIXED BINARY; COUNT = 0; DO I = LBOUND (X,1) TO HBOUND(X,1); COUNT = COUNT + 1; X(I) = COUNT; END; RETURN; END; |
This procedure receives a one-dimensional array as a parameter and
initializes the elements of the array with integral values beginning
with 1.
4.2 Structures
A structure is a data aggregate consisting of one or more members. The
members can be scalar data items or aggregrates. Different members can
have different data types. Structures are useful when you want to group
related data items having different data types.
4.2.1 Structure Declarations and Attributes
The declaration of a structure defines its organization and the names of members at each level in the structure. The major structure name is declared as structure level 1; minor members must be declared with level numbers greater than 1. For example:
DECLARE 1 PAYROLL, 2 NAME, 3 LAST CHARACTER(80) VARYING, 3 FIRST CHARACTER(80) VARYING, 2 SALARY FIXED DECIMAL(7,2); |
PAYROLL.NAME.LAST = 'ROOSEVELT'; |
Alternatively, because the last and first names have the same attributes, you can declare the same structure as follows:
DECLARE 1 PAYROLL, 2 NAME, 3 (LAST,FIRST) CHARACTER(80) VARYING, 2 SALARY FIXED DECIMAL(7,2); |
The following additional rules apply to the specification of level numbers:
Attributes for Structure Variables
Within a structure, you can only declare members at the lowest level of each substructure with data-type attributes. Additional rules for specifying attributes for the various components of a structure are as follows:
AUTOMATIC | GLOBALREF |
BASED | INTERNAL |
CONTROLLED | READONLY |
DEFINED | STATIC |
EXTERNAL | STRUCTURE |
GLOBALDEF | UNION |
TYPE |
A union is a variation of a structure in which all immediate members occupy the same storage. The UNION attribute (which must be associated with a level number in a structure declaration) declares a union. All immediate members of the union-that is, all members having a logical level number one higher-occupy the same storage. A reference to one member of a union refers to storage occupied by all members of the union. Therefore, a union provides a convenient way to look at a large entity (such as a character string or a bit mask) as a series of smaller entities (such as component character strings or individual flag bits).
A variable declared with the UNION attribute must be a major or minor structure. All members of a union must have a constant size (see Chapter 2 for format and details).
The UNION attribute is not part of the PL/I General-Purpose Subset; it is provided in Kednos implementations of PL/I to give users convenient access to data as it is internally represented. Potential applications of unions might depend on the internal representation of data, and would therefore not be transportable between OpenVMS VAX and OpenVMS Alpha systems. The following example shows unions:
DECLARE 1 CUSTOMER_INFO, . . . 2 PHONE_DATA UNION, 3 PHONE_NUMBER CHARACTER (13), 3 COMPONENTS, 4 LEFT_PAREN CHARACTER (1), 4 AREA_CODE CHARACTER (3), 4 RIGHT_PAREN CHARACTER (1), 4 EXCHANGE CHARACTER (3), 4 HYPHEN CHARACTER (1), 4 SPECIFIC_NUMBER CHARACTER (4), 2 ADDRESS_DATA, . . . |
The UNION attribute associated with the declaration of PHONE_DATA signifies that PHONE_DATA's immediate members (PHONE_NUMBER and COMPONENTS) occupy the same storage. Any modification of PHONE_NUMBER also modifies one or more members of COMPONENTS; conversely, modification of a member of COMPONENTS also modifies PHONE_NUMBER. Note, however, that the UNION attribute does not apply to the members of COMPONENTS because they are not immediate members of PHONE_DATA. The members of COMPONENTS occupy separate storage in the normal fashion for structure members.
Unions provide capabilities similar to those provided by defined variables. However, the rules governing defined variables are more restrictive than those governing unions. The following example (for VAX only) demonstrates a use of a union that would not be possible with a defined variable:
DECLARE 1 X UNION, 2 FLOAT_NUM FLOAT BINARY (24), 2 BREAKDOWN, 3 FRAC_1 BIT (7), 3 EXPONENT BIT (8), 3 SIGN BIT (1), 3 FRAC_2 BIT (16); |
The union X has two immediate members, FLOAT_NUM (a floating-point variable) and BREAKDOWN. The members of BREAKDOWN are bit-string variables that overlay the storage occupied by FLOAT_NUM and provide access to the individual components of an VAX floating-point value. Assignment to FLOAT_NUM modifies the members of BREAKDOWN and vice versa. For example:
EXPONENT = '0'B; SIGN = '1'B; FLOAT_NUM = FLOAT_NUM + 1; |
The first two assignment statements set the exponent and sign fields of FLOAT_NUM to the reserved operand combination; the expression FLOAT_NUM + 1 causes a reserved operand exception to occur.
Note that, unlike the character-string example that precedes it, this
example depends on the VAX internal representation of data.
4.2.3 Initializing Structures
You can initialize a structure by giving the INITIAL attribute to its members. Not all members need be initialized. For example:
DECLARE 1 COUNTS, 2 FIRST FIXED BIN(15) INITIAL(0), 2 SECOND FIXED BIN(15), 2 THIRD (5) FIXED BIN(15) INITIAL (5(1)); |
The first and third members of the structure COUNTS are initialized.
The INITIAL attribute cannot be applied, however, to a major or a minor structure name.
In a union, the same data can only be initialized once.
4.2.4 Using Structure Variables in Expressions
You can specify the name of a major or minor structure in an assignment
statement only if the source expression and the target variable are
identical in size and structure, and all corresponding members have the
same data types.
4.2.5 Passing Structure Variables as Arguments
You can pass a structure variable as an argument to another procedure. The relative structuring of the structure variable specified as the argument and the corresponding parameter must be the same. The level numbers do not have to be identical. The following example shows the parameter descriptor for a structure variable:
DECLARE SEND_REC ENTRY (1, 2 FIXED BINARY(31), 2 CHARACTER(40), 2 PICTURE '999V99'); |
The written argument in the invocation of the external procedure SEND_REC must have the same structure, and its corresponding members must have the same data types.
When structures are passed as arguments, they must match the
corresponding parameters. They cannot be passed by dummy argument.
4.2.6 Member Attributes
PL/I supports three member attributes, so named because they apply specifically to the declaration of structure members rather than to the structure as a whole. The member attributes are as follows:
Each is discussed in detail in the following sections.
4.2.6.1 Using the TYPE Attribute
The TYPE attribute copies a scalar, array, or member declaration in a major or minor structure into another scalar, array, or structure variable respectively. The TYPE attribute copies the attributes to the target variable. For structures, the TYPE attribute also copies the logical structuring and member declarations from the major or minor structure to the target variable. TYPE does not copy any storage class or INITIAL attributes or dimensioning (except for dimensioning that is applied to arrays and members) from scalars, arrays, or structures.
Note that the TYPE attribute is a superset of the LIKE attribute. The TYPE attribute is identical to the LIKE attribute when it is used to copy a member declaration in a major or minor structure declaration into another structure variable.
An identifier names the variable to which the declarations for the reference are copied. The reference is the name of a scalar, an array, or a major or minor structure known to the current block. For structures, the identifier must be preceded by a level number. Any attributes that can be used with a structure variable at that level can be used with the identifier. For example, a major structure can specify a storage class and dimensions, and a minor structure can specify dimensions. The following example shows the TYPE attribute:
DECLARE NO_OF_SINGLE_ROOMS FIXED BINARY(31); DECLARE NO_OF_DOUBLE_ROOMS TYPE (NO_OF_SINGLE_ROOMS); |
In the previous example, the declaration of NO_OF_DOUBLE_ROOMS uses the TYPE attribute to create a declaration that duplicates the attributes of NO_OF_SINGLE_ROOMS. The declaration of NO_OF_DOUBLE_ROOMS is equivalent to the following:
DECLARE NO_OF_DOUBLE_ROOMS FIXED BINARY(31); |
In the next example, the declaration uses the TYPE attribute to create the declaration that duplicates the attributes of BED_SERIAL_NOS:
DECLARE BED_SERIAL_NOS((NO_OF_SINGLE_ROOMS + NO_OF_DOUBLE_ROOMS),2) CHARACTER(12); DECLARE TABLE_SERIAL_NOS TYPE(BED_SERIAL_NOS); |
The declaration of TABLE_SERIAL_NOS in the previous example is equivalent to the following:
DECLARE TABLE_SERIAL_NOS((NO_OF_SINGLE_ROOMS + NO_OF_DOUBLE_ROOMS),2) CHARACTER(12); |
In the following example, the declaration of NEW_RESER uses the TYPE attribute to create a set of member declarations that duplicate those in RES_DATA:
DECLARE 1 RES_DATA BASED (RPTR), 2 DATE CHARACTER(8), 2 HOTEL_CODE CHARACTER(3), 2 PARTY_NAME, 3 LAST CHARACTER(20), 3 FIRST CHARACTER(10), 2 STAY FIXED BIN(7), 1 NEW_RESER TYPE(RES_DATA), . . . GET LIST (NEW_RESER.DATE,NEW_RESER.HOTEL_CODE); . . . RES_DATA = NEW_RESER; |
The declaration of NEW_RESER in the previous example is equivalent to the following:
DECLARE 1 NEW_RESER, 2 DATE CHARACTER(8), 2 HOTEL_CODE CHARACTER(3), 2 PARTY_NAME, 3 LAST CHARACTER(20), 3 FIRST CHARACTER(10), 2 STAY FIXED BINARY(7); |
In the previous example, the members of NEW_RESER are assigned data after that data is validated; the entire contents of NEW_RESER are assigned to RES_DATA. This assignment is possible because the two structures are identical as a result of using the TYPE attribute.
You can use the TYPE attribute to copy a minor structure to a major structure and vice versa; neither the level numbers nor the logical levels must match. For example:
DECLARE 1 PARTY_NAME, 2 LAST CHAR(20), 2 FIRST CHAR(10); DECLARE 1 SPOUSE_NAME TYPE(PARTY_NAME); |
Given the declarations in the preceding example, this declaration is equivalent to the following:
DECLARE 1 SPOUSE_NAME, 2 LAST CHAR(20), 2 FIRST CHAR(10); |
You can also apply dimensions or, for a major structure, storage-class attributes to a structure variable declared with the TYPE attribute, as follows:
DECLARE 1 KID_NAMES (10) TYPE(PARTY_NAME); |
Or, you can use:
DECLARE 1 DAILY_DATA, 2 DATE CHAR(8), 2 TODAYS_RESERS (NO_OF_RES) TYPE(RES_DATA); . . . |
The LIKE attribute copies the member declarations in a major or minor structure declaration into another structure variable. It copies the logical structuring and member declarations from the major or minor structure to the target variable, but does not copy any storage-class attributes or dimensioning (except for dimensioning that is applied to members).
An identifier names the variable to which the declarations in the reference are copied. The reference is the name of a major or minor structure known to the current block. The identifier must be preceded by a level number. Any attributes that can be used with a structure variable at that level can be used with the identifier; for example, a major structure can specify a storage class and dimensions, and a minor structure can specify dimensions.
The following example shows the LIKE attribute:
DECLARE 1 RES_DATA BASED (RPTR), 2 DATE CHARACTER(8), 2 HOTEL_CODE CHARACTER(3), 2 PARTY_NAME, 3 LAST CHARACTER(20), 3 FIRST CHARACTER(10), 2 STAY FIXED BIN(7), 1 NEW_RESER LIKE RES_DATA, . . . GET LIST (NEW_RESER.DATE,NEW_RESER.HOTEL_CODE); . . . RES_DATA = NEW_RESER; |
In the previous example, the declaration of NEW_RESER uses the LIKE attribute to create a set of member declarations that duplicate those in RES_DATA. The declaration of NEW_RESER is equivalent to the following:
DECLARE 1 NEW_RESER, 2 DATE CHARACTER(8), 2 HOTEL_CODE CHARACTER(3), 2 PARTY_NAME, 3 LAST CHARACTER(20), 3 FIRST CHARACTER(10), 2 STAY FIXED BINARY(7); |
In the previous example, the members of NEW_RESER are assigned data after that data is validated, the entire contents of NEW_RESER are assigned to RES_DATA. This assignment is possible because the two structures are identical as a result of using of the LIKE attribute.
You can use the LIKE attribute to copy a minor structure to a major structure and vice versa; neither the level numbers nor the logical levels must match. For example:
DECLARE 1 SPOUSE_NAME LIKE PARTY_NAME; |
Given the declarations in the preceding example, this declaration is equivalent to the following:
DECLARE 1 SPOUSE_NAME, 2 LAST CHAR(20), 2 FIRST CHAR(10); |
You can also apply dimensions or, for a major structure, storage-class attributes to a structure variable declared with the LIKE attribute:
DECLARE 1 KID_NAMES (10) LIKE PARTY_NAME; |
or
DECLARE 1 DAILY_DATA, 2 DATE CHAR(8), 2 TODAYS_RESERS (NO_OF_RES) LIKE RES_DATA; . . . |
Previous | Next | Contents | Index |