Kednos PL/I for OpenVMS Systems
Reference Manual


Previous Contents Index

10.2.1 %Assignment Statement

The preprocessor assignment statement gives a value to a specified preprocessor variable.

The format of the assignment statement is:

%target = expression; 

target

The name of the preprocessor variable to be assigned a value. It must be an unsubscripted reference to a preprocessor variable.

expression

Any valid preprocessor expression.

For arithmetic operations, only decimal integer arithmetic of precision (10,0) is performed. Each operand and all results are converted, if necessary, to a fixed decimal value of precision (10,0). Fractional digits are truncated.

10.2.2 %Null

The %Null statement performs no action.

The format of the %Null statement is:

%; 

The most common use for the %Null statement is as the target statement of a %THEN or %ELSE clause in an %IF statement. For example:


%IF 
   ERROR() > 0; 
%THEN 
   %GOTO FIXIT; 
%ELSE 
   %; 

10.2.3 %ACTIVATE

The %ACTIVATE statement makes preprocessor variable and procedure identifiers eligible for replacement. If the compiler encounters the named identifier after executing a %ACTIVATE statement, it initiates variable replacement.

The format of the %ACTIVATE statement is:

%

element ,...;

element

The name of a previously declared preprocessor identifier and/or a list of identifiers, where the identifiers are separated by commas and the list is enclosed in parentheses.

RESCAN or NORESCAN

Specifies that the preprocessor is to continue or discontinue checking the text for secondary value replacement.

The RESCAN option specifies that preprocessor scanning continue until all possible identifier replacements are completed. RESCAN is the default option.

The NORESCAN option specifies that replacement be done only once; the resulting text is not rescanned for possible further replacement.

An identifier is activated by either a %ACTIVATE statement or a %DECLARE statement. When an activated identifier is encountered by the compiler, in unquoted nonpreprocessor statements, the variable name or procedure reference is replaced by its value. Replacement continues throughout the rest of the source program unless replacement is stopped with the %DEACTIVATE statement.

You can activate several variables with a single statement. For example:


%DECLARE (A,B,C) FIXED; 
%ACTIVATE (A,B), C NORESCAN; 

Because RESCAN is the default action, this statement activates A and B with the RESCAN option. C is activated, but is not rescanned.

If an identifier that is not a preprocessor variable or procedure is the target of a %ACTIVATE statement, a warning message is issued and the identifier is implicitly declared as a preprocessor variable with the FIXED attribute. Thereafter, the identifier variable is eligible for replacement when activated.

For example:


DECLARE (A,B,C) FIXED; 
%DECLARE (A,B) FIXED; 
%ACTIVATE (A,B); 
 
%A = 1; 
%B = (A + A); 
 
C = A + B; 
PUT SKIP LIST (C);    /* C = 3 */ 

In this example, the activated preprocessor variables A and B are assigned values by the preprocessor. Notice that variables A and B are also declared as nonpreprocessor variables; this establishes them as variables within the nonpreprocessor program.

In the following example, the variable B is deactivated by the %DEACTIVATE statement.


   .
   .
   .
%DEACTIVATE B; 
B = 900; 
C = A + B; 
PUT SKIP LIST (C);    /* C = 901 */ 
END; 

Because the preprocessor variable B is deactivated, the preprocessor assignment statement %B = (A + A) is not in effect and the value of B is taken from the run-time assignment of B = 900. However, the value of A remains 1.

10.2.4 %DEACTIVATE

The %DEACTIVATE statement makes preprocessor variable and procedure identifiers ineligible for replacement. After a variable or procedure has been deactivated, it will not be replaced during preprocessing. Replacement of a deactivated variable or procedure occurs again only after it is reactivated with the %ACTIVATE statement.

The format of the %DEACTIVATE statement is:

%

element,...;

element

The name of a preprocessor identifier, or a list of identifiers that is enclosed in parentheses. Deactivated elements must have been previously declared preprocessor variables.

For example:


TESTF:PROCEDURE OPTIONS (MAIN); 
      DECLARE Y FIXED DECIMAL; 
      Y = 10;                  /* initial value: Y = 10 */ 
      %DECLARE Y FIXED; 
      %Y = 3;                  /* replacement value: Y = 3 */ 
      PUT SKIP LIST(Y);        /* output: Y = 3 */ 
      %DEACTIVATE Y; 
      PUT SKIP LIST(Y);        /* output: Y = 10 */ 
      END; 

In this example, %Y, when activated, replaces all the occurrences of the variable Y by the value assigned to %Y, until %Y is deactivated by the %DEACTIVATE statement. The identifier %Y is implicitly activated when it is declared as a preprocessor identifier.

It is possible to deactivate several variables with a single statement. For example:


%DEACTIVATE (A,B,C,D,E,F); 

10.2.5 %DECLARE

The %DECLARE statement establishes an identifier as a preprocessor variable, specifies the data type of the variable, and activates the identifier for replacement. %DECLARE can occur anywhere in a PL/I source program.

The format of the %DECLARE statement is:

%

element ,...;

element

The name of a preprocessor identifier or a list of identifiers, which are separated by commas and enclosed in parentheses. You can give elements the attribute BIT, FIXED, or CHARACTER, but you cannot specify precision or length. The compiler supplies the variables with the following implied attributes:
Specified Attribute Implied Attributes
BIT (31) INITIAL ((31)'0'B)
FIXED DECIMAL (10,0) INITIAL (0)
CHARACTER VARYING (32500) INITIAL (' ')

If no data type is specified, FIXED is assumed.

When a variable is declared in a preprocessor statement, it is activated for replacement and rescanning. The scope of a preprocessor variable is all of the text following the declaration of the variable, unless the variable is declared inside a preprocessor procedure. Using %DECLARE inside of a preprocessor procedure has the effect of declaring a local variable.

For example:


%DECLARE HOUR FIXED; 

In this example, HOUR is declared as a preprocessor variable identifier with the FIXED attribute. The compiler supplies the default values that make this declaration the equivalent of the following:


DECLARE HOUR FIXED DECIMAL (10,0) INITIAL (0); 

Note

In preprocessor declarations, the attribute FIXED implies FIXED DECIMAL. In nonpreprocessor declarations, FIXED implies FIXED BINARY.

Factored declarations are permitted and follow the same usage rules as nonpreprocessor declarations. For example:


%DECLARE (A,B) CHARACTER, C BIT; 

Both A and B are declared with the CHARACTER attribute. The compiler supplies default values that make this declaration the equivalent of the following:


%DECLARE (A,B) CHARACTER VARYING(32500) INITIAL(''), 
         C BIT(31)INITIAL((31)'0'B); 

10.2.6 %DICTIONARY

The %DICTIONARY statement causes VAX Common Data Dictionary (CDD) data definitions to be incorporated into the current PL/I source file during compilation. The statement can occur anywhere in a PL/I source file. For information on using PL/I with CDD, see Appendix E in the Kednos PL/I for OpenVMS Systems User Manual.

The format of the %DICTIONARY statement is:

%DICTIONARY cdd-path; 

cdd-path

Any preprocessor expression. It is evaluated and converted to a CHARACTER string if necessary. The resulting character string is interpreted as the full or relative path name of a CDD object. The resultant path name must conform to all rules for forming VAX CDD path names. See the Common Data Dictionary Utilities Manual for details.

For example, assume that you have a record with the following path name:


CDD$TOP.SALES.JONES.SALARY 

You can then specify a relative path name as follows:


%DICTIONARY 'SALARY'; 

Or you can specify an absolute path name as follows:


%DICTIONARY '_CDD$TOP.SALES.JONES.SALARY'; 

The compiler extracts the record definition from the CDD and inserts the PL/I structure declaration corresponding to the record description in the PL/I program.

If the %DICTIONARY statement is not embedded in a PL/I language statement, then the resulting structure is declared with the logical level 1 and the BASED storage attribute is furnished. The logical member levels are incremented from 2. For example:


DECLARE PRICE FIXED BINARY(31); 
%DICTIONARY 'ACCOUNTS'; 
This would result in a declaration of the following form:


DECLARE PRICE FIXED BINARY(31); 
DECLARE 1 ACCOUNTS BASED, 
          2 NUMBER, 
            3 LEDGER CHARACTER(3), 
            3 SUBACCOUNT CHARACTER(5), 
          2 DATE CHARACTER(12), 
             . 
             . 
             . 
 

Notice that in the above example, ACCOUNTS is a relative dictionary path name.

If the %DICTIONARY statement is embedded in a PL/I language statement, as in a structure declaration, then the resulting structure is declared with no logical level and no storage attribute. Logical member numbers are supplied and incremented from 100. For example:


DECLARE 1 COMMON_INTERFACES STATIC EXTERNAL, 
          %DICTIONARY 'ACCOUNTS';   , 
          %DICTIONARY 'ADDRESSES';  ; 
Notice the syntax in the above %DICTIONARY example. The %DICTIONARY statement is terminated with the preprocessor terminator semicolon before the normal PL/I line punctuation. The normal PL/I punctuation must also be included so that the final structure declaration will contain proper PL/I punctuation. The previous declaration would result in a declaration of the following form:


DECLARE 1 COMMON_INTERFACES STATIC EXTERNAL, 
          100 ACCOUNTS, 
              101 NUMBER, 
                  102 LEDGER CHARACTER(3), 
                  102 SUBACCOUNT CHARACTER (5), 
              101 DATE CHARACTER(12), 
                 . 
                 . 
                 . 
          100 ADDRESSES, 
             . 
             . 
             . 

The CDD supports data types that are not native to PL/I. If a data definition contains an unsupported data type, PL/I makes the unsupported data type accessible by declaring it as data type BIT_FIELD or data type BYTE_FIELD. PL/I does not attempt to approximate a data type that is not supported by PL/I. For example, an F_FLOATING_COMPLEX number is declared BYTE_FIELD(8), not (2)FLOAT(24).

Note, however, that use of these two data types is limited. Data declared with the BIT_FIELD or BYTE_FIELD data type can be manipulated only with the PL/I built-in functions ADDR, INT, POSINT, SIZE, and UNSPEC. A variable declared with either of these data types can be passed as a parameter provided the parameter is declared as ANY. Thus, references to data declared as BIT_FIELD or BYTE_FIELD are limited to contexts in which the interpretation of a data type is not applied to the reference.

PL/I ignores CDD features that are not supported by PL/I, but issues error messages when the features conflict with PL/I.

When you extract a record definition from the CDD, you can choose to include this translated record in the program listing by using the /LIST/SHOW=DICTIONARY qualifiers in the PLI command line. Even if you choose not to list the extracted record, the names, data types, and offsets of the CDD record definition are displayed in the program listing allocation map.

CDD data definitions can contain explanatory text in the CDDL DESCRIPTION IS clause. This text is included in the PL/I listing comments, if /LIST/SHOW=DICTIONARY is specified. For example, you could use CDDL comments to indicate the data type of each structure and member. The punctuation for CDDL comments is the same as for other PL/I programs: the slash-asterisk (/*) and the asterisk-slash (*/).

10.2.7 %DO

The %DO statement begins a preprocessor DO-group, a sequence of statements terminating with the %END statement. The preprocessor DO-group must be a simple DO-group and is noniterative, but it can be usefully combined with an %IF statement.

The format of the %DO statement is:

You can include both preprocessor and nonpreprocessor text in a preprocessor DO-group. For example:


%DECLARE T CHARACTER;          /* declare T */ 
%ACTIVATE T NORESCAN;          /* activate T for replacement */ 
   .
   .
   .
%IF VARIANT() = 'NONE'; 
   %THEN 
   %DO; 
   %T = '''unknown variant'''; /* assign string to T */ 
   %WARN T;                    /* output unknown variant 
                                  warning at compile time */ 
   INIT_MESSAGE = INIT_MESSAGE||' with '||T; /* assign 
                               value of T to nonpreprocessor 
                                    variable */ 
   %END; 

This preprocessor DO-group performs several steps. First, a string constant is assigned to T. Then the value of T is used in a preprocessor user-generated diagnostic message. This message is issued at compile time to warn the programmer that the program is compiled with an unknown variant. Finally, the value of T is concatenated with a nonpreprocessor string constant. INIT_MESSAGE, including the value of T, is part of the run-time image.

10.2.8 %END

The %END statement terminates a preprocessor procedure or DO-group.

The format of the %END statement is:

%END; 

Preprocessing then continues with the next executable preprocessor statement.

10.2.9 %ERROR

The %ERROR statement provides a diagnostic error message during program compilation.

The format of the %ERROR statement is:

%ERROR preprocessor-expression; 

preprocessor-expression

A maximum of 64 characters giving the text of the error message to be displayed. Messages of more than 64 characters are truncated.

Returned Message

The message displayed by %ERROR is:


%PLIG-E-USERDIAG, preprocessor-expression 

Compilation errors that result in the display of the %ERROR statement increment the informational diagnostic count displayed in the compilation summary, and inhibit production of an object file.

10.2.10 %FATAL

The %FATAL statement provides a diagnostic fatal message during program compilation.

The format of the %FATAL statement is:

%FATAL preprocessor-expression; 

preprocessor-expression

The text of the fatal message you want displayed. The text is a character string with a maximum length of 64 characters. It is truncated if necessary.

Returned Message

The message displayed by %FATAL is:


%PLIG-F-USERDIAG, preprocessor-expression 

Compilation errors that result in a fatal error terminate compilation after the message is displayed.

10.2.11 %GOTO

The %GOTO statement causes the preprocessor to interrupt its sequential processing of source text and continue processing at the point specified in the %GOTO statement. A %GOTO is useful for avoiding large segments of text in the source program.

The format of the %GOTO statement is:

%GOTO label-reference; 

label-reference

A label of a preprocessor statement. The label reference determines the point to which the compiler processing will be transferred.

Nonlocal %GOTOs are not permitted. In other words, if a %GOTO is used within a preprocessor procedure, control must not be passed out of the containing procedure. Also, a %GOTO must not transfer control into a preprocessor procedure.

The following example illustrates transfers (forward and backward) and the use of %GOTO:


%TEXT:PROCEDURE RETURNS(CHARACTER); 
         .
         .
         .
%CHANG_TEXT: DO; 
   .
   .
   .
%IF WARN() = 5 
    %THEN 
         %GOTO CHANG_TEXT; 
 
    %ELSE 
         %GOTO INSERT_TEXT; 
             .
             .
             .
 
%INSERT_TEXT: DO; 
   .
   .
   .
%END; 

Depending on the status of the %IF statement in this example, program compilation takes one of two courses. Control is transferred either forward to the statement labeled INSERT_TEXT or backward to the statement labeled CHANG_TEXT. The compiled program will then include one of the two blocks, but not both. Notice also in this example that the preprocessor built-in function WARN is used to determine preprocessor action, which makes the program self-diagnostic.

If program text is not compiled because the %GOTO statement transferred control over it, the compiler still checks the basic syntax of all statements. Therefore, comment delimiters and parentheses must balance, apostrophes must be paired correctly, and all statements must end with a semicolon.

10.2.12 %IF

The %IF statement controls the flow of program compilation according to the scalar bit value of a preprocessor expression. The %IF statement tests the preprocessor expression and performs the 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-expression

Any valid preprocessor expression that yields a scalar bit value. If any bit of the value is 1, then the expression is true; otherwise, the expression is false.

action

A single, unlabeled preprocessor statement, %DO-group, %GOTO statement, or a preprocessor null statement. The specified action must not be an %END statement.

The %IF statement evaluates the preprocessor test expression. If the expression is true, the action specified following the keyword %THEN is compiled. Otherwise, the action, if any, following the %ELSE keyword is compiled. In either case, compilation resumes at the first executable statement following the termination of the %IF statement, unless a %GOTO in one of the action clauses causes compilation to resume elsewhere.

If an action is not compiled because the alternative action was compiled instead, the compiler still checks the basic syntax of all statements. Therefore, comment delimiters and parentheses must balance, apostrophes must be paired correctly, and all statements must end with a semicolon.

10.2.13 %INCLUDE

The %INCLUDE statement incorporates text from other files into the current source file during compilation. It can occur anywhere in a PL/I source file; it need not be part of a procedure.

The format of the %INCLUDE statement is:

%INCLUDE

;

file-spec

A file specification enclosed in apostrophes interpreted as the complete file specification or path, including the device, directory, and file name. For the specification is subject to logical name translation and the application of default values by the OpenVMS operating system.

module-name

The 1- to 31-character name of a text module in a library of included files and/or other text modules.

library-name

The library containing the specified text module. Enclose the library and module in apostrophes. If you do not specify the library in the %INCLUDE statement, and if the text module is not in PLI$STARLET or in the text library pointed to by PLI$LIBRARY, you must specify the name of the library containing the module in the PLI compilation command.

Examples


%INCLUDE 'SUM.PLI'; 

This statement copies the contents of the file SUM.PLI into the current file during compilation.


%INCLUDE SYSTEM_PROCEDURES; 

This statement includes a module from a text module library. The library containing the module SYSTEM_PROCEDURES must be present in the command that compiles this program, or the logical name PLI$LIBRARY can point to the library that contains it.


%INCLUDE 'PROJECT_LIBRARY(MY_MODULE)'; 

This statement includes module MY_MODULE from the text library PROJECT_LIBRARY.TLB in the default directory.

Restrictions

%INCLUDE statements can be nested up to a maximum of four levels.


Previous Next Contents Index