fpp [ options ] [ input-file [ output-file ] ]
fpp は、FORTRAN 77 と Fortran 95 のプリプロセッサ (前処理系) です。fpp には、引数として 2 つのファイル名を必要に応じて指定することができます。input-file と output-file は、それぞれプリプロセッサが読み取る入力ファイルと書き込む出力ファイルです。デフォルトでは標準入力と標準出力が使用されます。Oracle Solaris Studio Fortran コンパイラを使用する場合は、cpp プリプロセッサの代わりに fpp を使用できます。
デフォルトでは、C 形式のコメントが認識されます。これを無効にするには、-c_com=no を指定します
プリプロセッサ変数である name の値を 1 として定義します。これは、fpp コマンド行に -Dname=1 オプションを指定した場合と同じです。または、
#define name 1
の行が fpp の処理するソースファイル内にある場合と同じです。
#define 指令と同様に name を定義します。これは、
#define name def
の行が fpp の処理するソースファイル内にある場合と同じです。-D オプションは -U オプションよりも優先順位が低くなります。つまり、-U オプションと -D オプションの両方で同じ名前を使用した場合は、オプションの順序に関係なくその名前は未定義となります。
入力ソースを固定書式として解釈します。
入力ソースを自由書式として解釈します。
名前が / で始まっていない #include ファイルの検索パスに directory を挿入します。directory は、「インクルード」ディレクトリの標準リストの先頭に挿入されます。したがって、名前が二重引用符 (") で囲まれている #include ファイルは、まずその #include 行があるファイルと同じディレクトリで検索され、次に -I オプションで指定されたディレクトリの中で検索され、最後に標準リストのディレクトリで検索されます。名前が山括弧 (<>) で囲まれている #include ファイルの場合、その #include 行があるファイルと同じディレクトリの検索は行われません。
メイクファイル依存関係のリストを生成して、標準出力に書き込みます。このリストは、入力ファイルから生成されるオブジェクトファイルが、入力ファイルだけでなく、参照されるインクルードファイルにも依存することを示します。
デフォルトでは、どこにあるマクロでも展開されます。コメント内のマクロ展開を抑止するには、-macro=no_com を指定します。すべてのマクロ展開を抑止するには、-macro=no を指定します。
行番号を付ける指令を出力ファイルに書き込みません。これは次のような形式の指令です。
#line-number file-name
name の初期定義をすべて削除します。ここで、name は特定のプリプロセッサによって事前定義された fpp 変数です。以下に、システムのアーキテクチャーに応じて事前定義されているシンボルリストの一部を示します。
Operating System: unix, __unix, and__SVR4 Hardware: sun, __sun, sparc, and__sparc
事前定義されているすべてのシンボルの初期定義を削除します。
fpp からの警告を標準エラーに出力しません。
大文字を小文字に変換します。ただし、文字列定数は変換しません。デフォルトでは、大文字から小文字への変換は行いません。
固定書式ソースファイル (下記を参照) の場合、fpp はシンボル「 」(スペース) に意味はないと解釈します。この書式のデフォルトでは、「スペース」シンボルはトークンの区切り文字です。
ファイルの検索時に、指定された directory を標準ディレクトリのリストの代わりに使用します。
fpp は、いくつかの f95 コンパイラオプションも認識します (f95(1) を参照)。
拡張されたソース行を受け付けます (最高 132 文字)。
警告を標準エラーに出力しません。
fpp は、固定書式と自由書式の両方のソースファイルに対して機能します。デフォルトでは、「.F」という拡張子が付いたファイルは固定書式であると解釈され、「.F90」および「.F95」という拡張子 (およびその他すべての拡張子) が付いたファイルは自由書式であると解釈されます。「-fixed」オプションを指定すると Fortran 95 で固定書式を使用できます。fpp は、固定モードの場合はタブ書式のソース行を認識します。
ソースファイルには fpp トークンを含めることができます。fpp トークンは Fortran のトークンと類似しています。これらは次のとおりです。
fpp 指令の名前。
シンボル名 (Fortran のキーワードなど)。fpp では、Fortran で使用可能なすべてのシンボルを名前の中で使用できます。
定数。整数、実数、倍精度、4 倍精度、2 進数、8 進数、16 進数 (代替表記を含む)、文字、およびホレリス。
コメント。Fortran コメントと fpp コメントがあります。
その他。特殊文字、スペース、タブ、復帰改行など。
出力は、変更された入力ファイルのコピーからなり、次の形式の行が追加されています。
#line_number file_name
これは、これに続く出力行に対応する、元のソース行番号とファイル名を示します。「-P」オプション (上記を参照) を使用すれば、この行の生成は抑止することができます。
fpp 指令の構文と意味は cpp 指令と同じです (cpp(1) を参照)。
すべての fpp 指令行は、ハッシュ記号 (#) で始まります。適切なインデントを行うために、最初の「#」のあとに空白 (スペースまたはタブ文字) を入れることができます。指令は次のグループに分類できます。
マクロ定義
条件付きソースコード選択
外部ファイルの取り込み
行制御
#define 指令を使用すると、単純な文字列変数と複雑なマクロの両方を定義することができます。
#define name token-string
これは fpp 変数の定義です。ソース行で定義のあとにある「name」は、「token-string」に置き換えられます。
#define name(argument [, argument] ... ) token-string
これは関数形式のマクロの定義です。マクロ名「name」のあとにコンマで区切った引数リストを括弧で囲んで続けた記述が現れると、このマクロ定義から生成されるトークン文字列で置き換えられます。マクロ定義の引数リストに指定された引数識別子は、対応するマクロ実引数を表すトークンの並びで置き換えられます。
マクロ置換演算子 # と ## のオペランド以外のマクロ引数は、置換トークンリストでの置換前に、再帰的に展開されます。
文字列リテラルへの引数置換を許可するには、# マクロ置換演算子を使用します。
#define a(x) #x ... a(actual argument)
次のものを生成します。
'actual argument'
(1 つまたは両方が引数である) 2 つのトークンをマクロ定義で結合するには、## マクロ置換演算子を使用します。
#define cat(x,y) x##y x##b a##y #define ab ok ... cat(a,b)
次のものを生成します。
ok ok ok
これらの定義では、マクロ名と「(」記号の間に空白を入れることは禁止されています。マクロ名のあとに空白があると、その指令はマクロ定義ではなく fpp 変数定義であると解釈され、「(」記号で始まる行の残りの部分がトークン文字列であると解釈されてしまうからです。
#undef name
「name」の定義 (「D」オプション、#define 指令、またはデフォルトで生成された定義) をすべて削除します。指令行の name のあとには何もトークンを追加してはいけません。
ファイルを取り込む (インクルードする) 形式は 2 つあります。
#include "filename" #include <filename>
この位置にfilenameの内容を読み込みます。ファイルから読み込まれる行は、fpp によって、現在のファイルの一部であるかのように処理されます。
<filename> という表記を使用すると、filename は標準の「インクルード」ディレクトリの中でのみ検索されます。詳細は、上記の「I」および「Y」オプションを参照してください。指令行の最後の「"」または「>」のあとには何もトークンを追加してはいけません。
#line-number "filename" または #line line-number "filename"
次のコンパイラパスのために行制御情報を生成します。整数定数は次の行の行番号として解釈され、filename はその行が取り出されたファイルの名前として解釈されます。「filename」が指定されていない場合、現在のファイル名は変更されません。
ソーステキストの条件付き選択には、次の 2 つの形式があります。
1) #if condition_1 block_1 #elif condition_2 block_2 #else block_n #endif 2) #ifdef name block_1 #elif condition block_2 #else block_n #endif or #ifndef name block_1 #elif condition block_2 #else block_n #endif
else と elif の部分の指定はオプションです。elif の部分は複数指定することができます。条件は、fpp 定数、マクロ、および組み込み関数から構成される式です。条件式は cpp の式と同様であり、任意の cpp 演算子とオペランドを含むことができますが、C の long 型、8 進、および 16 進の定数は使用できません。そのほか、fpp は Fortran の論理演算子 .NOT. .AND. .OR. .EQV. .NEQV. .GT. .LT. .LE. .GE. などと論理定数 .TRUE. .FALSE. を受け付けて評価します。
定義のスコープは、その定義の行から始まり、現在のファイルの末尾までのすべてのソース行 (およびインクルードされたファイルから取り込まれたソース行) に及びます。
fpp 定義によって影響を受けるスコープには次の例外があります。
Fortran の INCLUDE 文で取り込まれたファイル
fpp と Fortran のコメント
IMPLICIT 文の 1 文字指定
FORMAT 文の書式指定
数値定数、型のない定数、および文字定数
マクロの影響のスコープは #undef 指令を使用することで制限できます。
マクロ定義の長さは任意であり、「復帰改行」記号が現れるまで継続します。マクロは複数の行にわたって定義できます。マクロを次の行に継続させるには「\」を挿入します。したがって、マクロ継続記号なしで「復帰改行」が現れると、マクロ定義の終わりになります。
例: #define long_macro_name(x, y) x*y
固定形式の Fortran 77 ソースファイルでは、マクロの展開として、複数の行または文を生成する必要がある場合があります。別の行に生成する文を区切るには、次のように「;」を使用します。
#define init_i_j(x,y) i=x; j=y ... init_i_j(1,2)
次のものを生成します。
i=1 #2 j=2
マクロ呼び出しの引数の数は、対応するマクロ定義の引数の数と同じでなければなりません。そうでない場合はエラーが通知されます。
#undef name
この指令のあと、「name」は fpp によってマクロ名または変数名として解釈されなくなります。この名前が前にマクロ名として定義されていない場合は、この指令を指定しても何も効果はありません。
定数式
対応する #else、#elif、または #endif 指令までの後続行は、constant-expression が真の値になる場合にのみ出力されます。
#elif 指令に続く行は、次の条件がすべて当てはまる場合にのみ出力されます。
先行する #if 指令で constant-expression が .FALSE. と評価された、または、先行する #ifdef 指令で name が定義されていない、または、先行する #ifndef 指令で name が定義されていた。
それまでの間にあるすべての #elif 指令で constant-expression が .FALSE. と評価された。
現在の constant-expression が .TRUE. と評価される。
定数式の評価が .TRUE. になる場合、後続の #elif および #else 指令は対応する #endif まで無視されます。#if 指令で使用できる定数式はすべて、#elif 指令でも使用できます。
組み込み関数「defined」を定数式の中でも使用することができます。
使用可能な項目は、次のとおりです。
C 言語の演算子: <、>、==、!=、>=、<=、+、-、/、*、%、<<、>>、&、~、|、&&、|| fpp はこれらを C 言語の意味論に従って解釈します (この機能は、cpp を使用する古い Fortran プログラムとの互換性を維持するために提供されています)
Fortran 言語の演算子: .AND.、.OR.、.NEQV.、.XOR.、.EQV.、.NOT.、.GT.、.LT.、.LE.、.GE.、.NE.、.EQ.、** (累乗)。
Fortran の論理定数: .TRUE.、.FALSE.
定数式の中で使用できるのは、これらの項目と、整数定数、および名前だけです。名前が「D」オプション、#define 指令、またはデフォルトによって定義されていない場合、その名前の値は 0 になります。C 演算子「!=」(等しくない) は #if および #elif 指令の中では使用できますが、#define 指令の中では使用できません。#define 指令では記号「!」が Fortran のコメント記号であると見なされるからです。
対応する #else、#elif、または #endif 指令までの後続行が出力されるのは、name が #define 指令または「D」オプションによって定義されており、かつ、それまでの間に #undef 指令が存在しない場合だけです。指令行の name のあとには何もトークンを追加してはいけません。
対応する #else、#elif、または #endif 指令までの後続行が出力されるのは、name が定義されていない場合か、またはその定義が #undef 指令によって削除されている場合だけです。指令行の name のあとには何もトークンを追加してはいけません。
#if、#ifdef、または #ifndef 指令と、対応する #else または #endif 指令の間には、任意の数の #elif 指令を置くことができます。
これは、条件指令の意味を反転します。つまり逆の意味になります。先行する条件指令が、行を含めることを示す場合、#elseと対応する#endifの間の行は無視されます。先行する条件指令が、行を無視することを示す場合、後続の行は出力に含まれます。条件指令と対応する#else指令はネストできます。
#if、#ifdef、または #ifndef のいずれかの条件指令で開始した行セクションを終了します。これらの各指令には対応する #endif が必要です。
cpp の場合と同じです。ファイルは、次のように検索されます。
#include "file_name" の場合:
処理対象のファイルが見つかったディレクトリ内
-I オプションで指定されたディレクトリ内
デフォルトのディレクトリ内。
#include <file_name> の場合:
-I オプションで指定されたディレクトリ内
デフォルトのディレクトリ内。
fpp 指令 (行の先頭が # 記号で始まる) は、ソースコード内の任意の位置に指定できます。特に、Fortran 継続行の前に記述できます。ただし唯一の例外として、継続記号を使用して複数の行に分けられたマクロ呼び出しの中では fpp 指令は禁止されています。
fpp では、2 種類のコメントを使用できます。
Fortran 言語のコメント。「C」、「c」、「*」、「d」、または「D」という記号のいずれかが先頭にあるソース行は、コメント行であると見なされます。このような行の中では、マクロの展開は実行されません。「!」という記号は、行末まで続くコメントの開始であると解釈されます。ただし、この記号が #if および #elif 指令内の定数式の中にある場合だけは例外です (上記を参照)。
「/*」と「*/」という記号で囲まれた fpp コメント。これは出力から除外され、これらの記号の中ではマクロ展開が実行されません。fpp コメントは入れ子にすることができます。記号「/*」ごとに、対応する記号「*/」が必要です。fpp コメントは、ソースの広範囲にわたる部分をコンパイルから除外するのに適しています。Fortran コメント記号では、すべての行をコメントにしなければならないからです。
組み込み関数
defined(name) または defined name
.TRUE. - name がマクロとして定義されている場合。
.FALSE.- name が定義されていない場合。
マクロ展開の際に、行のカラム幅が 72 桁 (固定書式) または 132 桁 (自由書式) を超える場合、fpp は適切な継続行を挿入します。
固定書式の場合、ラベルフィールド (1 桁目から 5 桁目) でのマクロ展開には次の制約があります。
マクロ呼び出し (引数があればそれも含む) は 5 桁目を超えないようにする必要があります。
名前が Fortran のコメント記号で始まるマクロの呼び出しはコメントの一部であると見なされます。
マクロ展開から生成されるテキストが 5 桁目を超えることもあります。その場合は警告が出力されます。
固定書式で「-Xw」オプションが指定されている場合、マクロ呼び出しが文の位置に記述され、マクロ名の先頭部分または全体が Fortran のキーワードと一致していると、解釈が不明確になることがあります。たとえば、次のテキストを考えてみます。
#define callp(x) call f(x) call p(0)
fpp は「call p」というトークンの並びを解釈する方法を明確に決定できません。マクロ名であるとも解釈できます。現在の実装は次のことを行います。
長い方の識別子を選択します (この例では「callp」)。
この識別子から、もっとも長いマクロ名またはキーワードを抽出します。
マクロ名が抽出された場合は、マクロ展開が実行されます。名前が何らかのキーワードで始まる場合、fpp は適切な警告を出力します。
識別子の残りの部分は、その全体が 1 つの識別子であると見なされます。
上の例では、マクロ展開が行われ、次のような警告が出力されることになります。
警告: マクロ callp の誤置換の可能性
なお、このような状況が発生するのは、固定書式のソースコードを前処理する場合に、スペース記号がトークンの区切り文字として解釈されない場合だけです。また、マクロ名がキーワードの先頭部分と一致する、次のような場合を考えてみます。
#define INT INTEGER*8 INTEGER k
この場合、前述のアルゴリズムに従って、INTEGER キーワードがマクロ名 INT よりも先に検出されます。したがって、このようなマクロ定義の前処理で警告が出力されることはありません。
診断メッセージは次の 3 種類です。
警告。ソースコードの前処理は続行され、戻り値は 0 のままです。
エラー。fpp は前処理を続行しますが、リターンコードをゼロ以外の値 (エラーの個数) に設定します。
致命的エラー。fpp は前処理を中止して、ゼロ以外の戻り値を返します。
fpp によって生成されるエラーメッセージは、読めばわかるものです。エラーが発生した行番号とファイル名が、診断と共に出力されます。
cpp(1), f95(1)
fpp のソースコードは NetLib からダウンロードできます。
http://www.netlib.org/fortran/