This article includes a list of general references, but it remains largely unverified because it lacks sufficient corresponding inline citations. Please help to improve this article by introducing more precise citations. (February 2012) (Learn how and when to remove this template message)

The PL/I preprocessor is the preprocessor for the PL/I computer programming language. The preprocessor interprets a subset of the full PL/I language to perform source file inclusion, conditional compilation, and macro expansion.

The preprocessor language has a PL/I-like syntax with preprocessor statements and preprocessor procedures prefixed with a percent symbol (%). Listing-control statements, which supply formatting commands for the compiler listing, are usually considered preprocessor statements and also begin with %. Preprocessor statements are imbedded in and operate on input text. The input text is normally a PL/I program, but is agnostic to the grammar of PL/I, so the preprocessor can also be used independently to process other kinds of text files.

The preprocessor is not specified as part of standard PL/I, but most PL/I implementations accept the language of the IBM preprocessor.

Including files

The %INCLUDE preprocessor statement is used to include the text of another file, which may also contain preprocessor directives. The latest IBM compilers also provide an %XINCLUDE directive, which has the effect of including the specified file only if it has not already been included. %INSCAN and %XINSCAN operate similarly, except that the name of the file to be included is specified by a preprocessor expression.

Listing control

Listing control statements provide instructions for formatting both the listing generated by the preprocessor and the listing generated by the compiler.

Preprocessor operation

The preprocessor operates by scanning the input text and recognizing declared preprocessor names, also called preprocessor identifiers. The text is copied to the preprocessor output with the preprocessor names replaced with their current values. The name may represent a call to a preprocessor procedure (macro). Replacement text may be rescanned by the preprocessor for possible additional replacement.

Preprocessor data types

Preprocessor data may be declared to be CHARACTER, a character string with no maximum length, or FIXED an integer number of up to five decimal digits. A preprocessor builtin is a predefined procedure operating on preprocessor data. A preprocessor expression is an expression consisting only of preprocessor names, references to preprocessor procedures or builtins, and decimal or character constants. There are no BIT variables, but a BIT result may be obtained by comparison. The expression in %IF evaluates to BIT. All PL/I operators are allowed except exponentiation.

Preprocessor statements

 %IF preprocessor-expression
 %THEN preprocessor unit1
 %ELSE preprocessor-unit2

The preprocessor-units can be any single preprocessor statement or a preprocessor DO-group.

Preprocessor procedures

A preprocessor procedure is a subroutine executed by the preprocessor. The procedure is delimited by %PROCEDURE and %END statements and can contain only preprocessor statements, without the leading %. It is invoked as a function reference from open code, outside of any preprocessor procedure, or from another preprocessor procedure, and returns a CHARACTER or FIXED value. When the procedure is invoked from open code the arguments are passed by name, that is they are interpreted as character strings delimited by commas or a right parenthesis, all leading, trailing, or embedded blanks are significant and considered part of the argument.[1]: pp.508–509 

Preprocessor built-ins

These are the built-ins for IBM's PL/I for MVS and VM compiler.[2]: pp.404–406  There can be considerable difference in the built-ins provided among preprocessors of various PL/I compilers.


The following example for IBM PL/I for OS/2 illustrates the use of a preprocessor procedure to implement a C-like write statement for PL/I.[3] The procedure would be called by coding the statement uwrite file(filename) from(varying_string) count(byte_count); Byte_count is optional and defaults to the length of varying_string if omitted.

 procedure keys (File, From, Count);

 dcl (File, From, Count, Number, Size) char;

 if parmset(File) & parmset(From) then; else do;
    note ('FILE and FROM must be specified!', 12);

 if parmset(Count)
    then Size = 'min(length(' || From || '), ' || Count || ')';
    else Size = 'length(' || From || ')';

 Number = Counter();
 ans ('do;');
 ans ('dcl Count' || Number || ' fixed bin (15);' ) skip;
 ans ('Count' || Number || ' = filewrite('
                        || File
                        || ', ptradd(addr(' || From || '), 2)'
                        || ', ' || Size
                        || ');') skip;
 ans ('end;') skip;

 %act uwrite;

The statement uwrite file(file_name) from(var_str) count(64); generates the following:

 dcl Count00001 fixed bin (15);
 Count00001 = filewrite(file_name, ptradd(addr(var_str), 2), min(length(var_str), 64));


A 1964 report on "NPL",[4]: pp.109–114  as PL/I was called at the time, provided that macro procedures, identified by the keyword MACRO, could use the complete facilities of the language. The following compile-time statements were allowed in open code:

"NPL" as defined in this manual was never implemented.

In 1965 an update to IBM's PL/I Language specification defined an even less ambitious preprocessor language.[5]: pp.131–133  All mention of preprocessor procedures was omitted. The following compile-time statements were specified:

This language specification was again never implemented, however a 1966 revision of this manual restored preprocessor procedures with the now-current %PROCEDURE ... %END syntax and brought the specification close to what was actually included in PL/I(F).[6]: pp.132–139 [7]: pp.154–162  Fixed-length character variables were gone. New statements added were:

A single compile-time builtin, SUBSTR, was added.

Also in 1966 Robert Rosin published a pair of articles[8][9] discussing development of the preprocessor. This development was based in a "SHARE XXVI Memo" from earlier the same year and a paper by Mark Elson. Rosin credits MAD as the only previous example of a macro processor in a high-level language.

See also


  1. ^ IBM Corporation (2005). Enterprise PL/I for z/OS PL/I for AIX WebSphere Developer for zSeries PL/I for Windows Language Reference (PDF).
  2. ^ IBM Corporation (1995). IBM PL/I for MVS & VM Language Reference.
  3. ^ Sturm, Eberhard. "UIO-Makros für Builtin-Funktionen fileread und filewrite". Retrieved January 22, 2012.
  4. ^ IBM Corporation (1964). NPL Technical Report (PDF).
  5. ^ IBM Corporation (1965). IBM Operating System/360 PL/I: Language Specifications (C28-6571-1) (PDF).
  6. ^ IBM Corporation (1966). IBM Operating System/360 PL/I: Language Specifications (C28-6571-3) (PDF).
  7. ^ IBM Corporation (1969). IBM System/360 PL/I Reference Manual (C28-8201-3) (PDF).
  8. ^ Rosin, Robert (August 1966). "PL/I Macro Processor - Progress Report" (PDF). PL/I Bulletin (2). Retrieved January 22, 2013.
  9. ^ Rosin, Robert (August 1966). "Macros in PL/I" (PDF). PL/I Bulletin (2). Retrieved January 22, 2013.