PROCEDURES in PL/I
There are three types of PL/I procedures. MAIN procedure, Subroutine Procedure and Function Procedure. The main procedures are having separate compilations and may or may not have subroutine and functions. Subroutine and functions may also be compiled separately and called as Subprogram.
Four main advantages of using Subprograms
- Saves coding efforts
- Reduces the programming time
- Improves the program readability
- Improves program maintenance facility
The length of the procedure name must be within eight characters. The Subprograms is invoked by CALL Statement. Arguments passed to the Subprogram thru Argument list. The STOP or EXIT Statement abnormally terminates the execution of the Subprogram.
Subroutine procedures are separately compiled from the invoking procedures called External Procedures.
The Subroutine must return an error indicator to the invoking program, stating whether the error has been detected during the execution of the subroutine or not. Based on the error indicator, The Main procedure can take action.
Argument of the Subprogram and corresponding parameters may be any data type. If the argument is a bit or character string, then the corresponding parameter may be mentioned as asterisks.
Argument is a value passed to the invoked procedure and Parameter is the explicit declaration of the variables in a subroutine procedures.
Argument ———> CALL ADD(X,Y,Z);
Parameter ———-> ADD: PROCEDURE(X1, X2, X3);
Built-in functions can be specified as arguments to other subprograms.
* These functions with arguments are invoked before the subprograms are called, so that the value from the function is passed.
CALL ADD (X, SQRT(Y), Z);
* Built-in functions without arguments will not be invoked before the subroutine is called.
CALL ADD (X, Y, DATE);
* If any Built-in functions without arguments have to be invoked first, then that built-in argument has to be mentioned within parenthesis.
CALL ADD (X,Y,(DATE));
If the name of the arguments is not specified in the argument list then PL/I automatically assigns some dummy arguments as INTERNAL NAMES.
CALL ADD (1.75, A+B, X);
FUNCTION PROCEDURES in PL/1
A function is also a procedure that returns a single value to the invoking procedure. A function is invoked in a PL/I program in the same manner as built-in function. It can be appeared in any of the PL/I St. also such as IF, DO, PUTLIST …etc. It should not be invoked by CALL St.
RETURN St. is used to terminate a function. This is the major difference between Subroutine and Function. It returns the control as well as value to the Calling program.
Invoked pgm …
<name of the proc>: PROCEDURE (Arglist);
END <name of the proc>;
Invoking pgm …
W = <name of the proc> (parameter);
A = ADD(F,G,H);
RECURSIVE PROCEDURES in PL/1 Programming
When a procedure invokes itself, it is called RECURSIVE PROCEDURE. N factorial program is the right example for the recursive operation.
FACT: PROCEDURE (N) RECURSIVE;
K = N-1;
IF K = 1 THEN
I = N;
I = N * FACT(K);
LOGICAL TESTING STATEMENTS
SIMPLE IF :
If the condition is satisfied then the statement following to THEN keyword is executed before the program proceeds to the next imperative statements. If the condition is false, then the program flow will skip the THEN reserved word and proceeds to the next imperative statements.
IF < condn>
IF A = C THEN
X = ‘ANAND’;
This IF statement is called COMPOUND, because it has two sets of PL/I statement. If the condition is true then statement following the THEN reserved word is executed. If the condition is false then statement following the ELSE reserved word is executed.
IF A = B THEN
X = ‘ANAND’;
X = ‘BUVAN’;
IF STATEMENT WITH DO-GROUP :
In PL/I, IF statement is designed to execute a PL/I statement following THEN & ELSE clause.
Sometimes, there is a necessary to execute more than a statement has to be executed after the condition satisfied. This can be accomplished with the DO group.
IF A = B THEN
NESTED IF STATEMENT :
In a series of nested IF statements, each ELSE clause is paired with the closet IF, that is not already paired and starting at the inner most level. But every nested IF must have an ELSE clause whenever any IF statement of the outermost level requires an associated ELSE.
In the inner most IF structure, there is no operative PL/I statement followed by ELSE, but we have to specify ELSE statement because of the outermost IF statement’s ELSE association, then we can specify NULL ELSE statement. The null ELSE statement, as its name implies, a non operative statement.
IF A = B THEN
IF B = C THEN
X = ‘THIS IS RIGHT CHOICE’;
X = ‘ THIS IS OK ‘;
X = ‘THIS IS NOT A RIGHT ONE ‘;
IF A = B THEN
IF B = C THEN
X = ‘THIS IS RIGHT CHOICE’;
X = ‘THIS IS NOT A RIGHT ONE’;
1. The IF statement can be used for program switches, by using the indicator variable name or bit variables.
DCL MORE_RECORDS BIT(1);
2. Always use Ifs in their positive form. Avoid null ELSEs thru an alternate logic.
With null ELSE St. With alternate logic,
IF A = B THEN IF A = B & A = C THEN
IF A = C THEN X = 1;
X = 1;
ELSE; IF A NE B THEN
ELSE X = 3;
X = 3;
SELECT-GROUP STATEMENT :
One typical application of the CASE structure is testing special field in as input record and processing that record based on the unique code. It’s a extension of IF-THEN-ELSE.
In PL/I, the CASE structure is called a SELECT – GROUP, because it begins with the keyword SELECT and ends with END. One or more WHEN clause can be specified. Following each WHEN clause is an Expression in parentheses and Program action.
SELECT [ Optional Exp ];
WHEN (Exp1) Pgm Action 1;
WHEN (Exp 2) Pgm Action 2;
OTHERWISE Pgm Action n;
WHEN ( < 50) CALL MIN_COMP;
WHEN ( > 50 & < 150 ) CALL SLAP1_COMP;
WHEN (> 150 & < 300) CALL SLAP2_COMP;
WHEN (> 300) CALL MAX_COMP;
OTHERWISE CALL ERROR_COMP;
As mentioned earlier in IF WITH DO group, If we want to execute more than one PL/I statement in WHEN clause, then DO group can be used with WHEN clause.
WHEN (< 40)
X = ‘FAIL’;
Y = ‘HAS TO IMPROVE A LOT’;
WHEN (> 40 & < 60)
Y = ‘AVERAGE PERFORMANCE’;
WHEN (> 60 & < 80)
X = ‘PASS’;
Y = ‘GOOD PERFORMANCE’;
X = ‘PASS’;
Y = ‘DISTINCTION’;
It is also possible to nest SELECT groups within the other SELECT groups. The maximum nesting allowed in SELECT group is 49. When we are using the CASE structure instead of nested IF-THEN-ELSE, the readability of the program is increased automatically.
WHEN (<40) CALL FAIL_ADD;
WHEN (>40 & < 60) CALL AVG_ADD;
WHEN (>60 & < 80) CALL GOOD_ADD;
OTHEWISE CALL BEST_ADD;
ON STATEMENT :
For all the conditions, a standard system action exists as part of PL/I. Unless and otherwise, specified, when the ERROR condition is raised, the standard system action for the ERROR condition is to terminate the PL/I program and return the control to the operating system. Some cases we don’t want to use the standard system action in the response to a given condition. So we can handle thru program specified action taken for the response a given condition. This can be done thru ON statement.
ON condition on-unit;
MORE_RECS = NO;
A number of conditions may be specified in the ON statement. Some of the conditions that may be raised during I/O operations,
ENDFILE : This condition is raised during GET / READ operation. It is caused by an attempt made after the last record reached for the file named in GET / READ statement. After that no further GETs / READs should be executed for that file.
ENDPAGE : This condition is raised when a PUT statement results in an attempt to start a new line beyond the limit specified for the PAGESIZE. If PAGESIZE has not been specified an installation defined limits applies.
This is raised only once per page. When ENDPAGE condition raised, the standard system action is to skip to a new page and continue execution with the put statement.
This ENDPAGE condition is raised only when the max number of specified lines has been printed on the page.
PUT PAGE LIST(‘’, ‘ XXXXXXXXX’);
CTR_PAGE = CTR_PAGE + 1;
SYS_DATE = DATE;
CTR_PAGE = 1;
MORE_REC = YES;
GET LIST (DATA);
DO WHILE (MORE_REC);
SIGNAL ENDPAGE (PRT);
The above statement is used to cause a heading to be printed on the first page of the output. The SIGNAL statement has the same effect as if the condition had actually occurred.
TRANSMIT : This condition is raised, when the input or output device is not transmitting data correctly.
RECORD : This condition is raised, when the size of the record in a given file does not match with the size of the record in the PL/I program.
NULL ACTION : Null action can be specified for some conditions and not for all conditions. When ENDPAGE condition is found, we don’t want the system to skip a page. The program must be specify null action. A semicolon following to the condition name indicates a null action.
ON ENDPAGE (PRT);
ARITHMETIC CONDITION in PL/1 Programming
Some condition may be raised during arithmetic operation.
The CONVERSION condn occurs whenever a conversion attempted from character data to some other data type, which has invalid character for the conversion performed.
DCL X BIT(04);
X = ‘10BB’;
This condition occurs when the precision of the results of a fixed-point arithmetic operation exceeds 15 for decimal fixed-point and 31 for binary fixed-point values.
DCL A FIXED DEC (15);
DCL B FIXED DEC (15);
DCL C FIXED DEC (15);
A = 90000000;
B = 80000000;
C = A * B;
This condition occurs when the magnitude of a floating point number exceeds the maximum. 10^75.
A = 21E55;
B = 22E30;
C = A * B;
This condition occurs when the magnitude of the floating point number is smaller than the minimum. appox 10^-78
X = 21E-60;
Y = 29E-20;
Z = X * Y;
This condition occurs when an attempt made to divide by zero and is raised for both fixed-point and floating point division.
A = 10;
B = 0;
C = A / B;
This condition occurs when high-order or leftmost non zero binary or decimal digits are lost in an assignment operation.
DCL X FIXED DEC (7);
DCL Y FIXED DEC (9) INIT (12345678);
X = Y;
The important diff between FIXEDOVERFLOW & SIZE is that the FIXEDOVERFLOW occurs when the calculated fixed point value exceeds the max. precision and the SIZE condition occur when the value being assigned to the data item exceeds the declared size of the data item.
STATUS OF THE CONDITIONS :
Some conditions are always enabled and others are disabled. When a condition is enabled, it means, if the condn occurs the pgm-defined or system action takes place. When the condn are disabled the errors may be skipped.
* The I/O Condns are always enabled and cannot be disabled.
* The Arithmetic Condns except SIZE, all are enabled and can be disabled thru pgm.
* The SIZE Condn is disabled always and can be enabled thru pgm.
Conditions can be enabled or disabled thru a CONDITION PREFIX, which is one or more conditions separated by commas, enclosed by parentheses and prefixed by a colon. Condition prefix can be specified in a statement as a label. If it is desired to enable or disable the condn for the entire execution of the procedure then specify on the PROCEDURE statement.
(SIZE): X = A* B;
ADD: PROC OPTIONS (MAIN)
SIMULATING CONDITIONS :
The pgmmer can simulate the occurrence of a condn thru the SIGNAL St. It has the same effect as if the condition had actually occurred. If the condition is disabled and the SIGNAL statement treated as null statement.
SIGNAL ENDPAGE (filename);
BUILT-IN FUNCTION FOR ON STATEMENT:
There are four built-in functions facilitate program debugging for ON statement, such as, ONCODE, ONLOC, ONCHAR & ONSOURCE.
These are entirely different from other built-in statements. These built-in functions are starting with ON and are designed to be invoked in on-units to various conditions in the ON statement.
This built-in function may be specified in any on-unit. It returns a fixed binary integer.
This built-in function may also be used in any on-unit. It returns a character string indicating the name of the procedure in which the condition is raised.
ONCHAR & ONSOURCE:
This built-in function returns a character string whose value is the contents of the field that was being processed when the CONVERSION condn is raised. ONSOURCE causes the current value of the field that caused the CONVERSION error.
ONSOURCE = 0;
ONCHAR is a built-in function, can be used in an on-unit for the CONVERSION or ERROR conditions. Both ONCHAR & ONSOURCE are used as a pseudo variable. ONCHAR causes the current value of the field that caused the CONVERSION error.
DEBUGGING CONDITIONS :
STRINGRANGE CONDN :
This condn is raised whenever the lengths of the arg to the SUBSTR built-in function ref a nonexistent part of data.
DCL DETAIL CHAR(35);
DCL SUB_DETAIL CHAR(10);
SUB_DATIL = SUBSTR(DETAIL,4,17);
/* STRING RANGE ERROR IS RAISED ON THIS SUBSTR FUNCTION ST. */
This string range condn is disabled as default. So to enable it, specify it in a condn prefix. After the execution of the pgm, this has to be disabled, checking of this condn will add considerable overhead to the pgm.
STRINGSIZE CONDN :
This condn is occurred when the string is assigned to the shorter string. The right hand characters or bits of the source string are truncated to accommodate the size of the target string.
DCL X CHAR(50);
DCL Y CHAR(20);
Y = X;
/* STRING SIZE ERROR IS RAISED ON THIS ASSIGNMENT ST. */
This string range condn is disabled as default. So to enable it, specify it in a condn prefix.
DO-UNTIL STRUCTURE :
The DO-UNTIL structure differs from DO-WHILE in two aspects,
* The St. contained in the DO-UNTIL range is executed at least once, before the condition check.
* The DO-UNTIL is terminated when the condn tested is true and in DO-WHILE, termination will be only when the condn tested is false.
The steps performed in DO-UNTIL are,
* Execute the statements in the DO-Group
* When the END statement encountered, test the Expression / Condn specified.
* If the Condn is true, terminate the process. And if the condn is false, repeat the execution of the statements in the DO-group.
DO UNTIL <Condn>;
There may be any number of PL/I statements in DO-Group. There is no restriction like IF-THEN-ELSE.
ITERATIVE DO :
The iterative DO is a DO-WHILE structure. The sequence of steps of Iterative DO are,
Initialize the control variable to the initial value.
If the control variable is less than or equal to the limit value then execute the PL/I St. that follow DO. Otherwise the transfer the control to the END St.
The PL/I St. between DO & END St. are executed.
The modification value is added to the control variable.
Go to step 2 for the next iteration.
DO <Control Variable> = <Init.value> TO <Limit value> BY <Mod.value>
- * It is also possible to specify a negative modification value, for countdown operation.
- * Except the count down operation or negative modification value, the initial value of the control variable should not be greater than the limit value.
- * It is possible to use WHILE & UNTIL clause with Iterative-DO.
- * Iterative DO can be nested within another DO is also possible.
- * In the nested DO, All St. in the range of inner DO must be in the range of Outer DO.
- * When you are leaving DO-loop, avoid using GO TO St. Try to set some flag and exit format the loop. This is the good programming discipline.
DO X = 1 TO 100;
DO X = 1 TO 100 BY 2;
DO X = 100 TO 1 BY -1;
DO X = 1 BY 1;
DO ABC = X**2 TO Y**2 BY Z;
DO X = 1 TO 10, 31 TO 50, 71 TO 100;
DO X = 10,25, 35, 40, 55, 60;
DO X = 1 TO 100 WHILE (Y>100);
DO X = 1 TO 100 BY 1 WHILE (Y=Z);
DO X = 1 TO 100 BY 1 UNTIL (X=Y);
DO X = 1 TO 100;
Y = Y * 2;
IF Y < 0 THEN
X = 100;
ARRAYS in PL/I
An ARRAY is a table of data items in which each data item has the same attributes as every other data items in the array.
DCL A(10) CHAR(20);
DCL X(12) FIXED DEC(5,2);
We can declare the BOUND of an array, by specifying UPPER BOUND & LOWER BOUND of the array. bounds may be a constant, variables, expressions or asterisks. We can also specify the negative value for the bounds.
DCL X(20:40) FIXED DEC (5); /* THERE WILL BE 22 ELEMENTS */
DCL X(-4,+4) FIXED BIN (15,0) INIT (10,20,30,40,45,12,22,32,42);
The numbers of sets of Upper and Lower bounds of the array, specifies the DIMENSIONS of the array.
DCL X (5, 2) FIXED DEC (5);
DCL X (-3:3, -4:4) FIXED DEC (5) INIT (0);
The maximum dimensions allowed in PL/I program is 15.
Arrays may have Variables as a subscript.
X = 5;
Y = TEMP(X);
PL/I arithmetic exp may be specified as a subscript. Subscript expressions may include sub scripted items in the nested subscripts.
X = X1( A+B/C);
X = X1(X2(Y));
EXT_SAL = ADD_WRK_HRS(EMP_CD) * ADD_INC;
Initial attribute is used to initialize arrays.
DCL X(10) FIXED DECIMAL INITIAL (0);
DCL X(10) FIXED DECIMAL INITIAL ((10)0);
DCL Z(7,7) INIT ((49) -2);
DCL X(1,2) INIT (23,32);
Array can be read, with lowest numbered subscript and finishing with the highest sub-scripted number.
DCL MONTH(12) FIXED DEC (2);
GET LIST (MONTH);
The read operation will start from MONTH(1), MONTH(2), ….MONTH(12).
DCL X (4,4) FIXED DEC (3);
GET LIST (X);
The read execution will start from X(1,1), X(1,2), X(1,3), X(1,4), X(2,1), X(2,2) ..so on.
ARRAY MANIPULATION BUILT-IN FUNCTIONS :
DIM – provides the no of elements for the specified dimension in a given array.
LBOUND – finds the current lower boundary of a given array.
HBOUND – finds the current upper boundary of a given array.
SUM – finds the sum of all elements in an array.
PROD – finds the product of all elements of an array.
POLY – used to form polynomial expansion from two arg.
ANY – Used to test the bits of a given bit-string array.
ALL – Used to teat all bits of a given bit-string array.
ARRAY ASSIGNMENT :
Two types of array operations can be specified for arrays,
In Scalar-to-Array, the entire array is assigned to a single value.
In Array-to-Array, one array may be assigned to another array, provided the arrays must have an identical dimensions and bounds.