GNAT GPL User's Guide: Preprocessing with gnatprep

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

# 18. Preprocessing with `gnatprep`

This chapter discusses how to use GNAT's `gnatprep` utility for simple preprocessing. Although designed for use with GNAT, `gnatprep` does not depend on any special GNAT features. For further discussion of conditional compilation in general, see E. Conditional Compilation.

> 18.1 Preprocessing Symbols |  |
> 18.2 Using `gnatprep` |  |
> 18.3 Switches for `gnatprep` |  |
> 18.4 Form of Definitions File |  |
> 18.5 Form of Input Text for `gnatprep` |  |

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 18.1 Preprocessing Symbols

Preprocessing symbols are defined in definition files and referred to in sources to be preprocessed. A Preprocessing symbol is an identifier, following normal Ada (case-insensitive) rules for its syntax, with the restriction that all characters need to be in the ASCII set (no accented letters).

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 18.2 Using `gnatprep`

To call `gnatprep` use

    $ gnatprep [switches] infile outfile [deffile]

where

switches
  is an optional sequence of switches as described in the next section.

infile
  is the full name of the input file, which is an Ada source file containing preprocessor directives.

outfile
  is the full name of the output file, which is an Ada source in standard Ada form. When used with GNAT, this file name will normally have an ads or adb suffix.

deffile
  is the full name of a text file containing definitions of preprocessing symbols to be referenced by the preprocessor. This argument is optional, and can be replaced by the use of the ``-D'` switch.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 18.3 Switches for `gnatprep`

``-b'`
  Causes both preprocessor lines and the lines deleted by preprocessing to be replaced by blank lines in the output source file, preserving line numbers in the output file.

``-c'`
  Causes both preprocessor lines and the lines deleted by preprocessing to be retained in the output source as comments marked with the special string `"--! "`. This option will result in line numbers being preserved in the output file.

``-C'`
  Causes comments to be scanned. Normally comments are ignored by gnatprep. If this option is specified, then comments are scanned and any $symbol substitutions performed as in program text. This is particularly useful when structured comments are used (e.g., when writing programs in the SPARK dialect of Ada). Note that this switch is not available when doing integrated preprocessing (it would be useless in this context since comments are ignored by the compiler in any case).

``-Dsymbol=value'`
  Defines a new preprocessing symbol, associated with value. If no value is given on the command line, then symbol is considered to be `True`. This switch can be used in place of a definition file.

``-r'`
  Causes a `Source_Reference` pragma to be generated that references the original input file, so that error messages will use the file name of this original file. The use of this switch implies that preprocessor lines are not to be removed from the file, so its use will force ``-b'` mode if ``-c'` has not been specified explicitly.

  Note that if the file to be preprocessed contains multiple units, then it will be necessary to `gnatchop` the output file from `gnatprep`. If a `Source_Reference` pragma is present in the preprocessed file, it will be respected by `gnatchop -r` so that the final chopped files will correctly refer to the original input source file for `gnatprep`.

``-s'`
  Causes a sorted list of symbol names and values to be listed on the standard output file.

``-u'`
  Causes undefined symbols to be treated as having the value FALSE in the context of a preprocessor test. In the absence of this option, an undefined symbol in a `#if` or `#elsif` test will be treated as an error.

Note: if neither ``-b'` nor ``-c'` is present, then preprocessor lines and deleted lines are completely removed from the output, unless -r is specified, in which case -b is assumed.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 18.4 Form of Definitions File

The definitions file contains lines of the form

    symbol := value

where symbol is a preprocessing symbol, and value is one of the following:

- Empty, corresponding to a null substitution
- A string literal using normal Ada syntax
- Any sequence of characters from the set (letters, digits, period, underline).

Comment lines may also appear in the definitions file, starting with the usual `--`, and comments may be added to the definitions lines.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 18.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 )

The following restriction exists: 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 should be one of the following:

       (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.

[ << ] | [ >> ] |  |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

This document was generated by GNAT Mailserver on April, 17 2014 using texi2html