Mechanics Fortran Preprocessor

307 views Asked by At

I recently happened to come across the preprocessing option most Fortran compilers support these days (as explained e.g. in the Fortran Wiki) . Coming from a C background, I would like to better understand the mechanics and caveats related to the (Fortran-)preprocessor's #include directive.

To avoid any confusion right from the beginning: there are two include directives in Fortran (see e.g. F77 reference)

  • include "foo" is a compiler directive, i.e. foo can only contain Fortran statements
  • #include "bar" is a preprocessor directive, i.e. bar can contain #defines and the like

I am aware of this difference and I am interested in the second case only (my question is therefore not a duplicate of this post).

I'll explain my questions using an example: assume we have two files, a header file (macro.h) and a source file (display.F):

macro.h

#define MSG() say_hello()

display.F

#include "macro.h"

    PROGRAM display
    CALL MSG()
    CALL another_message()
    END

    SUBROUTINE say_hello()
    WRITE(*,*) 'Hello.'
    END

    SUBROUTINE another_message()
    CALL MSG()
    END

Here are my questions:

Scope

where (globally, locally in the SUBROUTINE etc.) is the macro MSG() defined if I include macro.h:

  1. at the beginning of the file (as above)?
  2. at the beginning of the PROGRAM display (and nowhere else)?
  3. at the beginning of e.g. SUBROUTINE another_message() (and nowhere else)?

From testing it seems: 1. globally, 2. in PROGRAM and all SUBROUTINES, 3. in that SUBROUTINE only. A confirmation of these assumptions and some theoretical explanations why would be great.

What of above (1. - 3.) is best practice for preprocessor includes?

Include Guards

If I have a multi-file project and I include header.h in multiple *.F source files, do I need to provide include guards?

In case the answers to the above questions should be compiler dependent (as preprocessing is not Fortran standard), I'd be most interested in ifort's behaviour.

1

There are 1 answers

0
Vladimir F Героям слава On BEST ANSWER

The rules are the same as for the C preprocessor you know. GCC even uses the same cpp for C and Fortran (for Fortran in the traditional mode). Therefore there is no scope around, everything is just a text and the preprocessor doesn't care about program units.

Therefore, 1., 2. and 3. all are valid from the place of their definition until the file end or until #undef. They are also valid in recursively #included files.

If by guards you mean #undef then yes, otherwise a warning or error about redefinition appears, but only if you include all those files from a single file. If they are independent then no.

The key is to think about the preprocessor as a text replacement tool. It knows nothing about Fortran.

Last thing, the preprocessor is non-standard, but widely available.