Previous: Form of Definitions File, Up: Preprocessing with gnatprep


3.10.2.5 Form of Input Text for gnatprep

The input text may contain preprocessor conditional inclusion lines, as well as general symbol substitution sequences.

The preprocessor conditional inclusion commands have the form:

    #if <expression> [then]
       lines
    #elsif <expression> [then]
       lines
    #elsif <expression> [then]
       lines
    ...
    #else
       lines
    #end if;

In this example, <expression> is defined by the following grammar:

    <expression> ::=  <symbol>
    <expression> ::=  <symbol> = "<value>"
    <expression> ::=  <symbol> = <symbol>
    <expression> ::=  <symbol> = <integer>
    <expression> ::=  <symbol> > <integer>
    <expression> ::=  <symbol> >= <integer>
    <expression> ::=  <symbol> < <integer>
    <expression> ::=  <symbol> <= <integer>
    <expression> ::=  <symbol> 'Defined
    <expression> ::=  not <expression>
    <expression> ::=  <expression> and <expression>
    <expression> ::=  <expression> or <expression>
    <expression> ::=  <expression> and then <expression>
    <expression> ::=  <expression> or else <expression>
    <expression> ::=  ( <expression> )

Note the following restriction: it is not allowed to have "and" or "or" following "not" in the same expression without parentheses. For example, this is not allowed:

    not X or Y

This can be expressed instead as one of the following forms:

    (not X) or Y
    not (X or Y)

For the first test (<expression> ::= <symbol>) the symbol must have either the value true or false, that is to say the right-hand of the symbol definition must be one of the (case-insensitive) literals True or False. If the value is true, then the corresponding lines are included, and if the value is false, they are excluded.

When comparing a symbol to an integer, the integer is any non negative literal integer as defined in the Ada Reference Manual, such as 3, 16#FF# or 2#11#. The symbol value must also be a non negative integer. Integer values in the range 0 .. 2**31-1 are supported.

The test (<expression> ::= <symbol>'Defined) is true only if the symbol has been defined in the definition file or by a `-D' switch on the command line. Otherwise, the test is false.

The equality tests are case insensitive, as are all the preprocessor lines.

If the symbol referenced is not defined in the symbol definitions file, then the effect depends on whether or not switch `-u' is specified. If so, then the symbol is treated as if it had the value false and the test fails. If this switch is not specified, then it is an error to reference an undefined symbol. It is also an error to reference a symbol that is defined with a value other than True or False.

The use of the not operator inverts the sense of this logical test. The not operator cannot be combined with the or or and operators, without parentheses. For example, "if not X or Y then" is not allowed, but "if (not X) or Y then" and "if not (X or Y) then" are.

The then keyword is optional as shown

The # must be the first non-blank character on a line, but otherwise the format is free form. Spaces or tabs may appear between the # and the keyword. The keywords and the symbols are case insensitive as in normal Ada code. Comments may be used on a preprocessor line, but other than that, no other tokens may appear on a preprocessor line. Any number of elsif clauses can be present, including none at all. The else is optional, as in Ada.

The # marking the start of a preprocessor line must be the first non-blank character on the line, i.e., it must be preceded only by spaces or horizontal tabs.

Symbol substitution outside of preprocessor lines is obtained by using the sequence:

    $symbol

anywhere within a source line, except in a comment or within a string literal. The identifier following the $ must match one of the symbols defined in the symbol definition file, and the result is to substitute the value of the symbol in place of $symbol in the output file.

Note that although the substitution of strings within a string literal is not possible, it is possible to have a symbol whose defined value is a string literal. So instead of setting XYZ to hello and writing:

    Header : String := "$XYZ";

you should set XYZ to "hello" and write:

    Header : String := $XYZ;

and then the substitution will occur as desired.