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 #included files) from that definition line to the end of the current file.

However, it does not affect:

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

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.

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":

for #include <filename>: 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):

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:

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.