The BEGIN statement denotes the start of a begin block.
The format of the BEGIN statement is:
A begin block is a sequence of statements headed by a BEGIN statement and terminated by an END statement. A begin block can be used wherever a single executable statement is valid, for instance, in an ON-unit. The statements in a begin block can be any PL/I statements, and begin blocks can contain DO-groups, DECLARE statements, procedures, and other (nested) begin blocks.
A begin block provides a convenient way to localize variables. Variables declared as internal within a begin block are not allocated storage until the block is activated. When the block terminates, storage for internal automatic variables is released. A begin block terminates in the following situations:
A begin block differs from a DO-group chiefly in its ability to localize variables. Variables declared within DO-groups are not localized to the group (unless the group contains a begin block or procedure that declares internal variables). Begin blocks are preferable when you want to restrict the scope of variables. Furthermore, there are some cases (such as ON-units) in which DO-groups cannot be used. Otherwise, DO-groups are often more efficient, because they do not have the overhead associated with block activation. In general, you should use a DO-group instead of a begin block unless there are declarations present or you require multiple statements in an ON-unit.
A begin block can designate a series of statements to be executed depending on the success or failure of a test in an IF statement. For example:
IF A = B THEN BEGIN ; . . . END;
A begin block also provides the only way to denote a series of statements to be executed when an ON condition is signaled. For example:
ON ERROR BEGIN; [statement ...] END;
See Section 1.4 for more details on blocks.
8.3 END Statement
The END statement marks the end of the block or group headed by the most recent BEGIN, DO, SELECT, or PROCEDURE statement.
The format of the END statement is:
label-referenceA reference to the unsubscripted label on the PROCEDURE, BEGIN, SELECT, or DO statement for which the specified END statement is the termination. A label is not required. If specified, the label reference must match only one label, which is the label of the most recent BEGIN, DO, SELECT, or PROCEDURE statement that is not already matched with an END statement. If the label reference is omitted, the most recent textual, non-terminated PROC, BEGIN, SELECT, or DO statement is matched by default.
Note that a procedure declared with the RETURNS option must execute a RETURN statement before it encounters the END statement marking the end of the procedure.
When the END statement is encountered, one of the following actions is performed, depending on the type of block or group that it terminates:
The IF statement tests an expression and performs a specified action if the result of the test is true.
The format of the IF statement is:
IF test-expression THEN action [ELSE action];
test-expressionAny valid expression that yields a scalar bit-string value. If any bit of the value is 1, then the test expression is true; otherwise, the test expression is false.
actionAny of the following:
- Any unlabeled statement except the nonexecutable statements: DECLARE, END, ENTRY, FORMAT, or PROCEDURE
- An unlabeled DO-group or begin block
The IF statement evaluates the test expression. If the expression is true, the action specified following the keyword THEN is executed. Otherwise, the action, if any, specified following the ELSE keyword is executed.
IF A < B THEN BEGIN;
The begin block following this statement is executed if the value of the variable A is less than the value of the variable B.
IF ^SUCCESS THEN CALL PRINT_ERROR; ELSE CALL PRINT_SUCCESS;
The IF statement defines the action to be taken if the variable SUCCESS
has a false value (the THEN clause) and the action to be taken
otherwise (the ELSE clause).
8.4.1 Nested IF Statements
The action specified in a THEN or an ELSE clause can be another IF statement.
An ELSE clause is matched with the nearest preceding IF/THEN that is not itself matched with a preceding ELSE. For example:
IF ABC THEN IF XYZ THEN GOTO GBH; ELSE GOTO THESTORE; ELSE GOTO HOME;
In this example, the first ELSE clause is executed if ABC is true and XYZ is false. The second ELSE clause is executed if ABC is false.
In some cases, proper matching of IF and ELSE can require a null statement (a semicolon) as the target of an ELSE. For example:
IF ABC THEN IF XYZ THEN GOTO HOME; ELSE; ELSE GOTO THESTORE;
In this example, the ELSE GOTO THESTORE statement is executed if ABC is
8.5 SELECT Statement
The SELECT statement tests a series of expressions and performs a specified action depending on the result of the test. The statement has two forms: in the first form, the expressions in a WHEN clause are tested for truth; in the second form, the expressions in a WHEN clause are compared to see if any have the same value as another specified expression called the select expression. Any of the expressions can be, but need not be, constants. An optional OTHERWISE clause is available to name an action to be performed if none of the preceding expressions have satisfied the condition specified.
The two forms of the SELECT statement and the OTHERWISE clause are described in more detail below.
The general form of the SELECT statement is:
select-expressionAn expression that can be evaluated to any type of value.
case-expression,...One or more expressions to be tested, evaluating to bit-string values, or, if a select expression is used, with values that will be compared to the select expression's value.
actionAny statement (including a null statement, another SELECT statement, a DO-group, or a BEGIN-END block) except a DECLARE, END, ENTRY, FORMAT, or PROCEDURE statement.
Depending on whether you use a select expression or not, SELECT has two different forms, which are explained in detail below.
SELECT Without a Select Expression
The first form of the SELECT statement omits the select expression. In this form, the expressions in a WHEN clause are evaluated, and a specified action is performed if the result of any test is true (or, if ALL is specified, the results of all tests are true); an expression is true if it evaluates to a bit string containing any bit with the value of '1'B. In the usual case, the test for truth results in a bit string containing one bit: '1'B for true or '0'B for false.
When the keyword ANY (the default) appears in the WHEN clause, then if any one of the expressions evaluates to true the corresponding action is performed. No further expressions in that WHEN clause or in subsequent WHEN clauses are evaluated (and thus the expressions need not have unique values), and no subsequent actions are performed.
The WHEN clauses are checked in the order listed. However, the expressions within one WHEN clause might be evaluated in any order, and not all these expressions are necessarily evaluated. As soon as any expression is found true, subsequent expressions are not evaluated.
If the keyword ALL appears in the WHEN clause, the action is performed only if all expressions in that WHEN clause evaluate to true. Once one action is performed, no subsequent WHEN clauses are evaluated and no subsequent actions are performed. If any expression in the WHEN clause does not result in a true value, no further expressions in that clause are evaluated and the action is not performed.
Following is an example of the first form of SELECT:
SELECT; WHEN ANY (A=10,A=20,A=30) B=B+1; WHEN (A=50) B=B+2; WHEN (A=60) B=B+3; WHEN (A=70) B=B+4; WHEN (A=80) B=B+5; WHEN (A=90) B=B+6; WHEN ALL (A>90,A<500) B=B+10; OTHERWISE B=B+C; END;
The SELECT statement defines the action to be taken if the variable A has any of the values specified in the WHEN clauses (or, in the case of the WHEN ALL clause, if A is both greater than 90 and less than 500). If none of the WHEN clauses is true, the action specified in the OTHERWISE clause (B=B+C) is performed.
SELECT With a Select Expression
The second form of the SELECT statement has a select expression after the keyword SELECT. This form of the SELECT statement evaluates expressions in the WHEN clauses and then compares their values to the value of the select expression (instead of testing the expressions for truth or falsity, as in the first form of SELECT). It performs a specified action if any expression has the same value as the select expression (or, if ALL is used, all expressions have the same value as the select expression). In this form of the SELECT statement, as in the previous form, the expressions in a WHEN clause might be evaluated in any order, and not all the expressions are necessarily evaluated.
Following is an example of the second form of SELECT:
SELECT(A); WHEN (50) C=C+1; WHEN ANY (60,61,62,B+C) C=C+2; WHEN ALL (70,D) C=C+3; OTHERWISE C=C+D; END;
The SELECT statement defines the action to be taken if the select
expression (A in the example) evaluates to any or all of the values of
the expressions following a WHEN clause. The first action (the
assignment statement C=C+1) will be performed if A has a current value
of 50. In that case, none of the subsequent WHEN clauses will be
evaluated. The second WHEN clause includes the ANY keyword, and so the
second action will be performed if A evaluates to or equals 60 or 61 or
62 or the sum of B and C. If neither the first nor the second action is
performed, the third WHEN clause's expressions are tested. The third
WHEN clause includes the ALL keyword, so the third action will be
performed only if A equals both 70 and D. If none of the WHEN clauses
causes an action to be performed, then the action in the OTHERWISE
clause (the assignment statement C=C+D) will be performed.
8.5.2 OTHERWISE Clause
If none of the WHEN clauses causes the corresponding action to be performed, the action specified in the optional OTHERWISE clause is performed; but if the OTHERWISE clause is omitted, an ERROR condition is signalled. OTHERWISE can be followed by a semicolon (a null statement) to cause execution to continue and avoid an ERROR condition when you do not want to specify an action after OTHERWISE. For example:
After an action is performed following a WHEN or OTHERWISE clause,
control passes to the next executable statement following the END
statement that terminates the SELECT statement, unless normal flow is
altered within the action.
8.5.3 Nested SELECT Statements
Note that the action specified in a WHEN or OTHERWISE clause can be another SELECT statement, resulting in nested SELECT statements, as in the following example:
SELECT; WHEN (condition A) SELECT; WHEN (condition A1) statement 1; WHEN (condition A2) statement 2; END; WHEN (condition B) SELECT; WHEN (condition B1) statement 3; WHEN (condition B2) statement 4; OTHERWISE statement 5; END; OTHERWISE statement 6; END;
In this example, statement 1 is executed when both condition A and condition A1 are true. Statement 2 is executed when both condition A and condition A2 are true and A1 is false. If A is true but neither A1 nor A2 is true, an ERROR condition is reported because no OTHERWISE clause exists within this SELECT statement.
If condition A is false, condition B is checked. If B is true but B1 and B2 are both false, statement 5 (in the corresponding OTHERWISE clause) is executed. If conditions A and B are both false, statement 6 (in the outermost OTHERWISE clause) is executed.
If you want to avoid the possibility that execution could be stopped by an ERROR condition, which occurs in this example if condition A is true and A1 and A2 are false, you can put in an OTHERWISE clause with a null statement (a semicolon) as its action, which would cause control to pass to the first executable statement following the end of the outermost SELECT statement.
An END statement must terminate each SELECT statement.
8.6 GOTO Statement
The GOTO statement causes control to be transferred to a labeled statement in the current or any outer procedure.
The format of the GOTO statement is:
label-referenceA label constant or an expression that, when evaluated, yields a label value. A label value denotes a statement in the program.
The specified label cannot be the label of an ENTRY, FORMAT, or PROCEDURE statement. The label reference specified in a GOTO statement can be any of the following:
- An unsubscripted label constant. For example:
GOTO ALPHA; . . . ALPHA:
- A subscripted label constant, for which the subscript is specified with an integer constant or a variable expression. For example:
GOTO PROCESS(1); . . . PROCESS(1):
- A label variable that, when evaluated, yields a label value. For example:
DECLARE PROCESS LABEL VARIABLE; . . . PROCESS = BILLING; . . . GOTO PROCESS;
- A subscripted label variable that, when evaluated, yields a label value. For example:
DECLARE X(5) LABEL; X(1) = NEXT; GOTO X(1);
In the case of a label variable, the resulting label value must designate an existing block activation. (Similarly, a label constant must designate an existing block activation.) If the designated block activation is the current block activation, the GOTO statement causes a local GOTO. No special processing occurs.
OTHERWISEThis option can be used only when the label-reference is a subscripted label with a variable subscript. If present in any other case, it will be reported as an error.
If the variable subscript is out of range and the OTHERWISE option is present, the statement following the GOTO will be executed next. If the OTHERWISE option is not specified and the subscript of the last label is not an asterisk (*), the subscript is reported out of range at run-time and the process will be terminated.
If the specified label value is not in the current block, the GOTO statement is considered a nonlocal GOTO. The following can occur:
The following example shows the use of the GOTO statement:
RESTART:; . . . BEGIN; ON ERROR GOTO RESTART; . . . END;
The GOTO statement provides a transfer address for the current procedure when the ERROR condition is signaled.
DECLARE PROCESS(5) LABEL VARIABLE; . . . GOTO PROCESS(2);
The GOTO statement evaluates the label reference and transfers control to the label constant corresponding to the second element of the array PROCESS. PROCESS consists of label variables.
The following restrictions apply to the use of labels and label data:
For more information on labels, see Section 3.7.
8.7 LEAVE Statement
The LEAVE statement causes control to be transferred out of the immediately containing DO-group or out of the containing DO-group whose label is specified with the statement.
The format of the LEAVE statement is:
label-referenceA reference to a label on a DO statement that heads a containing DO-group. The label reference can be a label constant or a subscripted label constant for which the subscript is specified with an integer constant. The label reference cannot be a label variable, nor can it be a subscripted label constant for which the subscript is specified with a variable.
On execution, a LEAVE statement with no label reference causes control to be transferred to the first statement following the END statement that terminates the immediately containing DO-group. If the LEAVE statement has a label, control is passed to the first executable statement following the END statement for the corresponding label indicated in the LEAVE statement. Thus, the LEAVE statement provides an alternative means of terminating execution of a DO-group. In the case of a LEAVE statement with a label reference, several nested DO-groups can be terminated as control transfers outside the referenced DO-group.
The following restrictions apply to the use of the LEAVE statement:
The following example shows a LEAVE statement without a label reference:
DO I = 1 TO 100; . . . IF COMMAND = 'QUIT' THEN LEAVE; . . . END; PUT LIST ('Job finished');
In this example, the LEAVE statement transfers control directly to the PUT statement if the condition in the IF statement is satisfied.
The next example shows a LEAVE statement with a label reference:
LOOP1: DO WHILE (MORE); . . . LOOP2: DO I = 1 TO 12; . . . IF QUAN(I) > 150 THEN LEAVE LOOP1; END; /* Loop 2 */ . . . END; /* Loop 1 */
In this example, the LEAVE statement transfers control to the first statement beyond the END statement that terminates LOOP1.
The following examples show some invalid uses of the LEAVE statement:
LEAVE; /* LEAVE statement must be in */ /* DO-group */ DO; BEGIN; LEAVE; /* LEAVE statement must be in */ END; /* same block as DO statement */ END; ON ENDFILE(SYSIN) LEAVE; /* ON-unit is separate block */ DECLARE LABVAR LABEL VARIABLE; LABVAR = LOOP; LOOP: DO I = 1 TO 10; LEAVE LABVAR; /* Label reference cannot be a variable */ END; LAB(1): DO; LAB(2): DO; I = 1; LEAVE LAB(I); /* Subscript must be a constant */ END; END;