4.6 詳細
4.6.1 マクロ、変数定義のスコープ
定義のスコープはその定義が置かれている行から始まり、現行ファイルの終端まで続き ます(#includeされたファイルからのソース行もすべて含みます)。しかし次のものに対しては影響しません:
- FortranのINCLUDE行によって取り込まれたファイル
- fpp及びFortranコメント
- IMPLICITの一文字指定
- FORMAT文
- 数値、文字定数
マクロの影響範囲については#undef指示文によって制限を加えることができます。
4.6.2 マクロ定義の終端
マクロ定義の長さは任意ですが論理的な行で言うと1行に限られます。 これらは複数の物理的な行に分かれていても構いませんが、その際、最後の行以外には 継続行があることを示す‘\’(バックスラッシュ)を配置します。 バックスラッシュとニューラインの記号は置換テキストの対象となりません。 バックスラッシュを置かずにニューラインが現れた場合にはマクロ定義は終結したもの とみなされます。次はマクロ定義を複数行に分けた例です:
#define long_macro_name(x,\ y) x*y
4.6.3 関数形式マクロ定義
マクロコールの引数の数は対応するマクロ定義内の引数の数に等しくなくてはなりませ ん。 引数の数が誤って使用された場合にはエラーとなります。4.6.4 マクロ定義のキャンセル
#undef nameこの指示文の後では‘name’はfppによってマクロ名や変数名とは解釈され なくなります。 ‘name’がマクロ名でなかった場合にはこの指示文は何の効果も持ちません。
4.6.5 条件付きソースコード選択
#if conditionCondition は以下に規定する定数式です。 対応する最初の#elif, #else、または#endif指示文に至る後続 行は、condition が真である場合に限り出力中に現れます。
#elif指示文に続く行は次の場合に限り出力中に現れます。
- 対応する#if指示文の条件が偽であり、
- 対応するそれ以前の#elif指示文の条件がすべて偽であり、かつ
- この#elif指示文の条件が真である。
条件が真の場合、後続の対応する#elif, #else指示文は対応する #endifに至るまですべて無視されます。
#else指示文に続く行は、該当条件文中におけるそれ以前の条件がすべて偽の 場合に限り出力中に現れます。
定数式中でマクロ関数‘defined’を使用することができます。それは引数が 定義されたマクロ名であった場合に限り真となります。
以下の演算が許されます。
- C言語演算: <, >, ==, !=, >=, <=, +, -, /, *, %, <<, >>, &, ~, |, !, &&, ||. これらはcppとの互換性のため、C言語セマンティクスに従って解釈されます。
- Fortran言語演算: .AND., .OR., .NEQV., .XOR., .EQV., .NOT., .GT., .LT., .LE., .GE., .NE., .EQ., **.
- Fortran論理定数: .TRUE., .FALSE..
- #ifdef name
- 指定された名前が#define指示文、または-D オプションに よって定義され、かつ#undef指示文の介在がない場合に限り、対応する #else, #elif、または#endifまでの後続行が出力中に現れま す。 指示文中、名前より後に追加のトークンを記述することはできません。
- #ifndef name
- 指定された名前が定義されていないか、あるいはその定義が#undef指示文に よって除去された場合に限り、対応する#else, #elif、または #endifまでの後続行が出力中に現れます。 指示文中、名前より後に追加のトークンを記述することはできません。
- #elif constant-expression
- #if, #ifdef、または#ifndef指示文と対応する#else または#endif指示文の間に任意の数の#elif指示文を配置することが できます。
- #else
- これは条件指示文の意味を反転させます。 先行する条件文が行を含めるべきことを示している場合、#elseと対応す る#endifの間にある行は無視されます。 先行する条件文が行を無視すべきことを示している場合、後続の行が出力中に含 められます。
- #endif
- 条件指示文#if, #ifdef、または#ifndefのいずれかで開始さ れた行選択を終了させます。それぞれの条件指示文には対応する#endifがな くてはなりません。
4.6.6 外部ファイルの取込み
ファイルは次のようにサーチされます。#include "filename"の場合:
- 処理中のファイルが見出されたディレクトリ
- -I option によって指定されたディレクトリ
- デフォルトディレクトリ
- -I option によって指定されたディレクトリ
- デフォルトディレクトリ
4.6.7 コメント
Fppに対しては次の2種類のコメントが使用できます:- Fortran言語のコメント。 第1桁に‘C’, ‘c’, ‘*’, ‘d’, ‘D’のいずれかの文字を含むソース行はコメント 行とみなされます。 これらの行中ではマクロ展開は行われません。 ‘!’文字の場合は単行のコメント行として解釈されます。 ただし#ifまたは#elif指示文中の定数式中で使用された場合を除きま す。
- 文字列‘/*’と‘*/’で囲まれたFppコメント。 これらは出力の対象から除外されます。 Fppコメントはネスト化できるので、それぞれの開始シーケンス‘/*’ に対しては対応する終了シーケンス‘*/’が存在しなくてはなりません。 Fppコメントはソースコード上の多くの部分をコンパイル対象からはずす際に便利で す。 “#if 0 ... #endif”を使っても同じ効果が得られます。
4.6.8 マクロ関数
マクロ関数defined(name) または defined name
はname がマクロとして定義されていれば.TRUE.に、そうでない場合に は.FALSE.に展開されます。
4.6.9 マクロ式
マクロ展開の過程で行の桁幅が72桁(固定形式の場合)、あるいは132桁(自由形式 の場合)を越えた場合、適切な継続行がfppによって挿入されます。固定形式においてはラベル部分(1-5桁)中でのマクロ展開に制限があります:
- (引数を含む)マクロコールは5桁目を越えることはできません。
- 名前がFortranのコメント文字のいずれかで始まるマクロコールはコメントとして 扱われます。
- マクロ展開の結果、5桁目を越える文字列が生成されることがあります。その場合 には警告メッセージが発行されます。
#define call p(x) call f(x) call p(0)
‘call p’というトークンシーケンスをどう解釈すべきか、fppには判断が 付きません。マクロ名とも考えられるからです。 現状の実装は次のようになっています:
- より長い識別子(上の例ではcallp)が選択されます。
- この識別子より最長のマクロ名、またはキーワードが抽出されます。
- マクロ名が抽出された場合にはマクロ展開が実行されます。その名前が あるキーワードで始まる場合には、fppは適切な警告メッセージを 出力します。
- 識別子の残りの部分は一つの識別子とみなされます。
warning: possibly incorrect substitution of macro callp
このような事態は固定形式のソースコードをプリプロセスする際で、なおかつ 空白文字がトークンの区切りとして解釈されないときにのみ起るという点に注 意してください。 なお、マクロ名がキーワードの先頭部分と一致する場合であっても:
#define INT INTEGER*8 INTEGER kのような場合には上記アルゴリズムにより、INTEGERキーワードがINTというマ クロ名より先に見つかることになります。従ってこのようなマクロ定義をプリ プロセスする場合には警告メッセージは発行されません。