Chapter 7. Source Preprocessing

Source preprocessing can help you port a program from one platform to another by allowing you to specify source text that is platform specific.

For a source file to be preprocessed automatically, it must have an uppercase extension, either .F (for a file in fixed source form) or .F90 (for a file in free source form). Files with these suffixes are preprocessed automatically by the Fortran preprocessor.

To specify preprocessing of source files with other extensions, including lowercase ones, use the -cpp, -E, -ftpp, or -P options described in Chapter 2, “Invoking MIPSpro 7 Fortran 90”.

General Rules

You can alter the source code through source preprocessing directives. These directives are fully explained in “Directives”. The directives must be used according to the following rules:

  • Do not attempt macro substitution in Fortran comments. This will cause macros beginning with a C in column 1 (in fixed source form) not to be substituted.

  • When the Fortran preprocessor is used, you must specify -macro_expand on the f90(1) command line if you want to enable macro expansion outside of preprocessor directive lines.

  • Do not use source preprocessor (#) directives within multiline compiler directives.

  • You cannot include a source file that contains an #if directive without a balancing #endif directive within the same file.

    The #if directive includes the #ifdef and #ifndef directives.

  • If a directive is too long for one source line, the backslash character (\) is used to continue the directive on successive lines. Successive lines of the directive can begin in any column (up to the column limit of 132).

    The backslash character (\) can appear in any location within a directive in which whitespace can occur. A backslash character (\) in a comment is treated as a comment character. It is not recognized as signaling continuation.

  • Every directive begins with the pound character (#), and the pound character (#) must be in column 1.

  • Blank and tab (HT) characters can appear between the pound character (#) and the directive keyword.

  • You cannot write form feed (FF) or vertical tab (VT) characters to separate tokens on a directive line. That is, if a source preprocessing line spans lines, it must be continued by using a backslash character (\).

  • Blanks are significant, so the use of spaces within a source preprocessing directive is independent of the source form of the file. The fields of a source preprocessing directive must be separated by blank or tab (HT) characters.

  • Because source preprocessing directives are independent of source form, a directive can be up to 132 columns on a single source line.

    Any directive text that extends past column 132 is ignored. The directive text is truncated, which is likely to produce parsing errors or unexpected results. If a directive is too long to fit on a single line, you can continue the line by using the backslash character (\). It cannot be continued using standard Fortran continuation methods.

  • Any user-specified identifier that is used in a directive must follow Fortran rules for identifier formation. There are two exceptions to this rule:

    • The first character in the name can be an underscore character (_).

    • Although Fortran rules state that only the first 31 characters of identifiers are significant, to the source preprocessor, the first 132 characters are significant.

  • Source preprocessing identifier names are case sensitive.

  • Numeric literal constants must be integer literal constants or real literal constants, as defined for Fortran.

  • Comments written in the style of the C language, beginning with /* and ending with */, can appear anywhere within a source preprocessing directive in which blanks or tabs can appear. The comment, however, must begin and end on a single source line.

  • The blanks shown in the syntax descriptions of the source preprocessing directives are significant. The tab character (HT) can be used in place of a blank. Multiple blanks can appear wherever a single blank appears in a syntax description.

Directives

The following sections describe the source preprocessing directives.

#include Directive

The #include directive directs the system to use the content of a file or directory. Just as with the INCLUDE line processing defined by the Fortran standard, an #include directive effectively replaces that directive line with the content of filename. This directive has the following formats:

#include "filename"
#include <filename>
filename

A file or directory to be used.

In the first form, if filename does not begin with a slash (/) character, the system searches for the named file, first in the directory of the file containing the #include directive, then in the sequence of directories specified by the -I option(s) on the f90(1) command line, and then the standard (default) sequence. If filename begins with a slash (/) character, it is used as is and is assumed to be the full path to the file.

The second form directs the search to begin in the sequence of directories specified by the -I option(s) on the f90(1) command line and then search the standard (default) sequence.

The Fortran standard prohibits recursion in INCLUDE files, so recursion is also prohibited in the #include form.

The #include directives can be nested.

When the compiler is invoked to do only source preprocessing, not compilation, text will be included by #include directives but not by Fortran INCLUDE lines. For information on the source preprocessing command line options, see “Command Line Options”.

#define Directive

The #define directive lets you declare a source preprocessing variable and associate a token string with the variable. It also allows you to define a function-like macro. This directive has the following formats:

#define identifiervalue
#define identifier(dummy_arg_list) value

The first format defines an object-like macro (also called a source preprocessing variable), and the second defines a function-like macro. In the second format, the left parenthesis that begins the dummy_arg_list must immediately follow the identifier, with no intervening white space.

identifier

Specifies the name of the variable or macro being defined.

dummy_arg_list

Specifies a list of dummy argument identifiers.

value

Specifies the value as a sequence of tokens. The value can be continued onto more than one line using backslash (\) characters.

If a preprocessor identifier appears in a subsequent #define directive without being the subject of an intervening #undef directive, and the value in the second #define directive is different from the value in the first #define directive, then the preprocessor issues a warning message about the redefinition. The second directive's value is used. For more information on the #undef directive, see “#undef Directive”.

When an object-like macro's identifier is encountered as a token in the source file, it is replaced with the value specified in the macro's definition. This is referred to as an invocation of the macro. By default, tokens are not processed in Fortran source code. They are recognized only when used in other source preprocessing directives.

The invocation of a function-like macro is more complicated. It consists of the macro's identifier, immediately followed by a left parenthesis with no intervening white space, then a list of actual arguments separated by commas, and finally a terminating right parenthesis. There must be the same number of actual arguments in the invocation as there are dummy arguments in the #define directive. Each actual argument must be balanced in terms of any internal parentheses. The invocation is replaced with the value given in the macro's definition, with each occurrence of any dummy argument in the definition replaced with the corresponding actual argument in the invocation.

The following two examples must be compiled with -macro_expand specified on the f90(1) command line:

  • The following program prints Hello, world. when compiled and run:

          PROGRAM P
    #define GREETING 'Hello, world.'
          PRINT *, GREETING
          END PROGRAM P

  • The following program prints Hello, Hello, world. when compiled and run:

          PROGRAM P
    #define GREETING(str1, str2) str1, str1, str2
          PRINT *, GREETING('Hello, ', 'world.')
          END PROGRAM P

For information on the -macro_expand option, see “-macro_expand” in Chapter 2.

#undef Directive

The #undef directive sets the definition state of identifier to an undefined value. If identifier is not currently defined, the #undef directive has no effect. This directive has the following format:

#undef identifier
identifier

Specifies the name of the source preprocessing variable or macro being undefined.

# (Null) Directive

The null directive simply consists of the pound character (#) in column 1 with no significant characters following it. That is, the remainder of the line is typically blank or is a source preprocessing comment. This directive is generally used for spacing out other directive lines.

Conditional Directives

Conditional directives cause lines of code to either be produced by the source preprocessor or to be skipped. The conditional directives within a source file form if-groups. An if-group begins with an #if, #ifdef, or #ifndef directive, followed by lines of source code that you may or may not want skipped. Several similarities exist between the Fortran IF construct and if-groups:

  • The #elif directive corresponds to the ELSE IF statement.

  • The #else directive corresponds to the ELSE statement.

  • Just as an IF construct must be terminated with an END IF statement, an if-group must be terminated with an #endif directive.

  • Just as with an IF construct, any of the blocks of source statements in an if-group can be empty.

    For example, you can write the following directives:

    #if MIN_VALUE == 1
    #else
      ...
    #endif

Determining which group of source lines (if any) to compile in an if-group is essentially the same as the Fortran determination of which block of an IF construct should be executed.

#if Directive

The #if directive has the following format:

#if expression
expression

An expression. The values in expression must be integer literal constants or previously defined preprocessor variables. The expression is an integer constant expression as defined by the C language standard. All the operators in the expression are C operators, not Fortran operators. The expression is evaluated according to C language rules, not Fortran expression evaluation rules.

Note that unlike the Fortran IF construct and IF statement logical expressions, the expression in an #if directive need not be enclosed in parentheses.

The #if expression can also contain the unary defined operator, which can be used in either of the following formats:

defined identifier
defined(identifier)

When the defined subexpression is evaluated, the value is 1 if identifier is currently defined, and 0 if it is not.

All currently defined source preprocessing variables in expression, except those that are operands of defined unary operators, are replaced with their values. During this evaluation, all source preprocessing variables that are undefined evaluate to 0.

Note that the following two directive forms are not equivalent:

  • #if X

  • #if defined(X)

In the first case, the condition is true if X has a nonzero value. In the second case, the condition is true only if X has been defined (has been given a value that could be 0).

#ifdef Directive

The #ifdef directive is used to determine if identifier is predefined by the source preprocessor, has been named in a #define directive, or has been named in the -D option on the f90(1) command line. For more information on the -D option, see “Command Line Options”.

This directive has the following format:

#ifdef identifier

The #ifdef directive is equivalent to either of the following two directives:

  • #if defined identifier

  • #if defined(identifier)

#ifndef Directive

The #ifndef directive tests for the presence of an identifier that is not defined. This directive has the following format:

#ifndef identifier

This directive is equivalent to either of the following two directives:

  • #if ! defined identifier

  • #if ! defined(identifier)

#elif Directive

The #elif directive serves the same purpose in an if-group as does the ELSE IF statement of a Fortran IF construct. This directive has the following format:

#elif expression
expression

The expression follows all the rules of the integer constant expression in an #if directive.

#else Directive

The #else directive serves the same purpose in an if-group as does the ELSE statement of a Fortran IF construct. This directive has the following format:

#else

#endif Directive

The #endif directive serves the same purpose in an if-group as does the END IF statement of a Fortran IF construct. This directive has the following format:

#endif

Predefined Macros

The MIPSpro 7 Fortran 90 source preprocessor supports a number of predefined macros. They are divided into groups as follows:

  • Macros that are based on the host machine

  • Macros that are based on IRIX system targets

The following predefined macros are based on the host system (the system upon which the compilation is being done):

Macro 

Notes

__unix 

Always defined. The leading characters consist of 2 consecutive underscores.

The following predefined macros are based on an IRIX system target:

Macro 

Notes

_ABIabi=n 

Defined when abi is set to N32 or 64. Its value is the instruction set architecture. For example, _ABIN32=2 is set when -n32 is specified on the f90(1) command line; _ABI64=3 is set when -64 is specified on the f90(1) command line.

For information on the f90(1) command line, see Chapter 2, “Invoking MIPSpro 7 Fortran 90”.

_COMPILER_VERSION 

Defined as the compiler version. For example, for the MIPSpro 7.2.1 release it is set as follows: _COMPILER_VERSION=721.

LANGUAGE_FORTRAN90, _LANGUAGE_FORTRAN90 

__host_mips 

The leading characters in the second form consist of 2 consecutive underscores.

LANGUAGE_FORTRAN, _LANGUAGE_FORTRAN 

MIPSEB, _MIPSEB 

__mips 

Set to the instruction set architecture, either 3 or 4. The leading characters consist of 2 consecutive underscores.

_MIPS_ISA 

Set to the instruction set architecture, either 3 or 4.

_MIPS_SIM 

Set to the instruction set architecture, as follows: _MIPS_SIM=_ABIN32 when -n32 is specified on the f90(1) command line; _MIPS_SIM=_ABI64 when -64 is specified on the f90(1) command line.

For information on the f90(1) command line, see Chapter 2, “Invoking MIPSpro 7 Fortran 90”.

_OPENMP 

__sgi 

The leading characters consist of 2 consecutive underscores.

_SYSTYPE_SVR4 

Command Line Options

Several f90(1) command line options affect source preprocessing. The following list indicates the sections in this manual that describe preprocessing options:

The -D identifier[=value][, identifier[=value]] ..., -F, and -U identifier[, identifier] ... options are ignored unless the Fortran input source file is specified as either file.F or file.F90.