Software Engineers Handbook/Language Dictionary/PLI

PL/I
Here is the Wikipedia entry.

Type
PL/I is a full procedural language.

Execution Entry Point
The program has its entry point specified as, in a procedure statement, as in:

Column specialties
There are no column specialities.

General Syntax
An assignment example:

In this numeric assignment statement,  is subtracted from , and the result multiplied by the value of  , before storing in variable. In this example string assignment, string  is joined to the end of string , and the composite string is stored in string variable.

Note: Using a compile-time option the concatenation operator  may be replaced by another pair of symbols, for being compatible with existing PL/I programs often   is used.

Comments
Every comment commences with the pair  and terminates with the pair. Comments may span lines.

Variable Declarations
Declarations are not compulsory, though most PL/I compilers provide a compiler option to force declarations, while some of the subset compilers insist that every variable be declared.

To declare  as an binary:

To declare  as an binary and give it an initial value of 0

To declare a variable as decimal,

The first declaration is of an integer  stored in decimal format, while the second is of a variable E capable of storing ten digits having 4 digits after the decimal point. To initialize, write: Note that values such as 0.1 are stored exactly.

To define a floating-point variable: that uses single precision hardware; and double precision: and extended precision: (typical declarations for the PC). The numbers 15 and 18 indicate the number of decimal digits that will be stored. (Although the values are actually held in binary, the decimal precisions are more convenient to recall than specifying the precisions in binary.) To specify a complex variable, simply include the word  in the declaration, thus: The assignment includes the complex constant 5.2+8i where 5.2 is the real part and 8 is the imaginary part.

The arithmetic data attributes for base (binary or decimal), scale (fixed or float) and mode (real or complex) may appear in any order, the attribute for precision (e.g. ) must not be the first one.

The following definitions are equivalent, except for the last one.

To declare a variable having the picture attribute: describes variable  as having as total of 7 decimal digits, with three digits after the decimal point. The decimal point is held in storage. The letter  indicates the position of the actual decimal point. For Europe, the specification may include a comma: To declare variable  as a character string: String  can store exactly 10 characters.

To declare variable  as a character string capable of storing up to 100 characters: A simple assignment: V holds the three characters. V holds the 8 characters.

PL/I also permits bit strings: permits bit strings to be stored, of length ten. The assignment statement: stores the bits in the given order. Such bit strings can be searched, etc., just like character strings.

Data structures, or aggregates, may be declared:

Arrays are declared by one of the above means, along with dimension information: specifies an array of ten elements,  through. The default lower bound is unity. To specify a different lower bound: declares a 16-element array  of floating-point elements.

Multi-dimension array are declared by separating the dimensions with commas defines a 2-dimensional array of 4 elements:,  ,  ,

To handle dates given as 2-digit years and as 4-digit years, possibly intermixed in the same program, the  attribute may be used.

The keywords  and   may abbreviated as   and , many attributes may abbreviated, too.

Output Statements
The first example writes  on the standard output (a screen or printer or file). The words are printed after any output already on that line. The second example starts a new line (the word ) before printing.

Method Declaration/Implementation
Describe how methods/functions/procedures are declared and implemented. The following example is of a complete PL/I program containing a function. The above program contains some typical input and output statements of the list-directed form. The first  statement prints the date. The second requests the reader to type three values representing the parameters of some triangle. The third echoes the inputs as confirmation. The last  statement contains a function reference, , which invokes the function. When it has been computed, the current  statement prints that area. The definition of the function  includes a   statement that lists the parameters required from the calling program, namely, ,  , and. These parameters are defined in the next statement. The  statement also states the type of the result to be returned to the calling program, namely, a floating-point value. This is indicated by. The  statement contains the formula to be used in calculating the area of the triangle. It then returns control to the calling program. A  statement typically includes the name of a variable, but may include an expression (as is the case here).

Scope
The scope of PL/I variables is confined to procedures in which they are declared. The scope extends into any procedures contained within that procedure (except of course any procedures in which a new declaration of the same name occurs).

In the event that a variable is not declared, then the scope of that variable is the whole program. Again, if a declaration (for a variable of the same name) appears in a block that is subordinate to the one(s) where the variable is (are) used, then the scope is excluded from the block containing the declaration.

PL/I has two kinds of blocks. One is the  block that is used for subroutines and functions. The other is the  block. The  block behaves as a   block, except that a   block has no parameters nor does it have to have a label. It is entered in normal sequential execution, whereas a  block can be executed only by executing a   statement or function reference.

Conditional Statements: IF..THEN..ELSE
Consider the two examples of conditional statements: The first example illustrates one optionally-executed statement

The second example shows two optionally-executed statements, the first of which is executed when  > , and the second of which is executed if   <=  ;

When multiple statements are to be executed conditionally, statement brackets  and   are used.

Multi-branch Conditionals: SELECT
The select-group offers a multi-branch evaluation, it may be written in one of the 2 following syntax schemes:

A select-group of scheme type 1 has the form and  (   = 1..n ) may be variables or expressions.

(  = 1..n ) and   may be single statements or do-groups.

The select-group is evaluated as (pseudo code): Evaluate var_or_expr and store it to the variable TEMP. For I = 1 to n:   Evaluate val_I, if the result equals TEMP: Execute unit_I and leave the select-group. Execute unit_other.

The  clause (which may be abbreviated  ) is optional, but if this clause is omitted and none of  equals   a run time error will occur.

A  clause may contain more than 1 value, e.g.

A select-group of scheme type 2 has the form (  = 1..n ) may be logical expressions or logical variables. (  = 1..n ) and unit_other may be single statements or do-groups.

The select-group is evaluated as (pseudo code): For I = 1 to n:   if expr_I is true: Execute unit_I and leave the select-group. Execute unit_other.

An example:

Looping Statements
The basic form of looping statement is: The body of the loop is executed ten times, with control variable  taking the values from 1 through 10. On loop exit, the value of  is one increment more, namely 11. The loop extends to the next  statement. Variations of looping statements are: Multiple iterative specifications may be used: in which the loop will be executed with control variable  taking the values 1 through 10, then 20, 25, 30, 35, ... 100, 120, 140, 160, 180, and 200.

A loop that is conditionally terminated uses the  construct: Such a loop is executed zero or more times, the test being performed at the beginning of the loop. The loop specified by the above statement is executed at least once, the test being performed at the end of the loop.

In the following, a  is used to specify an unusual change in the value of the control variable. In this case, the control variable  takes on the values 1, 2, 4, 8, 16, and so on, until   becomes greater than 1000.

The  form: may be used to traverse a linked list.

and  may be combined: (both examples are equivalent, i.e. the order of  and   in the statement doesn't matter )

may by followed by  or   or both of them: (the last two examples are equivalent)

Order of evaluation:

is evaluated as:

One more example: The following statement specifies that the do-group has to be executed eight times, with the value of I equal to 1, 3, 5, 9, 18, 36, 9, 18.

Boolean Values
In PL/I  strings represents single boolean values: strings may be used as boolean expressions in conditional and loop statements.
 * is interpreted as
 * is interpreted as

Boolean operators may be used for calculating new values: Note: Using compile-time options  operator and   operator may be replaced by other symbols, for being compatible with existing PL/I programs often   is used as ,   is used as.
 * The prefix operator  is used as logical.
 * The infix operator   is used as logical.
 * The infix operator   is used as logical.

Error Handling/Recovery
PL/I provides error detection and error handling. Errors that are detected include
 * floating-point overflow and underflow;
 * fixed-point overflow;
 * division by zero;
 * subscript bound error;
 * substring violation;
 * string truncation.
 * general errors.

The user can permit the system to report the error and perform a default action, or the user can specify a computational action to be executed when a given error is detected.

Events (including errors) are termed conditions.

For a condition to be detected, it must first be enabled. If the condition is enabled, and the corresponding condition occurs, the corresponding -unit (if supplied by the user) is executed.

Consider the following code:

In the event that the product  exceeds the maximum value permitted, the   condition is raised, and the  -unit for   is executed. The -unit here is one of the simplest, and merely transfers control to the statement labelled   (where, perhaps, the program deals with the next set of values).

The keyword  causes the running program to print an error message, along with the statement number where the error occurred.

A more general example follows:

In this example, the error detection and handling parts are shown in upper case. Subscript checking is enabled by the condition prefix  (parenthesised before the   statement). Before any statements are executed, the  statement must be executed, which establishes the action to be carried out in the event of a subscript error. The next statement executed is the input statement, which reads in a value, say 12. The loop is entered, and initializes ten values of x. On attempting to initialize, the   condition is raised, and causes the   unit   to be executed. causes an error message to be printed along with the statement number, and then statements within the  block are executed, namely the   statement, which prints. The program then s. Some specific conditions are:

Some conditions are provided to handle everyday events, for example, end of file and end of page. For example, to print a page number on the top of each page:

To detect the end of the input file, and to transfer to a named statement:

The programmer can invent his own conditions, and can signal them.

The  statement is provided to test a given  -unit (error-handler) during program testing. For example, To raise a user-defined condition called, the statement   would be used.

Containers


Algorithms

 * Sort algorithms and an XML parser is provided by IBM for its compilers.

Garbage collection
Any garbage collection is automatic. All variables with the automatic attribute or allocated with the     are removed from storage at the end of the block where they are declared. All allocated storage ( statement or  ) is removed from storage at the end of the program.

Physical Structure
The libraries of the standard functions are all automatically provided; it is unnecessary to do anything to obtain access to them, such as to specify directories or to use  statements or the like.

Tips

 * Source programs may be written in upper or lower case. There is no difference between the cases, except within strings.
 * Varying strings (declared with the attribute ) are similar to C's char.

For an exact equivalent, in Enterprise PL/I for z/OS you may use the attribute, in which strings are zero-terminated.

Without the attribute, strings are of fixed length. Such strings always store the specified number of characters. Thus, stores eight characters, namely,  followed by five blanks, whereas requires a storage of 10 bytes: 2 bytes for the actual length of V and 8 bytes for the characters. This latter feature makes possible the assignment which appends the word dog to what is already stored in V (up to a maximum of 8 characters in this example, of course).

Content of V after V = 'abc';: +---+---+---+---+---+---+---+---+---+---+ |  3   | a | b | c | ? | ? | ? | ? | ? |  /* "?" means: value is undefined */ +---+---+---+---+---+---+---+---+---+---+          1   2   3   4   5   6   7   8     /* index of character */

Content of V after V = V || 'dog';: +---+---+---+---+---+---+---+---+---+---+ |  6   | a | b | c | d | o | g | ? | ? |  /* "?" means: value is undefined */ +---+---+---+---+---+---+---+---+---+---+          1   2   3   4   5   6   7   8     /* index of character */

is equivalent to C's ; is equivalent to C's. is equivalent to C's.


 * Decimal arithmetic, because it is fixed-point, needs some care.

The built-in functions,  ,  , and   are provided to enable the programmer to specify the precision of each result. Thus they help to avoid overflow. For decimal fixed-point division, it is strongly recommended that the  function be used. Thus, to divide  by , where   has precision  , and   has precision  , the recommended form is: In the  reference, the arguments 10 and 5 direct that the result A/B has a total of ten digits, with 5 digits after the decimal point, respectively. This value is then stored in C. IBM PL/I permits up to 31 decimal digits for fixed-point working.

This enables checking for fixed-point overflow, and range-checking and truncation for strings and for subscripts.
 * When running PL/I programs, use the condition prefixes,  ,  , and  , on the initial procedure statement thus:


 * The lower bound of arrays is unity by default, not zero.


 * Division of integers (whether decimal or binary or mixed) may produce a fixed-point result having a scale factor. Thus, 9/2 produces 4.5000000, unlike Fortran which produces the integer 4. Should an integer result be required,  or   may be used, thus:   or - more generally - , the latter giving 31 bits of precision for a binary integer result. Alternatively, declaring binary integer variables to have maximum precision (typically 31 bits) will ensure that the result of dividing two such integer variables will give an integer result.

Web References

 * IBM manuals: PL/I for MVS &amp; VM
 * IBM manuals: Enterprise PL/I for z/OS

Books and Articles

 * J. K. Hughes, PL/I Structured Programming, 3rd Ed., Wiley, 1986. (beginner to professional; commercial applications)
 * R. Reddy & C. Ziegler, PL/I: Structured Programming and Problem Solving, West, 1986, ISBN 0-314-93915-6. (beginner to advanced)
 * R. A. Barnes, PL/I for Programmers, North-Holland, 1979. (professional)
 * G. F. Groner, PL/I Programming in Technological Applications, Books on Demand, Ann Arbor, MI, 1971. (professional)
 * M. E. Anderson, PL/I for Programmers, Prentice-Hall, 1973. (professional)
 * D. R. Stoutemyer, PL/I Programming for Engineering & Science, Prentice-Hall, 1971. (professional)
 * E. Sturm, Das neue PL/I (fur PC, Workstations and Mainframe), 5th Ed., Vieweg-Verlag, 2002.