Previous | Contents | Index |
By default, PL/I passes all arguments by reference except character strings and arrays with nonconstant extents. The parameter descriptor for an argument to be passed by reference need specify only the data type of the parameter.
On OpenVMS systems for example, the Read Event Flags (SYS$READEF) system service requires that its first argument be passed by immediate value and its second by reference. You could declare this procedure as follows:
DECLARE SYS$READEF ENTRY (FIXED BINARY(31) VALUE, BIT (32) ALIGNED); |
When the procedure is invoked, the second argument must be a variable declared as BIT(32) ALIGNED. PL/I passes the argument by reference.
An argument of any data type can be passed by reference. Bit-string variables, however, must have the ALIGNED attribute.
The data types in the parameter descriptors of all output arguments must match the data types of the written arguments. For convenience, you can specify ANY in the parameter descriptor. To describe an argument to be passed by reference, you can specify the ANY attribute without the VALUE attribute. When you specify ANY for an argument to be passed by reference, you cannot specify data type attributes. Note that if you specify the VALUE attribute in conjunction with the ANY attribute, PL/I passes the argument by immediate value.
The ANY attribute is especially useful when you must specify a data structure as an argument. You need not declare the structure within the parameter descriptor, only the ANY attribute.
When an argument is passed by reference, PL/I passes the address of the actual argument. This address can be interpreted as a pointer value; you can explicitly specify a pointer value as an argument for data to be passed by reference; for example:
DECLARE SYS$READEF (ANY VALUE, POINTER VALUE), FLAGS BIT(32) ALIGNED; CALL SYS$READEF (4, ADDR(FLAGS)); |
At this procedure invocation, PL/I places the pointer value returned by
the ADDR built-in function directly in the argument list.
7.8.3 Passing Arguments by Descriptor
A descriptor is a structure that describes the data type, extents, and address of a data item. When passing an argument by descriptor, PL/I creates the descriptor and places its address in the argument list for the called procedure.
PL/I passes arguments by descriptor when a parameter descriptor specifies the following:
For example, PL/I passes by descriptor the arguments associated with the following parameter descriptors:
DECLARE UNSTRING ENTRY (CHARACTER(*)), TESTBITS ENTRY (BIT(3)), MODEST ENTRY (1, 2 CHARACTER(*), 2, 3 BIT(3), 3 BIT(3)); |
When you declare a non-PL/I procedure that requires a character-string descriptor for an argument, specify the parameter descriptor as CHARACTER(*). For example, the Set Process Name (SYS$SETPRN) system service requires the address of a character-string descriptor as an argument. You can declare this service as follows:
DECLARE SYS$SETPRN ENTRY (CHARACTER(*)); |
When a parameter is declared as CHARACTER(*), its written argument can be one of the following:
For any of those arguments, PL/I constructs a character-string descriptor and passes its address.
To force an argument to be passed by descriptor, use the DESCRIPTOR built-in function. For example:
DECLARE P ENTRY (ANY); DECLARE (X,Y) FIXED DECIMAL (7,2); CALL P(DESCRIPTOR (X)); CALL P(Y); |
Here, X is passed by descriptor as specified by the DESCRIPTOR built-in function. Y is passed by reference (see Section 11.4.28).
The statements described in this chapter direct the run-time flow of execution from statement to statement. They are the DO, BEGIN, END, IF, SELECT, GOTO, LEAVE, STOP, null, ON, SIGNAL, and REVERT statements.
The remainder of the chapter is devoted to handling conditions that
could arise during the execution of your program.
8.1 DO Groups and Statements
A DO-group is a sequence of PL/I statements delimited by a DO statement and its corresponding END clause. The statements in a DO-group are executed as the result of an unconditional DO statement or as the result of the successful test of a conditional DO.
For example:
IF A > B THEN DO; . . . END; |
The statements that occur between the DO and the END are a DO-group. After all statements to be executed in this conditional DO-group are complete, execution continues with the next executable statement following the END statement.
Normally, all the statements contextually nexted one level below the DO in the group are executed. However, control can be transferred out of a DO-group in the following ways:
You can nest DO-groups to a maximum level of 64.
The DO statement begins a sequence of statements to be executed in a group; the group ends with the nonexecutable statement END. DO-groups have several formats. These formats are described individually under the following subheadings:
A simple DO statement is a noniterative DO. The statements nested directly between the DO statement and its corresponding END statement are executed once. PL/I treates these nested statements as if they are one statement. After all statements in the group are executed, control passes to the next executable statement in the program.
The format of a simple DO statement is:
IF A < B THEN DO; PUT LIST ('More data needed'); GET LIST (VALUE); A = A + VALUE; END; |
The simple DO statement is commonly used as the action of the THEN
clause of an IF statement, as shown above, or of an ELSE option.
8.1.2 DO WHILE
A DO WHILE statement causes a group of statements to be repeatedly executed as long as a particular condition is satisfied. When the condition is not true, the group is not executed.
The format of the DO WHILE statement is:
test-expression
Any expression that yields a scalar value. If any bit of the value is a 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses. (Comparison operations yield a value with the type BIT(1).)This expression is evaluated before each execution of the DO-group. It must have a true value in order for the DO-group to be executed. Otherwise, control passes over the DO-group to the next executable statement following the END statement that terminates the group.
DO WHILE (A < B); . . . END; |
This DO-group is executed as long as the value of the variable A is less than the value of the variable B.
DO WHILE (LIST->NEXT ^= NULL()); . . . END; |
This DO-group is executed until a forward pointer in a linked list has a null value.
DECLARE EOF BIT(1) INITIAL('0'B); . . . ON ENDFILE(INFILE) EOF = '1'B; READ FILE(INFILE) INTO(INREC); DO WHILE (^EOF); . . . READ FILE(INFILE) INTO(INREC); END; |
This DO-group reads records from the file INFILE until the end of the
file is reached. At the beginning of each iteration of the DO-group,
the expression ^EOF is evaluated; the expression is
<BIT_STRING>(1)B until the ENDFILE ON-unit sets the value of EOF
to <BIT_STRING>(1)B.
8.1.3 DO UNTIL
A DO UNTIL statement causes a group of statements to be repeatedly executed until a particular condition is satisfied. That is, while the condition is false, the group is repeated.
The format of the DO UNTIL statement is:
test-expression
Any expression that yields a scalar value. If any bit of the value is 1, then the test expression is true; otherwise the test expression is false. The test expression must be enclosed in parentheses. (Comparison operations yield a value having the type BIT(1).)This expression is evaluated after each execution of the DO-group. It must have a false value for the DO-group to be repeated. Otherwise, control passes to the next executable statement following the END statement that terminates the DO-group. The test expression must be enclosed in parentheses.
Both the WHILE and UNTIL options check the status of test expressions, but they differ in that the WHILE option tests the value of the test expression at the beginning of the DO-group, and UNTIL tests the value of the test expression at the end of the DO-group. Therefore, a DO-group with the UNTIL option and no WHILE option will always be executed at least once, but a DO-group with the WHILE option may never be executed. |
DO UNTIL (A=0); . . . END; |
This DO-group is executed at least once and continues as long as the value of A is not equal to zero.
DO UNTIL (K<ALPHA); . . . END; |
This DO-group is executed at least once and continues as long as the
value of the variable K is greater than or equal to the value of the
variable ALPHA.
8.1.4 Controlled DO
A controlled DO statement identifies a variable whose value controls the execution of the DO-group and defines the conditions under which the control variable is to be modified and repeatedly tested.
The format of the controlled DO statement is:
control-variable
A reference to a variable whose current value, as compared to the end value specified in the TO option, determines whether the DO-group is executed. If none of the options are specified, the DO-group is executed a single time regardless of the value of the control variable. The control variable must be of an arithmetic data type.start-value
An expression specifying the initial value to be given to the control variable. Evaluation of this expression must yield an arithmetic value.end-value
An expression giving the value to be compared with the control variable during successive iterations. Evaluation of this expression must yield an arithmetic value. This expression is evaluated exactly once when the statement is executed for the first time. Thus if the end value changes as the loop progresses, only this initial value is used.modify-value
An expression giving a value by which the control value is to be modified. Evaluation of this expression must yield an arithmetic value. This expression is evaluated exactly once when the statement is executed for the first time. Thus if the modify value changes as the loop progresses, only this initial value is used. If the BY option is not specified, the modify value is 1 by default.WHILE (test-expression)
An option specifying a condition that further controls the execution of the DO-group. The condition must be true at the beginning of each DO-group iteration for the DO-group to be executed. The specified test expression must yield a scalar value. If any bit in the value is a 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses.UNTIL (test-expression)
An option specifying a condition that further controls the execution of the DO-group. This expression is evaluated at the end of each interation of the DO-group, before the BY clause is applied to the control variable. The condition must be false at the end of a DO-group execution for the next DO-group iteration to be executed. The specified test expression must yield a scalar value. If any bit in the value is a 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses.
If the TO, WHILE, and UNTIL options are omitted, the controlled DO statement specifies no means for terminating the group; the execution of the group must be terminated by a statement or condition occurring within the group. |
This DO-group will prompt the user for integer input values, and add each input value to the current sum. When the sum is greater than 100, the DO-group will exit.
DECLARE (NEXT_VALUE,SUM) FIXED BIN; SUM = 0; DO UNTIL ( SUM > 100 ); GET LIST (NEXT_VALUE) OPTIONS (PROMPT ('Next value to add? ')); SUM = SUM + NEXT_VALUE; END; PUT SKIP LIST ('The total sum is ',SUM); |
The controlled DO-group is executed by the following steps:
control variable = control variable + modify value; |
DO I = 2 TO 100 BY 2; |
This DO-group is executed 50 times, with values for I of 2, 4, 6, and so on.
DO I = LBOUND(ARRAY,1) TO HBOUND(ARRAY,1); |
This DO-group is executed as many times as there are elements in the array variable ARRAY, using the subscript values of the array's elements for the values of I.
DO I = 1 BY 1 WHILE (X < Y); |
This DO-group continues to be executed with successively higher values for I while the value of X is less than the value of Y.
DO I = 1 BY 1 WHILE (X < Y) UNTIL (X = 12); |
This DO-group resembles the DO-group in the preceding example, except that the DO-group continues to be executed while the value of X is less than the value of Y or until the value of X is equal to 12.
A controlled DO statement that does not specify a TO or BY option results in a single iteration of the following DO-group. For example:
DO X = 1 WHILE (A); |
Even if A is true, this DO-group executes a single time only. If A is false, it is not executed at all. Because there is no expression to change the value of X, the DO-group will not be executed again.
DO X = 1; |
This DO-group executes a single time only, regardless of the value of X.
8.1.5 DO REPEAT
The DO REPEAT statement executes a DO-group repetitively for different values of a control variable. The control variable is assigned a start value that is used on the first iteration of the group. The REPEAT expression is evaluated before each subsequent iteration, and its result is assigned to the control variable. A WHILE clause can also be included. If it is included, the WHILE expression is evaluated before each iteration (including the first), but after the control variable has been assigned. The format of the DO REPEAT statement is:
variable
A reference to a control variable. The control variable can be any scalar variable.start-value
An expression specifying the initial value to be given to the control variable. The evaluation of this expression must yield a value that is valid for assignment to the control variable.expression
An expression giving the value to be assigned to the control variable on reiterations of the DO REPEAT group. The expression is evaluated before each iteration after the first. Evaluation of this expression must yield a result that is valid for assignment to the control variable.WHILE (test-expression)
An option specifying a condition that controls the termination of the DO REPEAT group. The DO REPEAT group continues while the condition is true. The specified test expression must yield a scalar value. If any bit of the value is 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses.This expression is evaluated each time control reaches the DO statement; the test expression must have a true value in order for the DO-group to be executed. Otherwise, control passes to the next executable statement following the END statement that terminates the DO-group.
See Section 8.1.4 for a discussion of this option when used with the controlled DO statement.
UNTIL (test-expression)
An option specifying a condition that further controls the termination of the DO REPEAT group. The DO REPEAT group continues until the condition is true. The specified test expression must yield a scalar value. If any bit in the value is 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses.This expression is evaluated after the first execution of the DO-group; the test expression must have a true value in order for the DO-group to be executed a second time. Otherwise, control passes to the next executable statement following the END statement that terminates the DO-group.
If the WHILE and UNTIL options are omitted, the DO REPEAT statement specifies no means for terminating the group; the execution of the group must be terminated by a statement or condition occurring within the group. |
A DO REPEAT group is executed by the following steps:
DO LETTER='A' REPEAT (BYTE(I)); |
This example will repeat the group with an initial LETTER value of <BIT_STRING>(A) and with subsequent values assigned by the built-in function BYTE(I). The control variable I can be assigned new values within the group. The group will iterate endlessly unless terminated by a statement or condition within the group.
DO I = 1 REPEAT (I + 2) WHILE ( I <= 100 ); |
This example has the same effect as the following controlled DO statement:
DO I = 1 TO 100 BY 2; |
The most common use of the DO REPEAT statement is in the manipulation of lists. For example:
DO P = LIST_HEAD REPEAT (P->LIST.NEXT) WHILE ( P ^= NULL() ); |
In this example, the pointer P is initialized with the value of the pointer control variable LIST_HEAD. The DO-group is then executed with this value of P. The REPEAT option specifies that each time control reaches the DO statement after the first execution of the DO-group, P is to be set to the value of LIST.NEXT in the structure currently pointed to by P.
Previous | Next | Contents | Index |