Difference between revisions of "C Preprocessor"

From WikiROMS
Jump to navigationJump to search
Line 32: Line 32:
==cpp_clean==
==cpp_clean==


The preprocessor reads the source file (*.F) and builts a target file (*.f90) according to activated cpp options. This target *.f90 file is then processed by cpp_clean to clean all
The preprocessor reads the source file (*.F) and builts a target file (*.f90) according to activated cpp options. This target *.f90 file is then processed by the perl script cpp_clean to clean all commented (#) lines inserted by cpp to make it more readable. This is actualy the file that is compiled by the Fortran compiler.

Revision as of 20:51, 1 November 2006

ROMS extensively uses the C preprocessor (cpp) during compilation to replace code statements, insert files into the code, and select relevant parts of the code depending on its directives. There are numerous cpp options that can be activated in header files cppdefs.h and globaldefs.h.

Cpp is in the ANSI C standard, but that version isn't quite right for preprocessing of Fortran. We therefore use the -traditional flag with the Gnu cpp and similar flags with others.

Preprocessor Directives:

  • The #define directive comes in three flavors:
  1. Turning on a logical switch. For example, the following definition will activate tidal forcing in the open boundary conditions to the barotropic momentum equations:
    #define UV_TIDES
  2. String substitution. The preprocessor will replace the symbolic name with the specified text everywhere in the code. For example, the following assigment is used to set the dimensions of private, automatic 2D arrays:
    #define PRIVATE_2D_SCRATCH_ARRAY Istr-3:Iend+3,Jstr-3:Jend+3
  3. Macro substitution. This functionality is better done through statement functions or inline functions which allow the Fortran compiler to do type checking.
  • The #undef directive undefines or deactiaves symbolic names. For example, the following option is used in parallel debugging to turn on/off the writing of current date and cpp options in ROMS history NetCDF files:
    #undef DEBUGGING
  • The #include directive allows one to insert the contents of another file into the source code. For example, the following statement is used to insert the tile-bounds header file that computes the horizontal sub-domain indices of RHO-, U- and V-type variables.
    #include "set_bounds.h"
  • The #ifdef, #endif directive or its equivalent #if defined, #endif allows to control whether the preprocessor omits and includes part of the source code. For example, the following code section is used to activate time profiling during execution:
    #ifdef PROFILE
    CALL wclocko_on (ng, iNLM, 13)
    #endif
  • The #ifndef, #endif directive or its equivalent #if !defined, #endif is the opposite. It is executed only when the symbol is not defined or activated. For example, the following statement is used to reference to the equation of state module only when the option TS_FIXED is not activated.
    #ifndef TS_FIXED
    USE rho_eos_mod, ONLY: rho_eos
    #endif
  • The #if <test1>, #elif <test2> #endif is a more general case of the above. In this case, the tests are often of the form:
    defined BBL_MODEL && (defined MB_BBL || defined SSW_BBL)
    Here, || is a logical or while && is a logical and. Notice that conditional expressions as used in ROMS require the defined syntax.
  • The conditional tests are a matter of style and the Gnu coding standards use a different style. Theirs is to always:
#define FLOATS 1
instead of simply:
#define FLOATS
This allows a test to be on the tag rather than defined tag.

cpp_clean

The preprocessor reads the source file (*.F) and builts a target file (*.f90) according to activated cpp options. This target *.f90 file is then processed by the perl script cpp_clean to clean all commented (#) lines inserted by cpp to make it more readable. This is actualy the file that is compiled by the Fortran compiler.