![]() | デバイス操作 | ライブラリルーチン | ![]() |
この章では、Server Express の拡張機能の 1 つである統合プリプロセッサインターフェイスについて説明します。この内容は、プリプロセッサを初めて作成するときや、他の環境からプリプロセッサを移植する場合に役立ちます。
言語プリプロセッサはプリコンパイラとも呼ばれ、標準以外の規格に基づいて記述された COBOL コードや、そのような記述を含む COBOL コードを、コンパイラで処理できる形式に変換するために使用されます。
開発環境に統合されていない独立型のプリプロセッサは、入力されたソースコードを読み取って解析し、修正したソースコードを出力します。こうして出力されたコードが、COBOL コンパイラの入力になります。このような独立型プリプロセッサには、次の欠点があります。
これらの欠点は生産性を低下させ、開発サイクルが大幅に長期化する原因になりかねません。
統合プリプロセッサインターフェイスでは、オリジナルと修正後のソースコードを関連付けることによって、これらの問題が克服されます。独立型プリプロセッサと同様、コンパイラはプリプロセッサで修正されたコードを処理しますが、表示されるのは処理前のオリジナルコードのみです。統合プリプロセッサインターフェイスではプリプロセッサとコンパイラが緊密に連携して動作するため、プリプロセッサの存在を特に意識することもありません。
統合プリプロセッサインターフェイスを使用する場合も、プリプロセッサは独立型と同様にソースファイルを読み取り、修正したソースデータをコンパイラに渡します。そのため、プリプロセッサとコンパイラ間のインターフェイスは完全に汎用的なものになります。ただし、このアプローチには、プリプロセッサ自体が COBOL のデータ構造に対応しなければならないという問題があります。COBOL のデータ構造とは、たとえばコピーファイルの継続と展開、REPLACE と REPLACING の効果などです。後者の 2 つには CP プリプロセッサを使えば対応できますが、この方法は COPY 文が通常の COBOL 構文規則に従うことが前提になります (CP プリプロセッサについては後述する説明を参照)。一方、コンパイラ側でソースファイルを読み取り、トークン単位でプリプロセッサに渡す方法もありますが、トークンの形式や COPY 文 (または同等の文) の構文を一定のルールに従わせる必要があります。
実際にコンパイルされるコードはオリジナルのソースコードとは大幅に異なる場合があるため、次のような影響が生じる可能性があります。
プリプロセッサは言うまでもなく、指令の設定を切り替えるための行を生成できますが、プリプロセッサで選択された言語の予約語とデータ項目の名前が重複する場合など、この機能自体が問題になることもあります。
プリプロセッサはコンパイラから起動します。具体的には、PREPROCESS コンパイラ指令を使用します。
プリプロセッサを起動するコマンドを次に示します。
cob filename -C" [directives] preprocess(preproc) [preproc-params]"
各パラメータについて次に説明します。
filename |
ソースファイル名 |
directives |
その他の必要なコンパイラ指令 |
preproc |
プリプロセッサ名 |
preproc-params
|
プリプロセッサのパラメータ (省略可。詳細については『プリプロセッサパラメータ』を参照) |
PREPROCESS からコマンド行末尾までに指定する各指令と ENDP 指令は、チェックなしでプリプロセッサに渡されます。
他のコンパイラ指令と同様、PREPROCESS も指令ファイル内で指定したり、$SET 文を使ってソースコード内に記述することが可能です。使用する方法にかかわらず、指定箇所は 1 箇所のみです。$SET 文を使用する場合は、ソースファイルの先頭行に指定する必要があります。
複数のプリプロセッサを起動するには、PREPROCESS 指令を 1 つプリプロセッサに渡し、そのプリプロセッサに次のプリプロセッサを呼び出させます。2 つめのプリプロセッサの呼び出しは、最初に呼び出されたプリプロセッサの役割であり、3 つめ以降のプリプロセッサも同様に直前のプリプロセッサから呼び出されます。この方法に対応していないプリプロセッサは、一連の呼び出しの最後のプリプロセッサのみが使用されます。詳細については、後述の『複数のプリプロセッサ』を参照してください。
複数のプリプロセッサを呼び出すコマンド行を次に示します。
cob filename -C "[directives] preprocess(preproc1) [preproc1-params] [preprocess(preproc2) [preproc2-params]] ..."
各パラメータの内容は次のとおりです。
filename |
ソースファイル名 |
directives |
その他の必要なコンパイラ指令 |
preproc1 |
コンパイラから呼び出すプリプロセッサの名前 |
preproc1-params
|
preproc1 用のプリプロセッサパラメータ (省略可。詳細については『プリプロセッサパラメータ』を参照) |
preproc2 |
preproc1 から呼び出されるプリプロセッサの名前 |
preproc2-params |
preproc2 用のプリプロセッサパラメータ (省略可。詳細については『プリプロセッサパラメータ』を参照) |
プリプロセッサのデバッグには、CBL_DEBUGBREAK ルーチンを使用する必要があります。このルーチンをプリプロセッサのソースコードに埋め込み、コードをコンパイルします。
cob preproc
プリプロセッサのコンパイル中に CBL_DEBUGBREAK が呼び出されると、その時点で Animator が起動し、コード内の該当箇所からデバッグがスタートします。
プリプロセッサのアニメート処理を行うには、次のコマンドを実行します。
cob filename.cbl -C "[directives] preprocess(preproc) [preproc-params]"
さらに、次のコマンドを実行します。
anim filename
各パラメータの内容は次のとおり。
filename |
ソースコード名 |
directives |
1 つ以上のコンパイラ指令 |
preproc |
プリプロセッサの名前 |
preproc-params |
プリプロセッサのパラメータ (省略可。詳細については『プリプロセッサパラメータ』を参照) |
CBL_DEBUGBREAK ルーチンの詳細については、『デバッギングハンドブック』の『Animator の起動』の章を参照してください。
注: この方法でコンパイラを起動する場合は、生成段階用のコンパイラ指令を使用できません。
ここでは、統合プリプロセッサを作成する方法を取り上げ、プリプロセッサとコンパイラ間の情報のやり取りに使用されるインターフェイスについて説明します。
プリプロセッサは COBOL 以外の言語でも作成できますが、ここでは COBOL での作成を前提として説明します。
統合プリプロセッサインターフェイスの動作は、プリプロセッサによる前処理を編集形態の 1 つと捉えるシンプルな概念に基づきます。プリプロセッサはソースコードの各行を、変更なし、挿入 (プリプロセッサで新たに追加した行)、修正 (オリジナルのソースでコンパイルされない行) のいずれかに分類します。COBOL プログラムのコンパイル時には、コンパイラはソースファイルを直接読み取るかわりにプリプロセッサを呼び出し、前処理済みのコードを行単位で受け取ります。
Animator の動作は、オブジェクトコードとソースコード間の行マッピングに左右されます。上記のように、プリプロセッサによってソースコードの各行が分類されるため、オブジェクトコードがソースコードに一致しない場合でも、両者の行マッピングの有効性は維持されます。
ここでは、コンパイラとプリプロセッサ間のインターフェイスについて説明します。
mode-flag
buffer
response
mode-flag
は制御情報、buffer
はテキスト情報 (ソースの行とファイル名)、response
はバッファ内のソース行の種類を渡すパラメータです。
各パラメータのデータ構造を次に示します。
01 mode-flag pic 9(2) comp-x. 01 buffer pic x(n). 01 response. 03 response-status pic 9(2) comp-x. 03 response-code-1 pic 9(4) comp-x. 03 filler redefines response-code-1. 05 filler pic x. 05 resp-main pic 9(2) comp-x. 03 response-code-2 pic 9(4) comp-x. 03 filler redefines response-code-2. 05 filler pic x. 05 resp-more pic 9(2) comp-x.
注: COMP-X 型の詳細については、『言語リファレンス』を参照してください。
コンパイラがプリプロセッサを最初に呼び出すのは、通常のコンパイルでソースファイルが開かれるタイミングです。この呼び出しでは mode-flag
パラメータが 0 に設定され、buffer
パラメータでソースファイル名が指定されます。コンパイラでソースファイルが見つかった場合は、buffer
の値に完全パスと拡張子も含まれます。ソースファイルが見つからなかった場合は、コマンド行で指定されたソースファイル名がそのまま使用されます。
最初の呼び出しではハンドシェイクプロセスも開始され、コンパイラとプリプロセッサが互いのサポート水準をチェックできるようになります。その結果、プリプロセッサインターフェイスに新しい機能を追加しても、コンパイラとプリプロセッサの両方がサポートしていない限り、その機能が使用されることはありません。コンパイラからプリプロセッサに渡される情報は、プリプロセッサ側で処理できる旨が通知された情報のみです。同様に、プリプロセッサがコンパイラに送信する要求も、コンパイラ側で処理できる旨が通知された要求のみに限定されます。ハンドシェイクプロセスは、それを認識しない旧バージョンのコンパイラやプリプロセッサの動作に影響を与えないように設計されています。
コンパイラはプリプロセッサを呼び出すときに、自身のサポート水準を response-code-2
パラメータでプリプロセッサに通知します。プリプロセッサも同じパラメータを使用して、コンパイラに制御を戻すときに自身のサポート水準をコンパイラに通知します。新しい機能が追加されるとサポート水準も高くなり、各サポート水準にはその下位の全水準の機能が含まれます。サポート水準、
8224 は、パラメータを初期化しない旧バージョンのコンパイラを示します。この水準は「基本レベル」と呼ばれます。同様に、サポート水準を設定しない旧バージョン用のプリプロセッサの場合は、32767
以下が基本レベルになります。
以下では、基本レベルでカバーされない各種の機能について説明します。これらの機能は、「拡張レベル」と総称されます。コンパイラのサポート水準を次にまとめます。
response-code-2
|
機能 |
---|---|
8224 | 基本レベル |
0 | response-code-1 に buffer の長さが格納される。 |
1 | resp-main の値として 14 がサポートされる。 |
2 | コンパイラはプリプロセッサのサポート水準を認識し、プリプロセッサに中止要求を行う。 |
プリプロセッサのサポート水準は次のとおり。
response-code-2 |
機能 |
---|---|
32767 以下 | 基本レベル |
32768 | コンパイラによって中止が要求される場合がある。 |
拡張レベル
コンパイラは buffer
の長さを response-code-1
に格納します。この長さは、プリプロセッサが返すソース行の最大値を示します。response-code-2
の値が 8224 の場合には、プリプロセッサが返すソース行の最大長は 80 バイトになります。
プリプロセッサは、ソースファイルが正常に開いた場合に、 response-status
として 0 を返し、失敗した場合は
255 を返します。
プリプロセッサを起動するオペレーティングシステムのコマンド行には、プリプロセッサに渡す各指令が、空白文字で区切られた形で含まれます。これらの指令は、コンパイラのコマンド行や指令ファイル内、または $SET 文によって指定され、PREPROCESS 指令に続いて指定されます。詳細については、『プリプロセッサの呼び出し』を参照してください。また、オペレーティングシステムのコマンド行の解釈方法については、『言語リファレンス』の『COMMAND-LINE』を参照してください。これらの指令は、コマンド行からプリプロセッサに情報を渡す手段として、プリプロセッサの開発者自身によって定義されます。なお、プリプロセッサに渡される各指令は、必ずしも 1 つの空白文字のみで区切られているとは限りません。コマンド行の構文は PREPROCESS 指令の形式に準じており、先頭の指令を含む各プリプロセッサ指令には、その前に複数の空白文字が位置する可能性があります。
プリプロセッサへの後続の呼び出しでは、末尾行に到達したことがプリプロセッサから通知されるまで、ソースコードの行を 1 行ずつ要求します。
これらの呼び出しでは、コンパイラは mode-flag
を 1、response-status
を 0 に設定します (ただし、後述の『COPY 文の処理』で説明されている場合を除きます)。要求を受け取ったプリプロセッサは、buffer
、resp-main
、および
resp-more
に応答を返します。これらの応答については、次に説明します。プリプロセッサでエラーが検出された場合は、response-status
にゼロ以外の値を設定する必要があります。その他の項目の値を定義する必要はありません。
response-code-1
と response-code-2
の先頭バイトは予備であり、常にゼロに設定する必要があります。そのための方法としては、resp-main
と resp-more
を設定する前に、response-code-1
と response-code-2
をゼロに設定するやり方が最も簡単です。
ソースコードに変更を加える場合は、オリジナルのソースコード行を、プリプロセッサで代替された行より先に返すべきである点に注意してください。さらに、ソース内の複数の行にわたるコードは常に、 1 つのブロックとして扱う必要があります。論理行の一部分のみを変更することはできません。
拡張レベル
mode-flag
の値が 2 の場合は、コンパイラがまもなく終了します。この値を受け取ると、プリプロセッサは一時作業ファイルの削除など、必要なすべての削除処理を実行すべきです。複数のプリプロセッサを使用している場合は、最初のプリプロセッサを中止する前に、次のプリプロセッサにも同じ方法で呼び出しを行う必要があります。『複数のプリプロセッサ』を参照してください。
プリプロセッサへの 2 番め以降の呼び出しは、ソース行やその他の要求 (エラーカウントの増加など)、または指令設定を返します。各ソース行は、変更なし、旧コード (コメントとして処理)、追加、または COPY 文のいずれかに分類されています。
resp-main
は返される値の種類を示します。resp-more
と buffer
の両方、または一方に追加情報が格納される場合もあります。
resp-main
の値とその意味を次に示します。
値
|
意味
|
---|---|
0 | ソースファイルの処理が完了し、入力データが存在しない。buffer と resp-more は使用されない。 |
1 | プリプロセッサによって新たに追加された行 (オリジナルに存在しない行) が buffer に格納されている。オリジナルのソース行の動詞が置き換えられる場合には、その動詞の行中での位置が resp-more に格納されている。コメントは追加行の対象外。 |
2 | コンパイラによって無視されるオリジナルのソース行が buffer に格納されている。resp-more は使用されない。 |
3 | プリプロセッサが展開する COPY 文の開始部分が buffer に、その文の行中での位置が resp-more にそれぞれ格納されている。 |
4 | オリジナルのソースコード内で COPY 文の継続部分を含む行が buffer に格納されている。resp-more は使用されない。 |
5 | プリプロセッサによって挿入された警告メッセージが buffer に格納されている。警告メッセージには注記行と同様、ソース行の標識領域にアスタリスク (*) が付けられている。resp-more は使用されない。 |
6 | 回復不能なエラーが発生した。この結果、コンパイラは終了し、COBOL Editor が起動する。最大 70 文字のメッセージが buffer に格納され、COBOL Editor の最下部に表示される。resp-more は使用されない。 |
7 | エラーが発生した。この結果、コンパイラの内部エラーカウントが 1 つ増加する。エラーのクラスは
resp-more で指定できる (後述の『エラーメッセージの生成』を参照)。buffer
は使用されない。 |
8 | この値は CP プリプロセッサによって生成される。詳細については、『CP プリプロセッサ』を参照。 |
9 | この値は CP プリプロセッサの実行中に使用される。詳細については、『CP プリプロセッサ』を参照。 |
10 | 次の 11 と同じ。 |
11 | プリプロセッサによって新たに追加された行が buffer に格納されている。ただし、プリプロセッサが展開する COPY 文の先頭部分を含む行のみ。この応答コードは、当該行に同じ COPY 文が複数含まれる場合や、オリジナルのコード行が COBOL の COPY 文ではない場合に使用される。resp-more には、対象の COPY 文の行中での位置が格納されている。 |
12 | プリプロセッサによって新たに追加された行が buffer に格納されている。ただし、COPY 文の継続を含む行のみ。resp-more は使用されない。 |
13 | この応答コードを受け取ると、コンパイラは指令設定の情報を返す。指令が buffer に格納される場合もある。resp-more は使用されない。 |
14 | 上記の 10 および 11 に似ているが、オリジナルのソースに -INC または ++INCLUDE が含まれていることを示す (拡張レベルのみ)。 |
32 | オリジナルのソースコード内でプリプロセッサによって修正されなかった行が buffer に格納されている。 |
33 〜 64 | これらの値は CP プリプロセッサによって生成される。詳細については、『CP プリプロセッサ』を参照。 |
128 | コピーファイルの末尾に到達した。buffer は空である。 |
resp-main
の値が 1 の場合には、オリジナルのソースコード内で置き換えられた COBOL 以外の動詞 (非 COBOL 動詞) の位置が、resp-more
の値によって次のように示されます。
位置
|
意味
|
---|---|
0 | 動詞はまったく置き換えられない。 |
nn |
現在の行によって置き換えられている非 COBOL 動詞の 1 字めが位置する列の番号。該当する非
COBOL 動詞を含む行は、resp-main の値として 2 が返されたときにあらかじめマークが付けられています。複数の行にわたる場合は、非
COBOL 動詞が最初の行に位置するものと見なされます。
たとえば、オリジナルのソースコードに次の記述があるとします。 exec abc do something useful end-exec このコードが次の行で置き換えられたとみなします。 call abc_something_useful この場合、 |
プリプロセッサは、ソースコードの処理中にエラーを検出すると、次のいずれかの方法でコンパイラにエラーを通知します。通知されたエラーは、コンパイラで構文エラーとして扱われます。
resp-main
を 5 に設定し、コメント行をバッファに格納する。このコメントはリストファイルに挿入される。resp-main
を 6 に設定する。この結果、コンパイラは終了する。resp-more
の値は、エラーが検出された列の番号を示します。この値は、COBOL Editor 起動時にカーソルの位置決定に使用されます。
エラー検出時にコンパイラの内部エラーカウントを増加させることも可能です。resp-main
を 7 に設定し、増加させるエラーカウントを
resp-more
で指定します。resp-more
に設定できる値は次のとおりです。
値
|
意味
|
---|---|
1 | 回復不能なエラー |
2 | 重大なエラー |
3 | エラー |
4 | 警告 |
5 | 情報 |
6 | フラグ数 |
回復不能なエラーのカウントを増加させると、コンパイラはただちに終了します。この場合、buffer
の値は使用されません。
コンパイラを終了させたり、エラーカウントを増加させる前に、ユーザ側にエラーメッセージを出力する処理を、プリプロセッサで実行する必要があります。このエラーメッセージは、リストファイルに挿入できる情報メッセージとは区別してください。COPY 文に指定した名前が読み取られて格納され、Animator で使用されます。読み取り時に大文字/小文字変換が施される可能性もあるため、名前は引用符で囲んで指定すべきです。一部のオペレーティングシステムでは、大文字と小文字が変換されると Animator がファイルを検出できなくなります。
resp-main
の値が 13 の場合は、buffer
に空白文字または指令名が格納されています。コンパイラは、プリプロセッサを次に呼び出すときに、指定された指令の値を
buffer
パラメータで渡します。コンパイラは値、 13 を受け取ると、設定済みの指令のリストを生成し、その中のいずれかの指令値を次回の呼び出しでプリプロセッサに渡します。それ以降に値、
13 を受け取ると、コンパイラは同じリストから値を返します。13 以外の値を受け取ると指令リストは失われ、それ以降に値、 13 を受け取ったときに再生成されます。リスト内の指令はアルファベット順に並んでおり、すべての指令値が渡されると、以降の呼び出しでは空白文字が渡されます。プリプロセッサから返された
buffer
が空白文字の場合は、コンパイラが最初の (または次の) 指令の値をプリプロセッサに渡します。buffer
に指令名が格納されている場合は、リスト内を検索して該当する指令の値を渡します。この方法で渡される指令は Checker のみです。
プリプロセッサがコピーファイルを処理しない場合は、COPY 文を修正せずにコンパイラに渡すことができます。渡された COPY 文は、コンパイラで展開されます。
この方法で渡すことができるのは、有効な COBOL データ構造のみです。COBOL 以外のデータ構造はコメント化され、有効な COPY 文で置き換えられてコンパイラで展開されます。
いずれの場合も、プリプロセッサ側ではコピーファイルの読み取りや処理は行われません。
コンパイラは COPY 文を、プリプロセッサによる修正の有無にかかわらず展開します。次に示す COPY 文が展開されます。
copy-filename
OF/IN library-name
プリプロセッサがコピーファイルの内容をチェックしない場合は、それ自体でコピーファイルを展開するか、または後述の CP プリプロセッサを使用する必要があります。展開したコピーファイルの内容は、プログラム本体のソースファイル内の行と同様にコンパイラに返されます。ただし、COPY 文には、他の内容とは異なる処理が施されます。
最も単純な場合、つまり COPY 文が 1 つ以上の行に含まれる唯一の文であり、しかも同文で完全にファイルが特定できる (必要な拡張子やパスが指定されている) 場合は、resp-main を 3 に設定して 1 行めがコンパイラに返されます。resp-more には、COPY 文の開始位置の列番号が格納されます。2 行め以降の各行は、resp-main を 4 に設定してコンパイラに渡されます。
COPY 文に指定されているファイル名に拡張子やパスを追加して位置を解決する場合や、対象行に複数の COPY 文が含まれている場合、または COPY
文が COBOL の標準とは異なる場合は、その COPY 文を含むすべての行をコメント化して (resp-main
は 2)、新たに挿入した代替行とともにコンパイラに返す必要があります。プリプロセッサが展開時に挿入する COPY 文は、COBOL 標準の構文規則に従う必要があります。挿入した行のうち、1
行めは resp-main
を 11 または 14、resp-more
を nn
(nn
は COPY 文の開始位置) に設定して返し、2 行め以降の各行は
resp-main
を 12 に設定して返します。
たとえば、ソースに次の行が含まれている場合について考えてみます。
01 ITEM-A. COPY "CPY-FIL.CPY".
この行は挿入される行で置き換えられるため、resp-main
を 2 に設定してコンパイラに渡されます。続く呼び出しで、プリプロセッサは次の行を返します。
01 ITEM-A.
resp-main
の値は、この行が挿入された代替行であることを示すため、1 に設定されます。さらに、続く呼び出しでは、プリプロセッサは次の行を返します。
COPY "COPY-FIL.CPY".
この行は COPY 文のみを含む代替行であるため、resp-main
の値は 11 に設定されます。resp-more
には、オリジナルのソース行での COPY の位置 (20) が設定されます。
コンパイラはプリプロセッサから COPY 文を受け取ると、プリプロセッサによる展開の有無にかかわらず解析を施し、REPLACING が含まれているかどうかをチェックします。REPLACING は、対象のコピーファイル (およびネストに含まれるすべてのコピーファイル) に影響を及ぼします。COPY 文に指定されている名前は読み取られて格納され、Animator で使用されます。読み取り時に大文字/小文字変換が実行される可能性もあるため、名前は引用符で囲んで指定すべきです。一部のオペレーティングシステムでは、大文字と小文字が変換されると Animator がファイルを検出できなくなります。
拡張レベル
オリジナルのソースに含まれる文が COBOL の COPY とは異なる場合 (++INCLUDE や -INC など)は、resp-main
が 14 に設定されます。一部のコンパイラ指令は、$SET 文内で他の COBOL ソースよりも前に指定する必要があります。そのような指令が COPY
に続けて指定されることはありませんが、++INCLUDE の場合はありえます。resp-main
を 14 に設定すると、++INCLUDE
を展開し、同時にそのような指令を続けて指定することが可能です。
プリプロセッサによるコピーファイルの展開が完了すると、resp-main
の値を 128 に設定します。128
以外の値を渡すと、コンパイラはコンパイルを中止します。ソースファイル本体の末尾に到達したときは、resp-main
を 0 に設定する必要があります。
見出し部 (IDENTIFICATION DIVISION) のコメントエントリに含まれる COPY 文は、必ずしも展開されるとは限りません。プリプロセッサからコピーファイルの展開通知 (resp-main
が 3 または 11) を受け取ったコンパイラは、その展開が無効であれば response-status
をゼロ以外に設定してプリプロセッサを呼び出します。この呼び出しを受け取ったプリプロセッサは、そのコピーファイルが空であるかのように、ただちにコピーファイルを無視して resp-main
を 128 に設定し、コピーファイルの末尾を通知する必要があります。
後述の、 CP プリプロセッサでコピーファイルを展開する場合には、プリプロセッサ側での展開は不要です。CP プリプロセッサも、上記と同じ方法で行を生成します。
ソースファイルの修正には、さまざまな COBOL コマンドが使用できます。ただし、次の 2 つのコマンドは、プリプロセッサ使用時にはコンパイラで実行できないため、プリプロセッサ側で制御する必要があります。
CP プリプロセッサは、REPLACE の影響に関する情報を他のプリプロセッサに返します。
1 つのソースプログラムは、複数のプリプロセッサで並行して処理することが可能です。これらのプリプロセッサは階層型に構成されます。つまり、コンパイラが最初のプリプロセッサを呼び出すと、そのプリプロセッサが次のプリプロセッサを呼び出し、さらに呼び出されたプリプロセッサから下位のプリプロセッサが順次呼び出されます。ソースコードを実際に読み取るのは、最後に呼び出された最下位のプリプロセッサです。このプリプロセッサが読み取ったソースが、行単位で上位の各プリプロセッサに順次渡され、最終的にコンパイラに渡されます。ただし、この仕組みを正しく機能させるには、いくつかのルールに従う必要があります。
『プリプロセッサの呼び出し』で説明したように、コンパイラは最初のプリプロセッサを呼び出すときに、コマンド行に指令を書き出します。呼び出されたプリプロセッサはこのコマンド行を読み取り、PREPROCESS 指令を検出すると、指定されているプリプロセッサを呼び出します。同時に、PREPROCESS に続いて指定されている各パラメータをコマンド行に順次指定し、呼び出したプリプロセッサに渡します。呼び出し側のプリプロセッサでは、この一連の処理を通じてハンドシェイク処理が継続されます。
コンパイラに渡されるプリプロセッサ指令は、ENDP 指令または行の末尾によって終了します。そのため、複数の PREPROCESS 指令を指令ファイル内で指定して渡す場合は、各指令をすべて同じ行に記述する必要があります。
プリプロセッサ間のインターフェイスは、プリプロセッサとコンパイラ間のインターフェイスと同様であり、階層的な呼び出しに対応しているプリプロセッサは、対応していないプリプロセッサとも組み合わせて使用できます。階層的な呼び出しに対応していないプリプロセッサは階層の最後に呼び出し、ソースコードを直接読み取らせます。
ほとんどの場合、プリプロセッサは別個の構文の組に従い、有効な COBOL 構文を生成します。そのため、一部のプリプロセッサに特定のソース行を渡す必要が生じることはまずありません。ただし、複数のプリプロセッサを階層的に使用し、各プリプロセッサでそれぞれ異なる言語水準を処理する場合は、ソース行がコンパイラに渡されるまでの間に、異なるプリプロセッサによって数回にわたって編集されます。そのような場合は、オリジナルのソースコードとコンパイラに渡されるコードとの整合性を維持するためにも、応答項目で返される情報を正しく管理する必要があります。さらに、1 つのプリプロセッサが修正したコードが次のプリプロセッサでも正しく修正されるように、プリプロセッサを呼び出す順序にも注意を払うべきです。
プリプロセッサがソースコードに加えた変更によって、使用している COBOL の方言やデータ名との競合が生じる可能性もあります。ここでは、そのような問題を回避するための注意点を説明します。
ソースコードに使用されている方言が、プリプロセッサに必要な機能をサポートしていない場合には、2 つの問題に対処する必要があります。1 つは、その方言に準拠しないコードがフラグ付けされる点、もう 1 つは必要な予約語が辞書に格納されていない可能性がある点です。
フラグ付けに伴う問題を避けるため、コンパイラはプリプロセッサが挿入した行にはフラグ付けを行いません。
必要なすべての予約語を使用可能にする場合は、プリプロセッサで (ANS85 指令などの) 設定行を生成する方法を使用できます。ただし、この方法では一部の文の動作が異なったり、有効なデータ名が予約語と認識されて、拒否されるという副作用が生じる可能性があります。
より確実な手段としては、実際に必要な予約語を選別し、それらの予約語のみを ADDRSV 指令で追加する方法があります。たとえば、FUNCTION という予約語が必要であれば、ADDRSV(FUNCTION) でその予約語のみを追加します。ただし、この方法でも FUNCTION をデータ名として使用しているコードでは問題が生じます。
最も確実なのは、ADDSYN 指令を使用する方法です。ADDSYN を使用すると、コード内で使用される可能性の低い単語を、本来の予約語の同義語として定義できます。たとえば、ADDSYN "FUNCTION" = "PREPGEN--FUNCTION" と定義すれば、それ以降は FUNCTION のかわりに PREPGEN--FUNCTION を使ってコードを生成できます。
注: 複数のプリプロセッサで同じソースを処理する場合には、ADDSYN で定義した同義語が、後続のプリプロセッサで正しく認識されない可能性があります。
専用のデータを生成するプリプロセッサでは、そのデータの名前として、ソースコードで使用される可能性の低い名前を選択すべきです。たとえば、前例の PREPGEN--USERID のような名前が適切です。それに対して、USERID など一般的な名前を使用すると、問題の原因になる可能性があります。
CP プリプロセッサは階層的な呼び出しに対応しており、コピーファイルを含むソースファイルの読み取りと展開に加え、REPLACE と REPLACING の影響に関する追加情報を階層の上位プリプロセッサに返す機能を持っています。そのため、CP プリプロセッサを利用すると、REPLACE や REPLACING に関する情報を取得する複雑なルーチンを、他のプリプロセッサに実装する必要がなくなります。
CP プリプロセッサには、次の制約があります。
CP プリプロセッサは COPY 文を検出すると、前述した方法でソース行にマーク付けを施し、該当するコピーファイルを読み取ります。コピーファイルの検索には、コンパイラの場合と同じパスとファイル名が使用されます。
コピーファイルが見つからないと、CP プリプロセッサは該当する COPY 文をコメント化し、適切なエラーメッセージを生成します。COPY 文の解析でエラーを検出しても、CP プリプロセッサはそれを無視してエラー位置からトークンの解析を継続します。他のプリプロセッサは、修正されていない COPY 文を受け取ると、CP プリプロセッサが処理できなかった部分と見なして変更を加えません。その結果、コンパイラでエラーメッセージが生成されます。
CP プリプロセッサは、他のプリプロセッサでもコンパイラと同様、REPLACE と REPLACING の影響に従ってソースコードを解析できるようにするため、次に説明する追加行を返します。ただし、その場合でもコンパイラは、後述の例外を除けば REPLACING を独自に実行できます。なお、追加行は情報提供のみを目的として渡されます。
CP プリプロセッサは修正すべき行を検出すると、resp-main
の値に 32 を加えて返します。この値で識別される 1 つ以上の行の直後には、resp-main
を 8 に設定された行が 1 つ以上続きます。この後続行には、先行する行に加えるべき修正内容に関する情報が含まれています。これらの行は情報提供のみを目的としており、階層内の上位プリプロセッサに順次渡され、最終的にコンパイラに渡されます。コンパイラは、resp-main
の値が 33 〜 64 の行については resp-main
の値から 32 を差し引き、resp-main
の値が 8 の行は無視します。
これらの行を渡されたプリプロセッサでは、必要に応じて対象行に修正を加えることができます。修正では通常どおり、新しい行を追加します。ただし、修正を加えた場合は、新しい行の
resp-main
を 1 ではなく 9 に設定し、その行に対する REPLACE や REPLACING の検査が不要であることをコンパイラに通知する必要があります。
CP プリプロセッサには、さまざまな指令を使用できます。これらの指令は通常の名前のほか短縮名でも指定できるため、コマンド行を短縮するうえで役立ちます。CP プリプロセッサは、コマンド行で指定された各指令を通常どおりの方法でチェックした後、さらに CPDIR 環境変数に指定されている指令もチェックします。
トレースファイルの作成を指定します。使用するファイルの名前も指定できます。ファイル名を省略すると、トレースファイルが progname.cpt
という名前で作成されます (progname
は対応するソースファイルの基本名)。
>>--.---TRACE----.-"filename"--.--.-->< | +-------------+ | +--NO--TRACE------------------+
NOTRACE
指令の受け入れを画面表示するように指定します。
>>-----.----.----CONFIRM--->< +-NO-+
NOCONFIRM
他のプリプロセッサを呼び出します (現在のプリプロセッサへのソース入力が、ソースファイル自体ではなく、他のプリプロセッサから渡されるように指定します)。
>>--.--PREPROCESS(prepnam)-.----------------.--.-->< | +-DIRECTIVE-NAME-+ | +-NO-PREPROCESS----------------------------+
NOPREPROCESS
指令設定に関する警告を画面表示するように指定します。
>>-----.----.----WARNING--->< +-NO-+
WARNING
EXEC SQL INCLUDE を COPY 文として扱うように指定します。
>>-----.----.----SQL------->< +-NO-+
SQL
すべてのエラーメッセージは次の形式で表示されます。
*CP nnn-X ** description
各要素の内容は次のとおり。
nnn | エラー番号 | ||||||||
X | 重大度。次のいずれかです。
|
descriptions にはエラー番号に対応するメッセージが表示されます。以降の項では、各種のメッセージとその原因、および対処方法について説明します。
初期化エラーで表示される各種のメッセージを次に示します。
ソースの処理では、次のエラーメッセージが生成される可能性があります。
Copyright © 2002 Micro Focus International Limited. All rights reserved.
本書、ならびに使用されている固有の商標と商品名は国際法で保護されています。
![]() | デバイス操作 | ライブラリルーチン | ![]() |