更新日付: 2004 年 2 月 27 日 |
Sun[tm] Studio 9: Fortran プリプロセッサ fpp Readme |
Fortran のプログラミング環境では、1 つのコードに対する複数バージョンの管理、多様な環境におけるコードの実行を要求される局面は珍しいことではありません。 この問題に対処する場合、プログラマに最も都合のいい方法は、あらゆるバージョンのコードを 1 つのソースファイルにインタリーブして、任意のバージョンを簡単に抽出できるようにすることです。 この方法で、すべてのバージョンに適用する変更を一度に済ませることができます。
この目的で長く利用されてきているのが、ソースコードプリプロセッサです。 ソースコードプリプロセッサを使用すると、ソースコード内に、プリプロセッサの出力に作用する指令文を挿入することができます。
通常は、このような特別な指令は、コンパイラへのコメント行として表されます。 一般に、ソースコードプリプロセッサでは、コンパイラに渡すソース行とスキップする行を条件付きで制御する特殊変数と論理構文をユーザーが定義することができます。 また、プリプロセッサのソース行編集機能では、定義されている文字列変数の値に従ってソースコードを変更する方法を指定することができます。
従来、標準的な C コンパイラに見られたソースコードプリプロセッサ (cpp) は、Fortran プログラマにこのような機能を提供するために利用されてきました。 しかしながら、cpp は、気軽に使うには、C の言語構文とソース行書式にあまりにも密接にかかわりすぎています。 Fortran プリプロセッサ (fpp) は、C のプログラマから UNIX 環境での使用を期待されている Fortran 固有のソースコード機能を提供します。
fpp の機能の一部は、その他のツールでの再利用が可能です。 fpp の実装には、Fortran ソースの構文解析、分析、Fortran 式の評価、Fortran 出力の生成などの機能が必要です。 これらの機能は、他のツールでの Fortran プログラムの開発に必要な高度な環境を実現するために必須の基本要素です。
以下では、fpp の機能を詳しく説明します。 さらに詳しい内容は、fpp(1) のマニュアルページを参照してください。
fpp の入力ソースは、プリプロセッサ文がはさみ込まれた標準的な Fortran です。 プリプロセッサ文は、つねに特殊文字の # で始まります。 この文字は、行の先頭文字位置にのみ指定します。 # の直後には、プリプロセッサコマンドのテキストを続ける必要があります。
プリプロセッサ指令は、Fortran コメント内に挿入できます。 プリプロセッサにより、Fortran コメント内のテキストも変更可能です。
プリプロセッサは、固定および自由の両書式のソースを処理します。 拡張子として、固定書式のソースファイルには .F、自由書式のソースファイルには .F90 が付きます。この固定書式のファイル名規則は、Fortran 77 と Fortran 90 の両方に適用されることに注意してください。 これらの拡張子を持つファイルの前処理がはじめに実行されてから、適切なコンパイラが起動されます。
マクロの展開または文字列の置換によって 1 行のカラム幅が 72 カラム (固定書式) または 132 カラム (自由書式) を超える場合、プリプロセッサは適宜、継続行を生成します。
プリプロセッサ変数は、指令を使用して、文字列値を持つ変数として定義します。 fpp は、 ソースコード内でプリプロセッサ変数が出現するごとに、場所が適切ならばその値に置き換えます。 変数はまた条件指令に指定して、出力に渡すソースコード行を制御できます。
#define name string
この指令は、変数「name」の値を「string」に定義します。 この結果、すべてのトークン「name」(IMPLICIT 文の範囲指定部、FORMAT 文内のテキスト、および文字列リテラル以外) は、「string」にリテラルに置き換えられます。
注: IMPLICIT 文の範囲指定部分、FORMAT 文内のテキストの場合は、そのコンテキストで有効なリテラルと衝突する場合のみマクロ展開が行われません。
「マクロ」のように、引数のインライン置換を行うこともできます。
#define name (arg1 [,arg2]...) string-with-args-inserted
例:
#define SOLARIS_2 .TRUE. #define CONVERT(TO_FARENHEIT) ((TO_FARENHEIT*9)/5)+32
プリプロセッサ変数は、その定義ポイントからコンパイル単位の末尾まで有効です (すなわち、ファイル全体にわたる大域的なスコープです)。
プリプロセッサ変数は、次の文を使用して明示的に定義解除できます。
#undef name
Fortran プリプロセッサに対して、/* と */ で囲んだ、C 形式のコメントを使用できます。
これは、cpp の条件付きコード構文にもとづいています。
#if condition1 block1 [#elif condition2 block2 ] ... [#else blockn ] #endif
または
#ifdef name block #endif #ifndef name block #endif
条件 (condition1、condition2) は、プリプロセッサ変数 (#define 文で指定) を含む fpp の式です。 条件は、括弧で囲んで指定できることに注意してください。 fpp の式は、Fortran の論理定数を評価できる点で cpp の式のスーパーセットです。 そのため、fpp の式では、.TRUE は有効です。 プリプロセッサはこれらの条件を評価して、真または偽の結果を取得します。 式は浮動小数点値の評価も、組み込み関数のインクルードもできません。
例 :
#define SOLARIS_2 .TRUE. #if (SOLARIS_2) CALL solaris_2 (X,Y,Z) #else CALL solaris_1 (X,Y,Z) #endif
ファイルにプリプロセッサ変数をまとめると、便利なことがあります。 これは、次の文を使用して行うことができます。
#include filename
#include を入れ子にすることもできます。 #include 文を継続行に指定することはできません (つまり、インクルードされるファイルの最初の文を継続行に指定することはできません)。
defined(name) は、名前の定義状態を提供します。 name が定義されているかどうかで、TRUE または FALSE を返します。 通常、defined(name) は #if 文内で使用します。
#if defined(BIG_MODEL)
通常、fpp は Fortran コンパイラドライバから呼び出されます。 また、スタンドアロンで呼び出すこともできます。 以下に、fpp に使用できるオプションの一部を示します。
-Dname
name を 1 と定義します。これは、fpp が処理しているソースファイルに #define name1 の行を記述するのと同じことです。
-Dname=def
これは、fpp が処理しているソースファイルに #define name def の行を記述するのと同じことです。
-Idirectory
名前がスラッシュ (/) 以外の文字で始まる #include ファイルの検索パスに「directory」を挿入します。 「directory」は、標準の「include」ディレクトリリストの先頭に挿入されます。 このため、名前が二重引用符 (") で囲まれた #include ファイルの検索順序は、最初が #include 行を含むファイルが存在するディレクトリ、2 番目が -I オプションで指定されたディレクトリ、最後が標準リストのディレクトリの順になります。
-Uname
「name」の初期定義を削除します。「name」は、プリプロセッサによって事前定義されている名前です。
-Ydirectory
#include ファイルを探すときに標準のディレクトリリストではなく、「directory」を使用します。
fpp の使用に関する詳しい内容は、fpp(1) のマニュアルページを参照してください。fpp ソースコードは NetLib、http://www.netlib.org/fortran からダウンロードできます。
Copyright (C) 2004 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.