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 #included 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.
Fpp permits comments of two kinds:
-
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.
-
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.