Kednos PL/I for OpenVMS Systemstm
Reference Manual


Previous Contents Index

5.8.1 String Overlay Defining

If the defined variable is specified with the POSITION attribute, then both the defined variable and the base reference must be suitable for bit- or character-string overlay defining.

In brief, a variable is suitable for overlay defining if it consists entirely of characters or bits, and those characters or bits are packed into adjacent storage without gaps. Such a variable can be treated as a string or interpreted as different types of aggregates. For example:


DECLARE A (10) CHARACTER (5); 
DECLARE B (5) CHARACTER (10) DEFINED (A); 
 
A (1) = 'AAAAA'; 
A (2) = 'BBBBB'; 
PUT LIST (B(1)); 

Figure 5-5 shows a 50-byte region of storage treated either as a 10-element array (A) of 5-character strings or as a 5-element array (B) of 10-character strings.

Figure 5-5 An Overlay Defined Variable


If the defined variable and its base reference have identical data types, a reference to the defined variable is equivalent to the base reference. In the case of overlay defining, the defined variable maps onto part of the base reference's storage as follows:

  1. If the POSITION attribute was specified, let position be its value at the moment of reference; otherwise, let position equal 1.
  2. Let m be the total number of characters (or bits) specified by the data type of the defined variable. (Note that for pictured data, m is the total number of characters in the picture specification, exclusive of the V character.)
  3. A reference to the defined variable accesses m characters (or bits) of the base reference, beginning with the character or bit specified by position. The reference must lie entirely within the base reference; that is, position and m must satisify the following formula: 1 <= position <= position+m <= n+1
    n is the total number of characters or bits in the base reference.

5.8.2 Rules for Overlay Defining

A variable V is suitable for character-string overlay defining if V is not an unconnected array and if one of the following criteria is satisfied:

A variable V is suitable for bit-string overlay defining if V is not an unconnected array and if one of the following criteria is satisfied:

5.9 Storage Sharing

Variables that have any of the attributes BASED, DEFINED, UNION, or PARAMETER can share physical storage locations with one or more other variables.

A based variable is not allocated any storage when it is declared. Instead, storage is either located by a locator-qualified reference to the variable or allocated by the ALLOCATE statement. The BASED attribute then allows you to describe the characteristics of a variable, which can then be located by a reference that qualifies the variable's name with any valid pointer value. Based variables are useful when the program must control the allocation of storage for several variables with identical attributes. The creation and processing of a queued or linked list is a common case. For full details on based variables and valid pointer values, see Section 5.5.

A defined variable uses the storage of a previously declared variable, which is referenced in the DEFINED attribute. The referenced variable is known as the base of the defined variable. The base can be a character- or bit-string variable, suitable for a technique called string overlay defining. When the base is a string variable, the POSITION attribute can also be specified for the defined variable, giving the position within the base variable's storage at which the overlay defining begins. Defined variables are useful when the program must refer to the same storage by different names. For full details, see Section 5.8

Unions provide capabilities similar to those of defined variables, but the rules governing unions are less restrictive. A union is a variation of a structure in which all immediate members occupy the same storage.

The UNION attribute, which is used only in conjunction with a level number in a structure declaration, signifies that all immediate members of the major or minor designated structure occupy the same storage. Immediate members are those members having a level number one higher than the major or minor structure with the union attribute. For more details, see Section 4.2.2

Parameters of a procedure share storage with their associated arguments. The associated argument is either a variable written in the argument list or a dummy variable allocated by the compiler. When the written argument is a variable, the sharing of storage by the parameter and argument allows a procedure to return values to the invoking procedure by changing the value of the parameter. For instance, a function can return values in this manner in addition to returning the value specified in its RETURN statement. For more information, see Section 7.5.


Chapter 6
Expressions and Data Type Conversions

An expression is a representation of a value or of the computation of a value, and an assignment gives the value contained in an expression to a variable. Together, expressions and assignments form the mechanism for performing computation.

This chapter describes the following topics:

6.1 Assignment Statement

The assignment statement gives a value to a specified variable. The format of the assignment statement is:

target,...= expression; 

target

A reference to a variable to be assigned the expression's value. If there are two or more targets, they are separated by commas. A target can be:

expression

Any valid expression.

PL/I evaluates the targets and the expression in any order. Thus, a program should not depend on the evaluation of the targets before the expression.

PL/I performs the following steps for assignment. Note that the only certain things about the order of steps performed are that step 1 precedes step 3 and that step 4 is performed last.

  1. The expression is evaluated, producing a value to be assigned to the target. An expression can consist of many subexpressions and operations, each of which must be evaluated.
  2. Each target is evaluated. If a target contains a pseudovariable, any expressions in the argument list are evaluated.
  3. If the data type of the result does not match the data type of a target variable, the resulting value is converted to the data type of the target, if possible. The compiler issues a WARNING message to alert you to the implicit conversion.
  4. The value of the expression is assigned to the targets.

Some general rules regarding the types of data you can specify in assignment statements are listed in Table 6-1. For the complete rules for data conversion in assignments, see Section 6.4.

Table 6-1 Data Types for Assignment Statement
Data Type Rules
Area Only the current extent of an area is moved from the source area to a target. If the target area is not large enough to hold the extent, the AREA condition is raised. Note that the assignment is performed in such a way that all offsets in the source area are valid in the target area after the assignment. Areas cannot be assigned as members of structures.
Arithmetic PL/I converts an arithmetic expression to the type of its target if their types are different. If the target is a character- or bit-string variable, PL/I converts the arithmetic expression to its character- or bit-string equivalent.

A character-string expression can be converted to the data type of an arithmetic target only if the string consists solely of characters that have numeric equivalents.

Arrays You can specify an array variable as the target of an assignment statement in only the following ways:
  • array-variable = expression;

    where expression yields a scalar value. Every element of the array is assigned the resulting value.

  • array-variable-1 = array-variable-2;

    where the specified array variables have identical data type attributes and dimensions. Each element in array-variable-1 is assigned the value of the corresponding element in array-variable-2.

    The storage occupied by the two arrays must not overlap.

Any array variable specified in an assignment statement must occupy connected storage. All other specifications of an array variable as a target of an assignment statement are invalid.

Bit When a target of an assignment is a bit-string variable, the resulting expression is truncated or padded with trailing zeros to match the length of the target.
Character When a target of an assignment is a fixed-length character string, the resulting expression is truncated on the right or padded with trailing spaces to match the length of the target. If a target is a varying-length character string, the resulting expression is truncated on the right if it exceeds the maximum length of the target.

When one character-string variable is assigned to another, the storage occupied by the two variables cannot overlap.

Entry If the specified expression is an entry constant, an entry variable, or a function reference that returns an entry value, the target variable must be an entry variable.
Label If the specified expression is a label constant, a label variable, or a function reference that returns a label value, the target variable must be a label variable.
Pointer and Offset If the specified expression is a pointer or offset, or a function reference that returns a pointer or offset, the target variable must be a pointer or offset variable.
Structures You can specify the name of a major or minor structure as a target of an assignment statement only if the source expression is an identical structure with members in the same hierarchy and with identical sizes and data type attributes. The storage occupied by the two structures must not overlap.

Any structure variable specified in an assignment statement must occupy connected storage.

The following are examples of assignment statements:


A = 1; 
A = B + A; 
SUM = A + 3; 
STRING = 'word'; 

6.2 Operators and Operands

An operator is a symbol that requests a unique operation. Operands are the expressions on which operations are performed. Built-in functions can also be considered operators, as well as their arguments considered operands.

Operators

A prefix operator precedes a single operand. The prefix operators are the unary plus (+), the unary minus (-), and the logical NOT (^).

The following are examples of expressions containing prefix operators:


A = +55; 
B = -88; 
BITC = ^BITB; 

An infix operator appears between two operands, and indicates the operation to be performed on them. PL/I has infix operators for arithmetic, logical, and relational (comparison) operations, and for string concatenations. Following are some examples of expressions containing infix operators:


RESULT = A / B; 
IF NAME = FIRST_NAME || LAST_NAME THEN GOTO NAMEOK; 

An expression can contain both prefix and infix operators. For example:


A = -55 * +88; 

You can apply prefix and infix operators to expressions by using parentheses for grouping.

For a table giving the categories of operators and the operator symbols, see Chapter 1.

Operands

Because all operators must yield scalar values, operands cannot be arrays or structures. The data type that you can use for an operand in a specific operation depends on the operator:

6.2.1 Arithmetic Operators

The arithmetic operators perform calculations. Programs that accept numeric input and produce numeric output use arithmetic operators to construct expressions that perform the required calculations. The infix arithmetic operators are:
Operator Operation
+ Addition
- Subtraction
* Multiplication
/ Division
** Exponentiation

In addition, there are two prefix operators: unary plus (+) and unary minus (-). The unary plus is valid on any arithmetic operand, but it performs no actual operation. The unary minus reverses the sign of any arithmetic operand.

For any arithmetic operator, operands must be arithmetic; that is, they must be constants, variables, or other expressions with the data type attribute BINARY, DECIMAL, or PICTURE. Operands of different arithmetic types are converted to a common type before the operation is performed.

Arithmetic operators have a predefined precedence that governs the order in which operations are performed. All expressions can be enclosed in parentheses to override the rules of precedence. Table 6-2 lists the precedence of operators.

6.2.2 Logical Operators

The logical operators perform logical operations on one or two operands. The operands of the logical operators must be bit-string expressions, except that the operand of the NOT operator can be a bit-string expression or a single relational operator. All relational expressions result in bit-string values of length 1, and they can therefore be used as operands in logical operations.

Except when the NOT operator is used as the prefix of a relational operator, the result of a logical operation is always a bit string.

Except for AND THEN and OR ELSE, logical operations are performed on their operands bit by bit. If bit-string operands are not the same length, PL/I extends the smaller of the operands on the right (that is, in the direction of the least significance) with zeros to match the length of the larger operand. This length is always the length of the result.

There are five infix operators and one prefix operator:
Prefix Operator Operation
^ (circumflex) Logical NOT. In a logical NOT operation, the value of the operand is complemented; that is, a 1 bit becomes a 0 and a 0 bit becomes a 1. The value of a relational expression is also complemented; that is ^(A < B) is equivalent to (A >= B).
Infix Operator Operation
& (ampersand) Logical AND. In a logical AND operation, two operands are compared. If corresponding bits are 1, the result is 1; otherwise, the result is 0.
| (vertical bar) or ! (exclamation point) Logical OR. In a logical OR operation, two operands are compared. If either or both of two corresponding bits are 1, the result is 1; otherwise the result is 0. (The | and the ! characters can be used interchangeably.)
&: (ampersand and colon) Logical AND THEN. The operation is like AND except that the second operand is evaluated only if the first operand is true, and except that AND THEN does not do bit-by-bit operations on bit-string operands.
^ (circumflex) Logical EXCLUSIVE OR. Two operands are compared, and the result is 1 if one of the corresponding bits is 1 and the other is 0.
|: (vertical bar and colon) Logical OR ELSE. The operation is like OR except that the second operand is evaluated only if the first operand is false, and except that OR ELSE does not do a bit-by-bit operation on bit-string operands.

You can define additional operations on bit strings with the BOOL built-in function.

Logical expressions will not be completely evaluated in some cases. If the result of the total expression can be determined from the value of one or more individual operands, the evaluation can be terminated. For example:


A & B & C & D & E 

In this expression, evaluation will stop when any operand or the result of any operation is a bit string containing all zeros.

Examples


DECLARE (BITA,BITB,BITC) BIT(4); 
BITA = '0001'B; 
BITB = '1001'B; 
BITC = ^BITA;           /* BITC equals '1110'B */ 
BITC = BITA | BITB;     /* BITC equals '1001'B */ 
BITC = BITA & BITB;     /* BITC equals '0001'B */ 
BITC = ^(BITA & BITB);  /* BITC equals '1110'B */ 
BITC = ^(BITA > BITB);  /* BITC equals '1000'B (true) */ 

In the last assignment statement, the logical NOT expression yields <BIT_STRING>(1)B; when this value is assigned to BITC, a BIT(4) variable, the value is padded with zeros and becomes <BIT_STRING>(1000)B.

6.2.2.1 NOT

The logical NOT operator in PL/I is the circumflex character (^), used as a prefix operator. In a logical NOT operation, the value of a bit is reversed. If a bit is 1, the result is 0; if a bit is 0, the result is 1.

The NOT operator can be used on expressions that yield bit-string values (bit-string, relational, and logical expressions). It can also be used to negate the meanings of the relational operators (<,>, =). For example:


IF A ^> B THEN ...
   /* equivalent to IF A <= B THEN ...*/ 

The result of a logical NOT operation on a bit-string expression is a bit-string value. For example:


DECLARE (BITA, BITB) BIT (4); 
BITA = '0011'B; 
BITB = ^BITA; 

The resulting value of BITB is 1100.

The NOT operator can test the falsity of an expression in an IF statement. For example:


IF ^(MORE_DATA) THEN ...

6.2.2.2 AND

The ampersand (&) character is the logical AND operator in PL/I. In a logical AND operation, two bit-string operands are compared bit by bit. If two corresponding bits are 1, the corresponding bit in the result is 1; otherwise, the resulting bit is 0.

The result of a logical AND operation is a bit-string value. All relational expressions result in bit strings of length 1; they can therefore be used as operands in an AND operation. If the two operands have different lengths, the shorter operand is converted to the length of the longer operand, and the greater length is the length of the result.

Examples


DECLARE (BITA, BITB, BITC) BIT (4); 
BITA = '0011'B; 
BITB = '1111'B; 
BITC = BITA & BITB; 

The resulting value of BITC is <BIT_STRING>(0011)B.

The AND operator can test whether two or more expressions are both true in an IF statement. For example:


IF (LINENO(PRINT_FILE) < 60) & 
   (MORE_DATA = YES) THEN ...


Previous Next Contents Index