NAG Fortran Compiler, Release 7.2: Preprocessing details

Navigation: Previous Up Next

## 4.6 Preprocessing details

### 4.6.1 Scope of macro or variable definitions

The scope of a definition begins from the place of its definition and encloses all the source lines (and source lines from `#include`d files) from that definition line to the end of the current file.

However, it does not affect:

- files included by Fortran `INCLUDE` lines;
- fpp and Fortran comments;
- `IMPLICIT` single letter specifications;
- `FORMAT` statements;
- numeric and character constants.

The scope of the macro effect can be limited by means of the `#undef` directive.

### 4.6.2 End of macro definition

A macro definition can be of any length but is only one logical line. These may be split across multiple physical lines by ending each line but the last with the macro continuation character ‘\’ (backslash). The backslash and newline are not part of the replacement text. The macro definition is ended by a newline that is not preceded by a backslash.

For example:

      #define long_macro_name(x,\
      y) x*y

### 4.6.3 Function-like macro definition

The number of macro call arguments must be the same as the number of arguments in the corresponding macro definition. An error is produced if a macro is used with the wrong number of arguments.

### 4.6.4 Cancelling macro definitions

`#undef` name

After this directive, ‘name’ will not be interpreted by fpp as a macro or variable name. This directive has no effect if ‘name’ is not a macro name.

### 4.6.5 Conditional source code selection

`#if` condition

Condition is a constant expression, as specified below. Subsequent lines up to the first matching `#elif`, `#else` or `#endif` directive appear in the output only if the condition is true.

The lines following a `#elif` directive appear in the output only if

- the condition in the matching `#if` directive was false,
- the conditions in all previous matching `#elif` directives were false, and
- the condition in this `#elif` directive is true.

If the condition is true, all subsequent matching `#elif` and `#else` directives are ignored up to the matching `#endif`.

The lines following a `#else` directive appear in the output only if all previous conditions in the construct were false.

The macro function ‘defined’ can be used in a constant expression; it is true if and only if its argument is a defined macro name.

The following operations are allowed.

- C language operations: `<`, `>`, `==`, `!=`, `>=`, `<=`, `+`, `-`, `/`, `*`, `%`, `<<`, `>>`, `&`, `~`, `|`, `!`, `&&` and `||`. These are interpreted in accordance with C language semantics, for compatibility with cpp.
- Fortran language operations: `.AND.`, `.OR.`, `.NEQV.`, `.XOR.`, `.EQV.`, `.NOT.`, `.GT.`, `.LT.`, `.LE.`, `.GE.`, `.NE.`, `.EQ.` and `**`.
- Fortran logical constants: `.TRUE.` and `.FALSE.`.

Only these items, integer literal constants, and names can be used within a constant expression. Names that are not macro names are treated as if they were ‘0’. The C operation ‘`!=`’ (not equal) can be used in `#if` or `#elif` directives, but cannot be used in a `#define` directive, where the character ‘`!`’ is interpreted as the start of a Fortran comment.

`#ifdef` name
  Subsequent lines up to the matching #else, #elif, or #endif appear in the output only if the name has been defined, either by a #define directive or by the -D option, and in the absence of an intervening #undef directive. No additional tokens are permitted on the directive line after name.
`#ifndef` name
  Subsequent lines up to the matching #else, #elif, or #endif appear in the output only if name has not been defined, or if its definition has been removed with an #undef directive. No additional tokens are permitted on the directive line after name.
`#elif` constant-expression
  Any number of #elif directives may appear between an #if, #ifdef, or #ifndef directive and a matching #else or #endif directive.
`#else`
  This inverts the sense of the conditional directive otherwise in effect. If the preceding conditional would indicate that lines are to be included, then lines between the `#else` and the matching `#endif` are ignored. If the preceding conditional indicates that lines would be ignored, subsequent lines are included in the output.
#endif
  End a section of lines begun by one of the conditional directives #if, #ifdef, or #ifndef. Each such directive must have a matching #endif.

### 4.6.6 Including external files

Files are searched as follows:

for `#include "`filename`"`:

- in the directory, in which the processed file has been found;
- in the directories specified by the -I option;
- in the default directory.

for `#include <`filename`>`:

- in the directories specified by the -I option;
- in the default directory.

Fpp directives (lines beginning with the `#` character) can be placed anywhere in the source code, in particular immediately before a Fortran continuation line. The only exception is the prohibition of fpp directives within a macro call divided on several lines by means of continuation symbols.

### 4.6.7 Comments

Fpp permits comments of two kinds:

1. Fortran language comments. A source line containing one of the characters ‘`C`’, ‘`c`’, ‘`*`’, ‘`d`’ or ‘`D`’ in the first column is considered to be a comment line. Within such lines macro expansions are not performed. The ‘`!`’ character is interpreted as the beginning of a comment extending to the end of the line. The only exception is the case when this symbol occurs within a constant expression in a `#if` or `#elif` directive.
2. Fpp comments enclosed in the ‘`/*`’ and ‘`*/`’ character sequences. These are excluded from the output. Fpp comments can be nested so that for each opening sequence ‘`/*`’ there must be a corresponding closing sequence ‘`*/`’. Fpp comments are suitable for excluding the compilation of large portions of source instead of commenting every line with Fortran comment symbols. Using “`#if 0 ... #endif`” achieves the same effect without being ridiculous.

### 4.6.8 Macro functions

The macro function

`defined`(name) or `defined` name

expands to `.TRUE.` if name is defined as a macro, and to `.FALSE.` otherwise.

### 4.6.9 Macro expression

If, during expansion of a macro, the column width of a line exceeds column 72 (for fixed form) or column 132 (for free form), fpp inserts appropriate continuation lines.

In fixed form there are limitations on macro expansion in the label part of the line (columns 1-5):

- a macro call (together with possible arguments) should not extend past column 5;
- a macro call whose name begins with one of the Fortran comment characters is treated as a comment;
- a macro expansion may produce text extending beyond the column 5 position. In such a case a warning will be issued.

In the fixed form when the -Xw option has been specified an ambiguity may appear if a macro call occurs in a statement position and a macro name begins or coincides with a Fortran keyword. For example, in the following text:

      #define call p(x)   call f(x)
              call p(0)

fpp can not determine with certainty how to interpret the ‘call p’ token sequence. It could be considered as a macro name. The current implementation does the following:

- the longer identifier is chosen (callp in this case);
- from this identifier the longest macro name or keyword is extracted;
- if a macro name has been extracted a macro expansion is performed. If the name begins with some keyword fpp outputs an appropriate warning;
- the rest of the identifier is considered as a whole identifier.

In the above example the macro expansion would be performed and the following warning would be output:

warning: possibly incorrect substitution of macro callp

It should be noted that this situation appears only when preprocessing fixed form source code and when the blank character is not being interpreted as a token delimiter. It should be said also that if a macro name coincides with a keyword beginning part, as in the following case:

         #define INT    INTEGER*8
                 INTEGER k

then in accordance with the described algorithm, the INTEGER keyword will be found earlier than the INT macro name. Thus, there will be no warning when preprocessing such a macro definition.