| 複数の言語による開発 | アプリケーション構成システム |
H2cpy ユーティリティは、C 言語のヘッダーファイルを対応する COBOL のコピーファイルに変換するアプリケーションです。コマンド行から単体で直接実行できるほか、ヘッダープリプロセッサから自動的に呼び出すことも可能です。H2cpy は ANSI または ISO 準拠の C 言語ヘッダーファイルに対応しています。
H2cpy は、COBOL の型定義と CALL プロトタイプ構文を使って C のヘッダーファイルを COBOL のコピーファイルに変換します。Server Express は、COBOLプログラム内で使用されているパラメータが C ヘッダーファイル内の定義に合致しているかどうかを、生成されたコピーファイルを基にチェックします。H2cpy を使用すれば、C のヘッダーファイルでインターフェイスが定義されているライブラリルーチン (Motif のルーチンなど) を、より確実かつ簡単に COBOL で利用できます。
H2cpy は C 言語のヘッダーファイルから 2 種類の COBOL ファイルを生成します。1 つは型定義とリテラルを含むコピーファイル (.cpy ファイル)、もう 1 つは外部データの宣言を含む補助的な .ext ファイルです。どちらのファイルも、COPY 文で COBOL プログラムにインクルードできます。H2cpy は C で記述されたインターフェイスを COBOL で利用する場合に不可欠なユーティリティであり、同時に C で開発したプログラムを COBOL に移植する際にも役立ちます。
H2cpy の入力には、ANSI や ISO に準拠するあらゆる C のソースファイルを使用できます。これらの規格で定義されていない記述がソースファイル内で見つかると、H2cpy は失敗するか、または誤った変換を実行します。
H2cpy はコマンド行から直接実行できるほか、PREPROCESS"headers" コンパイラ指令を指定して自動実行させることも可能です。ヘッダープリプロセッサは、COBOL のソースファイルの COPY 文内で .h ファイルを検出すると、それを C のヘッダーファイルとして認識し、H2cpy を呼び出して変換します。この機能は、サイズが比較的小さいヘッダーファイルを使用する場合に特に効果的です。
H2cpy のコマンド行で使用するオプションがほぼ一定であれば、それらのオプションを 1 つのグループにまとめ、名前を付けて登録できます。詳細については、-G オプションの説明を参照してください。
この章で紹介するコード例はいずれも断片的なものであり、H2cpy が生成するコード全体を示しているわけではありません。
COBOL コピーファイルの出力例には、変換前のヘッダーファイルには指定されていないデータ項目も含まれています。これらの項目は、C のデータ型に対応する COBOL の汎用的な型定義です。これらのデータ項目のサイズは、使用している環境によって異なります。詳細については、『コマンド行オプション』の -e オプションに関する説明を参照してください。
77 char pic s9(2) comp-5 is typedef.
77 uns-char pic 9(2) comp-5 is typedef.
77 short pic s9(4) comp-5 is typedef.
77 uns-short pic 9(4) comp-5 is typedef.
77 int pic s9(9) comp-5 is typedef.
77 uns-int pic 9(9) comp-5 is typedef.
77 long pic s9(9) comp-5 is typedef.
77 uns-long pic 9(9) comp-5 is typedef.
77 d-l-float comp-2 is typedef.
77 d-float comp-2 is typedef.
77 float comp-1 is typedef.
77 proc-pointer procedure-pointer is typedef.
77 data-pointer pointer is typedef.
77 void pic 9(2) comp-5 is typedef.
注: 他のヘッダーファイルが先に処理されることを前提としたヘッダーファイルは、単体では C コンパイラで処理できません。同様に、H2cpy ユーティリティで変換できるヘッダーファイルも、単独で完結している、または必要な全ファイルを含むファイルセットであることが条件です。C コンパイラのコマンド行で指定すべきマクロ名や、特定のコンパイラで独自に定義されているマクロは、すべて H2cpy のコマンド行で指定する必要があります。たとえば、Microsoft 社の C コンパイラでは、次のマクロが独自に定義されています。
_CHAR_UNSIGNED
_CPPUNWIND
_DLL
_M_IX86_MSC_VER _MT _WIN32
ANSI C で定義されている次の各マクロは、-D オプションを使ってコマンド行で指定します。
__DATE__
__FILE__
__LINE__
__STDC__
__TIME__
H2cpy を呼び出すコマンド行の構文を次に示します。
h2cpy { [filename] [option] } ...
各パラメータは次のとおり。
filename |
COBOL のコピーファイルに変換する C のヘッダーファイル |
option |
H2cpy のオプション (後述する『コマンド行のオプション』を参照) |
filename と option は必須です。パラメータを指定しないと、使用可能なオプション一覧が表示されます。
コマンド行のオプションは、先頭にハイフン (-) を付けて指定します。大文字と小文字は区別されます。1 文字のオプションは、それぞれを個別に指定するかわりに、1 つのハイフンに続けて指定することもできます。たとえば、-v、-C、-h の 3 つのオプションは、「-v -C -h」と「-vCh」のどちらでも指定できます。オプションを指定する順序には、特に制限はありません。
次に各オプションとその説明を一覧します。大文字のオプション、小文字のオプションの順に、それぞれアルファベット順で一覧しています。オプション文字の前後には、空白文字を入れることもできます。パラメータも省略可能です。
| オプション | 説明 | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| -A | ANSI 規格への準拠を厳密にはチェックしません。
ANSI C や ISO C には、C 言語の初期実装とは異なる部分があります。H2cpy の使用時に発生した問題が、この相違に起因すると思われる場合は、-A オプションを指定します。 |
||||||||||||||||||||||||||||||||||||||||||||
| -C | 生成する COBOL コードに C のコードを埋め込みます。
COBOL コード内の C ソースコード行には、先頭にアスタリスク (*) と空白文字が付加されます。これらの行は COBOL コンパイラでは解釈されません。C のプリプロセッサで処理されたコードが埋め込まれます。 |
||||||||||||||||||||||||||||||||||||||||||||
| -D name[=val] | マクロ名を宣言します。マクロの値 (数値または文字列リテラル) も指定できます。 | ||||||||||||||||||||||||||||||||||||||||||||
| -E | 構造体と共用体をすべて展開します。
構造体や共用体を表す COBOL コードが各メンバーまで完全に明示されるのは、最初の宣言時のみです。それ以降は名前で参照されます。 |
||||||||||||||||||||||||||||||||||||||||||||
| -F name=val | C の関数呼び出し規約 name を、COBOL の CALL プロトタイプで使用される CALL-CONVENTION の値 val に対応付けます。name には次のいずれかの値を指定できます。
これらの値は、それぞれ C 言語の同じ名前のキーワードと対応しています (C のキーワードには、先頭に 1 つ以上の下線が付きます)。ただし、 |
||||||||||||||||||||||||||||||||||||||||||||
-G name |
h2cpy.dir ファイル内の [name] セクションで指定されているオプショングループを指定します。name を省略すると、[default] セクションに指定されているオプショングループが使用されます。-G オプションは、h2cpy.dir ファイル内でセクション名の次の行に記述できますが、指定済みのオプショングループを参照する手段として使用することはできません。
H2cpy はカレントディレクトリ、$COBDIR ディレクトリの順で h2cpy.dir ファイルを検索します。両方のディレクトリで h2cpy.dir ファイルが見つかると、双方の内容が結合されます。どちらのディレクトリでも見つからない場合には、h2cpy.dir ファイルが空の場合と同様、オプショングループは使用されません。name セクションが見つかり、サイレントモードが無効化されている場合は、name とその位置が表示されます (サイレントモードについては、-v オプションを参照してください)。 h2cpy.dir は、1 つ以上のセクションを含むテキストファイルです。セクションヘッダーから次のセクションヘッダー (またはファイルの末尾) が 1 つのセクションです。各セクションには、先頭にグループ名を角かっこ ([]) で囲んだセクションヘッダーを記述し、それ以降の行に 0 個以上のコマンド行オプションを記述します。セクションヘッダーは必ず行の先頭から記述し、空白文字は使用できません。 |
||||||||||||||||||||||||||||||||||||||||||||
-I path |
インクルードファイルの検索パスリストの先頭にパスを追加します。このオプションを使用すれば、検索パスリストの上限までパスのエントリを登録できます。登録可能なエントリ数の上限は 14 です。
検索パスリストには、初期状態で C 標準のヘッダーディレクトリ (/usr/include) が登録されています。 |
||||||||||||||||||||||||||||||||||||||||||||
| -J | 文字型のデフォルトを符号なし (unsigned) に変更します。 | ||||||||||||||||||||||||||||||||||||||||||||
| -K name | name をキーワードとして認識させ、解釈の対象から除外します。このオプションは、-M オプションや -O オプションでカバーされない C コンパイラ用のヘッダーファイルを使用する場合に役立ちます。 | ||||||||||||||||||||||||||||||||||||||||||||
| -M | 通常は認識される Microsoft のキーワードを無効化します。具体的には、次のキーワードが無効化されます。
|
||||||||||||||||||||||||||||||||||||||||||||
| -O | 通常は認識される IBM C (OS/2 用) のキーワードを無効化します。具体的には、次のキーワードが無効化されます。
|
||||||||||||||||||||||||||||||||||||||||||||
-P |
C コードのプリプロセッサ処理のみを実行し、COBOL コピーファイルは生成しません。
-C オプションとほぼ同じですが、このオプションでは COBOL コピーファイルも生成されません。H2cpy による C ソースファイルの前処理が、C コンパイラとは異なると思われる場合に使用できます。 |
||||||||||||||||||||||||||||||||||||||||||||
| -R name | COBOL の予約語を辞書に追加します。
H2cpyには、現時点で確認されているすべての予約語が組み込まれていますが、このオプションを使用すれば、さらに新しい予約語を追加できます。 |
||||||||||||||||||||||||||||||||||||||||||||
| -S | #define マクロ定義用の COBOL コードを別ファイルとして生成します。生成されるファイルには、他の出力ファイルと同じ基本名に拡張子、
.78 を連結した名前が付けられます。 |
||||||||||||||||||||||||||||||||||||||||||||
| -V | 生成するパラメータ数を固定します。 | ||||||||||||||||||||||||||||||||||||||||||||
| -X | 文字列ポインタに対応する COBOL の型を、char* のみから char* と unsigned char* の両方に拡張します。
関数プロトタイプの |
||||||||||||||||||||||||||||||||||||||||||||
| -a type=n | C のデータ型の整列を設定します。type には、int、char、short、long、llong、pointer、float、dfloat、および dlfloat のいずれかを指定します。
C の各データ型にはデフォルトで整列が設定されていますが、このオプションを使用すれば任意のデータ型の整列を変更できます (デフォルトの整列については -e オプションを参照してください)。 |
||||||||||||||||||||||||||||||||||||||||||||
| -c | COBOL の名前をすべて小文字で生成します。
標準では、COBOL の名前は基本的に C の対応する名前に従います。そのため、名前に含まれる各文字の大文字と小文字の用法も、対応する C の名前と同じになります。 |
||||||||||||||||||||||||||||||||||||||||||||
| -e n |
変換後のコードの実行環境 (n) として、lp32、ilp32、llp64、lp64、ilp64 のいずれかを指定します。このオプションを省略すると、H2cpy の実行環境の COBOL システムに最も適した値が設定されます。
これらの環境名を構成する C のデータ型のサイズと整列は、コードの実行環境に左右されます。実行環境は PC (DOS、Windows、または OS/2 V1.x) と、より強力な環境 (UNIX、OS/2 V2.x、または Windows NT) の 2 種類に大別されます。この 2 つの環境は、サポートする C の整数型のサイズから、それぞれ 16 ビット環境および 32 ビット環境と呼ばれ、前者が lp16、後者が ilp32 で表されます (旧製品の lp32 と ilp32 に該当。この 2 つは現在でも認識されます)。UNIX が動作する一部のマシンでサポートされる 64 ビット環境は、その種類に応じて lp64、llp64、または ilp64 で表されます。 C のヘッダーファイルで |
||||||||||||||||||||||||||||||||||||||||||||
| -f | #define で定義した浮動小数点リテラルを COBOL に渡します。
COBOL コンパイラは、浮動小数点リテラルのサイズと形式を検証します。 浮動小数点リテラルを含む定数式が H2cpy によって評価されると、浮動小数点リテラルがゼロとして扱われ、警告が生成されます。 |
||||||||||||||||||||||||||||||||||||||||||||
| -h | #define で定義した 16 進の数値を 10 進数に変換します。
|
||||||||||||||||||||||||||||||||||||||||||||
| -o name | 生成する COBOL ファイルの名前を指定します。
標準では、生成される COBOL コピーファイルには、最初に変換された C ヘッダーファイルの基本名に拡張子 .cpy (外部宣言ファイルの場合は .ext) を連結した名前が付けられます。このオプションを使用すれば、生成される COBOL ファイルの名前を任意に指定できます。なお、外部宣言ファイルには、常にコピーファイルと同じ基本名が使用されます。 |
||||||||||||||||||||||||||||||||||||||||||||
| -p | CALL プロトタイプを生成しません。
H2cpy は通常、C の関数プロトタイプを COBOL の CALL プロトタイプに変換します。COBOL コンパイラは、生成された CALL プロトタイプを使って呼び出しの形式を検証します。ただし、この検証処理は柔軟性の点で十分でない場合があります。 -p オプションを指定すれば、H2cpy による CALL プロトタイプの生成を回避できます。 数値リテラル (78 レベル項目) をパラメータとして渡す呼び出しには注意してください。COBOL コンパイラは通常、この項目を CALL プロトタイプで指定されたサイズの COMP-5 形式に変換します。CALL プロトタイプが存在しない場合には、デフォルトサイズ (2 バイト) が使用されます。ところが、デフォルトサイズは必ずしも適切であるとは限らず、サイズが不適切であれば実行時に呼び出しが失敗してしまいます。そのような場合には、BY VALUE 指定の SIZE 句で正しいバイト数を指定する必要があります。 |
||||||||||||||||||||||||||||||||||||||||||||
| -r | COBOL の予約語リストを削除します。
生成される COBOL コードをコンパイルしない場合には、このオプションを使用して起動時間を短縮できます。 |
||||||||||||||||||||||||||||||||||||||||||||
| -s type=n | C のデータ型のサイズを指定します。type に指定できる値は -a オプションと同様です。 | ||||||||||||||||||||||||||||||||||||||||||||
| -v | メッセージ表示の表示/非表示を切り替えます。
メッセージの画面表示の表示/非表示を切り替えるオプションです。このオプションを指定すると詳細モードが有効になり、プログラムのバナーやその他のメッセージ (ネストした このオプションを省略した場合 (サイレントモード) は、エラーメッセージのみが表示されます。UNIX では、サイレントモードがデフォルトです。 |
H2cpy は通常、C のヘッダーファイル内で使用されているデータとプロシージャの名前を、そのまま COBOL のコピーファイルでも使用します。ただし、C と COBOL では名前の扱いに相違があるため、C のファイル内の名前が次の条件に該当する場合は、COBOL への変換時に新しい名前が生成されます。
これらの条件の一部は、オプションを設定して調整できます。
該当する名前は、H2cpy によって先頭に番号を付けた名前に変換されます。この番号は、同じ名前の宣言数を示す序数です。
サイズの大きな C ヘッダーファイルを変換したり、生成されたコピーファイルに手を加えたり、さまざまなコマンド行フラグを使い分ける場合は、H2cpy をコマンド行から実行する方が効率的です。
単純な C ヘッダーファイルを変換する場合は、COBOL プログラム内から直接参照する方法が、より効率的です。この方法では、当該プログラムをコンパイルするたびに、ヘッダープリプロセッサによって H2cpy が自動実行されます。
後者の方法で H2cpy を使用するには、変換対象のヘッダーファイル (.h ファイル) を参照する COPY 文を COBOL プログラム内に記述します。COPY 文の記述位置には、特に制約はありません。さらに、PREPROCESS(headers) 指令も使用できます。次に示すように $SET 文を使用すれば容易に指定できます。
$set preprocess(headers)
working-storage section.
01 data-item pic x(9).
copy "cheader.h".
01 cobol-b usage btype.
procedure division.
copy "cheader2.h".
move 6 to c-long of cobol-b
move 7 to c-int of cobol-b
move "Show" to c-char of cobol-b
display "C struct= " c-long " " c-int " "
c-char level-78.
cheader.h の内容は次のとおり。
#define b B
int a;
typedef struct btype {
long c_long;
char c_char[5];
int c_int;
} b;
cheader2.h の内容は次のとおり。
#ifdef b
#define level_78 "C literal"
#else
typedef struct btype {
signed char c_uchar;
float c_float[5];
} b;
#endif
このプログラムを実行すると、次のメッセージが表示されます。
C struct= +0000000006 +00007 Show C literal
H2cpy は、プリプロセッサ、マクロ、条件、#error、および #pragma の 5種類の指令を変換します。
H2cpy では、#include 指令と #define 指令の両方が処理されます。
H2cpy は、次の形式の #include 指令を変換します。
#include <name>
|
name は拡張子付きのファイル名。相対パスを含めることも可能です。 |
#include "name"
|
name は拡張子付きのファイル名。相対パスまたは絶対パスを含めることも可能です。 |
#include macro |
macro は上のいずれかの name に展開されます。 |
H2cpy は指定されたファイルを検索し、見つかったファイルから C のソースを読み取ります。指定ファイルの末尾に到達すると、参照側のファイルに戻って解釈を続行します。
#include 指令には、ファイルの絶対パスを指定する必要はありません。ファイル名を二重引用符 (") で囲んで指定すると、最初にカレントディレクトリが検索され、続いてインクルードファイルの検索パスリストに登録された各ディレクトリが順次検索されます。
山かっこ (<>) で囲んだファイル名はシステムのヘッダーファイルと見なされ、インクルードファイルの検索パスリスト内のディレクトリのみが検索されます。カレントディレクトリは検索されません。
検索パスリストには、検索対象のディレクトリが絶対パスで最大 14 件登録されています。該当するファイルが見つかるまで、登録されているディレクトリが順次検索されます。ファイルが見つからないままリスト内の全ディレクトリの検索が終了すると、エラーメッセージが表示されます。
-I オプションを使用すれば、検索パスリストの先頭に任意のディレクトリを追加できます。このオプションについては、『コマンド行オプション』の説明を参照してください。
検索パスリストには、初期状態で /usr/include ディレクトリが登録されています。なお、H2cpy はパスを構成する各ディレクトリ名の区切り文字として半角の円記号 (\) を使用するため、検索パスに含まれるスラッシュ (/) は検索の開始前にすべて円記号に変換されます。
たとえば、INCLUDE 環境変数を次のように設定した場合を考えてみましょう。
include=d:\include;e:\sys\include
この場合、次の #include 指令を検出すると、H2cpy は d:\include\Xm\Xm.h を検索し、続いて e:\sys\include\Xm\Xm.h を検索します。
#include <Xm/Xm.h>
デフォルトパス (/usr/include) を使用している場合は、次の #include 指令を検出すると、
/usr/include/Xm/Xm.h のみが検索されます。
#include <Xm/Xm.h>
H2cpy はマクロをパラメータの有無にかかわらず変換します。C のソース内でマクロ名を検出すると、H2cpy はその定義を保持し、該当するマクロを展開します。1 つのマクロには任意数の C 言語のトークンを定義することが可能であり、通常は COBOL のコードに直接変換することはできません。
H2cpy は、次のマクロ定義を COBOL の 78 レベル項目に変換します。
C 言語の同一のトークンによって、大文字と小文字の両方で定義されているマクロは無視されます。これらの定義に相違があると、エラーメッセージが表示されます。
マクロ名の定義は、#undef 指令を使用すれば解除できます。
H2cpy は、パラメータ付きのマクロを文字列演算子と連結演算子 (# および ##) を使って展開します。次に #define 指令によるマクロ定義の例を示します。
#define DECLARE_HANDLE32(name)
struct name##__ { int unused; }; \
typedef const struct name##__ _far* name
このマクロ定義自体は 78 レベル項目には変換されませんが、同じ C ヘッダー内で次のマクロが見つかると、H2cpyは C の規則に従ってそのマクロを展開し、対応する COBOL コードを生成します。
DECLARE_HANDLE32(HHOOK);
COBOL ではデータポインタとプロシージャポインタを区別する場合を除き、ポインタの型を指定できません。
01 HHOOK-- is typedef.
02 unused usage int.
01 HHOOK is typedef usage data-pointer.
H2cpy は次の条件指令を解釈します。これらの指令のネスト構造にも対応しています。
#if #else #endif #elif #ifdef #ifndef
#if 指令の直後には、常に定数式が指定されます。H2cpy は、この式に含まれるマクロを展開し、定義済み演算子を評価し、認識できない名前をゼロで置換して式を評価して特定の数値を導出します。条件は、式の評価結果がゼロの場合は
FALSE、それ以外の値であれば TRUE になります。以降の行は、条件が FALSE の場合は無視され、TRUE であれば変換されます。
#else 指令と #endif 指令は、いずれもその前の #if、#ifdef、または #ifndef 指令で指定された条件を反転し、その効果を終了させます。
#elif 指令は、#else 指令とそれに続く #if 指令の組み合わせと基本的に同等です。ただし、#elif
の範囲内に入れ子が含まれないこと、および後続する #endif 指令が #elif 以前の #if
指令に対応していないことが条件です。
#ifdef 指令の直後には、常に名前が指定されます。この名前がヘッダーファイル内や -D オプションで定義済みであれば条件は
TRUE、未定義の場合は FALSE になります。以降の行は、条件が FALSE の場合は無視され、TRUE であれば変換されます。#ifndef
指令も、条件の解釈が逆になることを除いて、同様に処理されます。
#error 指令には、同じ行の後続部分にさまざまなコメントが指定されます。-C オプションを指定すると、H2cpy は同指令の行全体を画面表示し、出力ファイルにも書き出します。
#pragma 指令は基本的に無視されます。ただし、Microsoft や IBM の C 環境で各データ型のデフォルト整列を変更し、構造体や共用体のメンバーをパックする #pragma pack は例外です。次に #pragma pack の例を示します。
#pragma pack(n)
n の値は 1、2、4 のいずれかであり、以降に記述されたすべての構造体または共用体のメンバーを n バイトの境界に整列します。C 言語のデフォルト整列に戻すには、次の指令を使用します。
#pragma pack()
デフォルト整列は H2cpy の -e オプションや -a オプションでも変更できます。詳細については、前述の『コマンド行オプション』を参照してください。
H2cpy に -M オプションと -O オプションの両方を指定した場合には、#pragma pack は無視されます。
文字 (#) で始まる行は無視されます。
H2cpy は、定義と宣言の文を変換します。
その他の C の文はすべて無視されます。
H2cpy は、外部定義されたデータ宣言を除くすべてのデータ宣言を無視します。extern で定義された C のデータ宣言は、IS EXTERNAL 句を使用する COBOL 宣言に変換されます。C のモジュール内でそのように宣言され、COBOL アプリケーションからリンクできるデータ項目は、COBOL アプリケーションから参照することが可能です (リンク方法の詳細については、『Server Express ユーザガイド』を参照してください)。
H2cpy で生成されたデータは、基本的に .cpy ファイルに出力されますが、外部データ宣言は .ext ファイルに出力されます。
C のソース
typedef struct _WidgetClassRec *WidgetClass; extern WidgetClass widgetClass;
.cpy ファイルへの出力
01 WidgetClass is typedef usage data-pointer.
.ext ファイルへの出力
01 1widgetClass is external by "widgetClass" usage data-pointer.
COBOL では、定義する型の名前と外部データ項目の名前の重複は許可されません。そのため、この例では外部データ項目の名前の先頭に 1 が付加されています。シンボル名、
widgetClass は、リンカによって C のソース内で宣言されている外部データ項目への参照を解決するときに使用されます。
H2cpy は、明示的にsigned または unsigned 宣言された文字データを数値項目として処理します。また、配列として宣言されている場合は COBOL の英数字項目として、その他の場合には数値項目として処理します。2 次元配列は OCCURS 句に変換されます。
要素数が指定されていない配列は、同じデータ型のポインタと同様に変換されます。
C のデータ型のポインタは型定義を通じて COBOL のデータポインタに変換されます。同様に関数型のポインタも COBOL のプロシージャポインタに変換されます。
C のソース
typedef char t_slab[12], cnt, c_list[], c_table[12][5];
typedef unsigned char BYTE, *BYTE_ptr;
typedef t_slab *t_slab_ptr;
typedef void _near _cdecl _export _dmsEVENT(short ent_type);
typedef _dmsEVENT *fptr;
typedef void (*XtActionProc)(
#if NeedFunctionPrototypes
Widget /* widget */,
XEvent* /* event */,
String* /* params */,
Cardinal* /* num_params */
#endif
);
typedef XtActionProc* XtBoundActions;
生成される COBOL コード
01 t-slab is typedef pic x(12).
01 cnt is typedef usage char.
01 c-list is typedef usage data-pointer.
01 c-table is typedef.
02 filler occurs 12 pic x(5).
01 BYTE is typedef usage uns-char.
01 BYTE-ptr is typedef usage data-pointer.
01 t-slab-ptr is typedef usage data-pointer.
01 fptr is typedef usage proc-pointer.
01 XtActionProc is typedef usage proc-pointer.
01 XtBoundActions is typedef usage data-pointer.
C のその他の型定義は、COBOL の類似する型定義に変換されます。次に例を示します。
typedef signed int I, AI[12], *PI, I_Table[12] [5];
この型定義は、次の COBOL コードに変換されます。
01 I is typedef usage int.
01 AI is typedef.
02 filler occurs 12 usage int.
01 PI is typedef usage data-pointer.
01 I-Table is typedef.
02 filler occurs 5.
03 filler occurs 12 usage int.
構造体や共用体、および列挙型の宣言には必要に応じて名前が付けられます。これらのデータ型の宣言は、単独で記述される場合のほか、型定義に記述されたり、他の構造体や共用体の宣言の中に記述されることがあります。
名前が付けられた宣言は完全に COBOL コードに変換されます。
C のソース
typedef struct fsid { long val[2]; } fsid_t;
typedef unsigned long ino_t; /*inode number (filesystem) */
typedef unsigned int uint_t;
#define FHSIZE 32
#define MAXFIDSZ (FHSIZE - sizeof(fsid_t) - sizeof(uint_t))
struct fileid { /* this is for servers only! */
uint_t fid_len;
ino_tfid_ino;
uint_t fid_gen;
char fid_x[MAXFIDSZ - (sizeof(ino_t) + 2) -
sizeof(uint_t)]; };
生成される COBOL コード
01 fsid is typedef.
02 val occurs 2 usage long.
01 fsid-t is typedef usage fsid.
01 ino-t is typedef usage uns-long.
01 uint-t is typedef usage uns-int.
78 FHSIZE value 32.
78 MAXFIDSZ value 28.
01 fileid is typedef.
02 fid-len usage uns-int.
02 filler pic x(2).
02 fid-ino usage uns-long.
02 fid-gen usage uns-int.
02 fid-x pic x(14).
H2cpy は、長整数型の fid-ino 項目が 4 バイトで正しく整列されるように、2 バイトの fid-len 項目の後に 2 バイトの FILLER 項目を挿入します。
整列すべきバイト数は、-e オプションや -a オプション、および #pragma pack 指令の指定によって左右されます。IBM の C 環境で構造体および共用体に使用される _Packed 型は無視されます。
宣言に名前が付けられていない場合に、完全に COBOL コードに変換されるのは、宣言を使用する項目のみです。
C のソース
typedef struct {
int type;
union {
char b[20];
short s[10];
long l[5];
} data;
} XClientMessageEvent;
生成される COBOL コード
01 XClientMessageEventis typedef.
02 type usage int.
02 filler pic x(2).
02 data.
03 data.
04 1b pic x(20).
03 filler redefines data.
04 s occurs 10 usage short.
03 filler redefines data.
04 l occurs 5 usage long.
H2cpy は、名前が付けられた列挙型の値に対応する 78 レベル項目を生成します。列挙型の項目には、構造体の内部で名前を付けることもできます。構造体の内部では、ビットフィールドを指定することも可能です。
C のソース
enum input_type { GPICK = 0x0001, GANK= 0x0002,
GPFK = 0x0004, FP_NOINBUF = 0x10000,
FP_WTMAX = 0x20000 };
typedef struct qqel { /* queue element*/
enum input_type type; /* enum input_type value */
int time; /* timestamp */
struct {
unsigned bad_data :1; /* extra data io failed */
unsigned no_data :1; /* queue empty (for K_POLL) */
unsigned reserved :6; /* reserved */
char rsvd[3]; /* reserved */
} flags;
int data_len; /* length of appended data */
} q_qel;
生成される COBOL コード
01 input-type is typedef usage uns-int.
78 gpick value 1.
78 gank value 2.
78 gpfk value 4.
78 fp-noinbuf value 65536.
78 fp-wtmax value 131072.
01 qqel is typedef.
02 type usage input-type.
02 time usage int.
02 flags.
03 bad-data.
04 bad-data usage uns-int. *> 1 ビット
03 filler redefines bad-data.
04 no-data usage uns-int. *> 1 ビット
03 filler redefines bad-data.
04 reserved usage uns-int. *> 6 ビット
03 rsvd pic x(3).
03 filler pic x(1).
02 data-len usage int.
01 q-qel is typedef usage qqel.
rsvd は 3 バイト長の項目です。直前の 8 ビットで 1 バイトの記憶域が割り当てられることを前提としていましたが、ANSI
C ではビットフィールドに整数型の項目を充てるように定義されているため、実際には 16 ビットの領域が割り当てられます。したがって、H2cpy は末尾にパディング用の
1 バイト項目を追加する必要があります。
C 言語の関数プロトタイプには、常に特定の型の項目を返すこと、および 1 つ以上のパラメータを渡すことが求められます。パラメータが指定されていない関数定義は関数プロトタイプではなく、そのため、 H2cpy によって COBOL の CALL プロトタイプに変換されません。また、戻り値の型が指定されていない場合は整数型として処理されます。
特に値を返さない関数のプロトタイプでは、返される値の型として void 型が使用されます。この関数プロトタイプは H2cpy によって変換されますが、RETURNING 指定は生成されません。また、パラメータを持たない関数のプロトタイプは、void 型のパラメータを 1 つ持ちます。この関数プロトタイプの H2cpy による変換では、USING 指定や BY VALUE 指定、および BY REFERENCE 指定は生成されません。
C のソース
extern XFontStruct *XLoadQueryFont( ); extern void XrmInitialize( ); extern char *XFetchBytes( ); extern int (*XSetAfterFunction( ))(); extern XtAppContext XtCreateApplicationContext( void ); extern void XtInitializeWidgetClass( WidgetClass ); XmColorProc XmGetColorCalculation(void);
生成される COBOL コード
program-id. "c_typefefs" is external.
special-names.
call-convention default-convention-val is defaultconv.
$set constant XtCreateApplicationContext
$set "XtCreateApplicationContext"
entry XtCreateApplicationContext default-conv
returning data-pinter
.
$set constant XtInitializeWidgetClass
$set "XtInitializeWidgetClass"
entry XtInitializeWidgetClass default-conv using
by value data-pointer
.
$set constant XmGetColorCalculation "XmGetColorCalculation"
entry XmGetColorCalculation default-conv
returning proc-pointer
.
end program "c_typedefs".
エントリ名はリテラルではなく定数で指定されており、特殊名段落内のエントリによって呼び出し規則が指定されています。
C のソース
typedef HINSTANCE HMODULE; DWORD _far _pascal GetVersion(void); UINT _far _pascal GetFreeSystemResources(UINT); #define GFSR_SYSTEMRESOURCES 0x0000 BOOL _far _pascal SetWinDebugInfo(const WINDEBUGINFO _far* lpwdi); void _far _cdecl DebugOutput(UINT flags, LPCSTR lpsz, ...); #define WDI_OPTIONS 0x0001
生成される COBOL コード
01 HMODULE is typedef usage uns-int.
end program "c-typedefs".
program-id. "c-typedefs" is external.
special-names.
call-convention pascal-convention-val is pascal-conv.
$set constant GetVersion "GetVersion"
entry GetVersion pascal-conv
returning uns-long
.
$set constant GetFreeSystemResources
$set "GetFreeSystemResources"
entry GetFreeSystemResources pascal-conv using
by value uns-int
returning uns-int
.
end program "c-typedefs".
program-id. "c-typedefs" is external.
special-names.
call-convention pascal-convention-val is pascal-conv.
78 GFSR-SYSTEMRESOURCES value h"0000".
end program "c-typedefs".
program-id. "c-typedefs" is external.
special-names.
call-convention pascal-convention-val is pascal-conv.
$set constant SetWinDebugInfo "SetWinDebugInfo"
entry SetWinDebugInfo pascal-conv using
by reference windebuginfo
returning int
.
end program "c-typedefs".
program-id. "c-typedefs" is external.
special-names.
call-convention cdecl-convention-val is cdecl-conv.
$set constant DebugOutput "DebugOutput"
entry DebugOutput cdecl-conv using
by value uns-int
by reference any
by value any
.
end program "c-typedefs".
program-id. "c-typedefs" is external.
special-names.
call-convention cdecl-convention-val is cdecl-conv.
78 WDI-OPTIONS value h"0001".
end program "c-typedefs".
H2cpy による COBOL コードの生成は、標準呼び出し規約を使用するデフォルトの外部プログラム、c_typedefs 内から開始されています。GetVersion ルーチンでは Pascal の呼び出し規約が使用されるため、H2cpy は手続き部の ENTRY 文を含む新しい外部プログラムのヘッダーを生成しています。GetFreeSystemResources ルーチンは同じ Pascal の呼び出し規則を使用します。そのため、ここでは新しいプログラムヘッダーは生成されず、2 つめの ENTRY 文が生成されています。続いて、データ部内に 78 レベル項目を 1 つ生成する必要があるため、H2cpy は新しいプログラムヘッダーを生成しています。さらに、DebugOutput ルーチンでは cdecl 呼び出し規約が使用されるため、プログラムヘッダーをもう 1 つ生成しています。
C 言語では、パラメータは概念的にスタック経由で渡されます。パラメータ渡しには直接渡す方法と、ポインタで間接的に渡す方法があります。一方 COBOL では、4 バイトを超えるデータをスタック経由で直接渡すことはできません。C でも、構造体や共用体をスタック経由で渡す方法は不適切なプログラミング技法として認識されており、渡されるデータがポインタのサイズ (4 バイト) を超えると処理効率も低下してしまいます。H2cpy は 4 バイトを超える引数を見つけると自動的にパラメータを追加し、スタックの整合性を維持します。そのため、上記の COBOL の制約が問題になることはありません。
整数型や文字型、ポインタなどの単純なデータ型は容易に COBOL のデータ型に変換できます (H2cpy は、スタック経由で直接渡されるパラメータを検出すると BY VALUE 指定を生成します)。C 言語では、パラメータを間接的に渡す手段として型付きポインタを使用できます。COBOL でも間接的に渡すことは可能ですが、単一レベルのみに限定されます。H2cpy は型付きポインタを検出すると、BY REFERENCE 指定を生成します。
C のソース
typedef unsigned char BYTE;
typedef char _far* LPSTR;
typedef int HFILE;
typedef Boolean (*XtFilePredicate)( /* String filename */ );
BYTE _far _pascal GetTempDrive(char);
long _far _pascal _llseek(HFILE, long, int);
long _far _pascal _hwrite(HFILE, const void _huge*, long);
LPSTR _far _pascal AnsiLower(LPSTR);
void _far _pascal Throw(const int _far*, int);
extern_pascal String XtFindFile(
CONST String /* path */,
Substitution /* substitutions */,
Cardinal /* num_substitutions */,
XtFilePredicate /* predicate */
);
生成される COBOL コード
01 BYTE is typedef usage uns-char.
01 LPSTR is typedef usage data-pointer.
01 HFILE is typedef usage int.
01 XtFilePredicate is typedef usage proc-pointer.
end program "c-typedefs".
program-id. "c-typedefs" is external.
special-names.
call-convention pascal-convention-val is pascal-conv.
$set constant GetTempDrive "GetTempDrive"
entry GetTempDrive pascal-conv using
by value char
returning uns-char
.
$set constant 1-llseek "_llseek"
entry 1-llseek pascal-conv using
by value int
by value long
by value int
returning long
.
$set constant 1-hwrite "_hwrite"
entry 1-hwrite pascal-conv using
by value int
by value data-pointer
by value long
returning long
.
$set constant AnsiLower "AnsiLower"
entry AnsiLower pascal-conv using
by reference any
returning data-pointer
.
$set constant Throw "Throw"
entry Throw pascal-conv using
by reference int
by value int
.
end program "c-typedefs".
program-id. "c-typedefs" is external.
special-names.
call-convention default-convention-val is default-conv.
end program "c-typedefs".
program-id. "c-typedefs" is external.
special-names.
call-convention default-convention-val is default-conv.
$set constant XtFindFile "XtFindFile"
entry XtFindFile default-conv using
by reference any
by value data-pointer
by value uns-int
by value proc-pointer
returning data-pointer.
.
end program "c-typedefs".
_hwrite ルーチンの void 型ポインタは、値で渡されるデータポインタを生成しますが、AnsiLower
ルーチンの文字型ポインタ、 LPSTR は、あらゆるパラメータを指定できる BY REFERENCE 句を生成します。通常は、COBOL
のあらゆる英字項目が渡される可能性があり、文字型では制約が大きすぎるため、any が生成されます。
Throw ルーチンには、整数型項目が BY VALUE と BY REFERENCE の両方で渡されます。また、XtFindFile ルーチンには、プロシージャポインタが BY VALUE で渡されます。
C のソース
typedef int (_far _pascal* FARPROC)();
typedef struct tagSEGINFO
{
UINT offSegment;
UINT cbSegment;
UINT flags;
UINT cbAlloc;
HGLOBAL h;
UINT alignShift;
UINT reserved[2];
} SEGINFO;
typedef SEGINFO _far* LPSEGINFO;
typedef struct tagPOINT
{
int x;
int y;
} POINT;
void _far _pascal GetCodeInfo(FARPROC lpProc, SEGINFO _far*
lpSegInfo);
BOOL _far _pascal PtInRect(const RECT _far*, POINT);
void _far _pascal ClientToScreen(HWND, POINT _far*);
生成される COBOL コード
01 FARPROC is typedef usage proc-pointer.
01 tagSEGINFO is typedef.
02 offsegment usage uns-int.
02 cbsegment usage uns-int.
02 flags usage uns-int.
02 cballoc usage uns-int.
02 h usage uns-int.
02 alignshift usage uns-int.
02 reserved occurs 2 usage uns-int.
01 SEGINFO is typedef usage tagseginfo.
01 LPSEGINFO is typedef usage data-pointer.
01 tagPOINT is typedef.
02 x usage int.
02 y usage int.
01 POINT is typedef usage tagpoint.
end program "c-typedefs".
program-id. "c-typedefs" is external.
special-names.
call-convention pascal-convention-val is pascal-conv.
$set constant GetCodeInfo "GetCodeInfo"
entry GetCodeInfo pascal-conv using
by value proc-pointer
by reference seginfo
.
$set constant PtInRect "PtInRect"
entry PtInRect pascal-conv using
by reference rect
by value point
returning int
.
$set constant ClientToScreen "ClientToScreen"
entry ClientToScreen pascal-conv using
by value uns-int
by reference point
.
end program "c-typedefs".
POINT 型のパラメータは、BY VALUE と BY REFERENCE の両方で渡されます。
H2cpy はパラメータ付きのマクロを検出すると、以降のコード内での展開に備えて定義を保持します。ただし、パラメータ付きマクロの定義が 2 〜 3 行以上にわたる場合には、記憶域の容量が不足し、一部の定義情報を確保できない可能性があります。その時点では問題は表面化しませんが、当該マクロの展開が必要になった時点でエラーが発生します。
H2cpy と C コンパイラの前処理方法の相違による問題が発生するようであれば、ヘッダーファイルの前処理のみを C コンパイラで実行し、処理後のファイルを H2cpy の入力に使用することで問題を回避できる場合があります。
C 言語のデータ型は COBOL のデータ型とは異なり、そのままで環境間の互換性があるとは限りません。そのため、同じライブラリとのインターフェイスを使用するプログラムでも、動作するマシンやオペレーティングシステムが異なれば、H2cpy によるコードの再生成が必要になる可能性があります。
H2cpy は、IBM C 特有の _Packed 型を検出しても、構造体や共用体の 1 バイト整列は行いません。そのため、_Packed を前提としたパディング項目が使用されている場合には、手作業で削除する必要があります。
H2cpy は情報、警告、およびエラーの 3 種類のメッセージを生成します。情報メッセージは処理の状況を示します。警告メッセージは、変換したコードが正しくコンパイルされるが、意図した結果が得られない可能性がある問題を示します。エラーメッセージは、変換時にエラーが検出され、生成されるコードが正しくコンパイルできないことを示します。
注: 上記の各メッセージ以外にも、いくつかの内部エラーメッセージが表示される可能性があります。該当するメッセージには、内部メッセージとしてフラグがたてられます。内部エラーメッセージが生成されることはほとんどありませんが、仮に生成された場合は、C のヘッダーファイルが ANSI C のソースコードとして有効かどうかをチェックしてください。ヘッダーファイルに問題が見つからなければ、MERAN アンサーラインまで連絡してください。
警告メッセージには、常に先頭にアスタリスク (*) が付いています。このメッセージは、C のヘッダーファイル内に処理できないコードが見つかり、H2cpy によって無視されたことを示します。その結果、COBOL コピーファイルの生成や使用が妨げられることはありませんが、コピーファイルに間接的な影響が及んだり、該当する C ヘッダーファイルに不正な記述が含まれている可能性があります。H2cpy が生成する警告メッセージは次のとおりです。
説明: 関数 name の宣言内で使用されている戻り値のデータ型が、該当する関数プロトタイプで定義されたデータ型と一致しません。検出された宣言は無視されます。
説明: 数値式の内部で浮動小数リテラルが検出されました。式の評価では、該当するリテラルがゼロで置き換えられました。
説明: 長すぎる、または複雑すぎる数値式が検出されました。H2cpy は該当する式を処理せず、無視します。C のソースをチェックし、COBOL に変換すべき C の定義内で該当する式が使用されていないことを確認してください。
説明: マクロ name の定義が複数行にわたって検出されました。このマクロ定義は長すぎるため H2cpy で処理されず、無視されます。通常、無視されたマクロ定義は以降のヘッダーファイル内では参照されないため、COBOL への変換に影響が及ぶことはありません。
説明: 非常に多くのパラメータを指定しているマクロ定義が検出されました。このマクロ定義は H2cpy で処理されず、無視されます。通常、無視されたマクロ定義は以降のヘッダーファイル内では参照されないため、COBOL への変換に影響が及ぶことはありません。
説明: 非常に大きなパラメータを指定しているマクロ定義が検出されました。このマクロ定義は H2cpy で処理されず、無視されます。通常、無視されたマクロ定義は以降のヘッダーファイル内では参照されないため、COBOL への変換に影響が及ぶことはありません。
説明:
C のヘッダーファイル内で ANSI C に準拠しないコードが見つかりました。メッセージに示されているように、#define の使用方法が不正です。該当する行は無視されます。生成される COBOL コードは使用しないでください。C のヘッダーファイルで該当行を修正し、H2cpy による変換を再試行します。
説明:
C のヘッダーファイル内で ANSI C に準拠しないコードが見つかりました。メッセージに示されているように、#define によって同じマクロが繰り返し、異なる内容で定義されています。該当する行は無視されます。生成される COBOL コードは使用しないでください。C のヘッダーファイルで該当行を修正し、H2cpy による変換を再試行します。
説明: 32 ビットの C 環境では、4 バイトを超えるデータ項目を値で渡すことが可能ですが、その効果は実装によって異なり、COBOL から該当項目に直接アクセスすることもできません。この方法は C の開発者の間でも不適切なプログラミング技法として認識されており、それを使用している C のヘッダーファイルは変更すべきです。64 ビットシステムでは、値で渡せるデータ項目の最大サイズは 8 バイトになります。
次の各メッセージは、いずれも H2cpy のコマンド行が不正であるため、COBOL への変換が実行されないことを示します。エラーの内容に応じてコマンド行を修正し、H2cpy を再試行します。
説明:
コマンド行が長すぎます。ヘッダーファイル名とマクロ宣言を 1 つのヘッダーファイルにまとめてください。コマンド行で filename や -D declaredname オプションを使用するかわりに、ヘッダーファイル内で #include "filename" と #define declaredname オプションを使用して指定します。
説明: H2cpy に入力するヘッダーファイルの名前が指定されていません。
説明:
コマンド行で指定したファイル名が多すぎます。C のヘッダーファイルを 1 つ作成し、その中で #include を使って各ファイルをインクルードしてください。
説明: -D オプションで指定した name が重複しています。
説明: 指定した -I オプションによって、インクルードファイルの検索リストの上限数を超過しています。指定済みの -I オプションの数を減らす、またはINCLUDE 環境変数で指定しているディレクトリの数を減らしてください。
説明: -a オプション (または -s オプション) に指定したパラメータが不正です。
説明: -a オプションで指定したパラメータが不正です。
説明: -s オプションで指定したパラメータが不正です。
説明: -F オプションで指定したパラメータが不正です。
説明: -e オプションで指定したパラメータが不正です。
説明: フラグの文字が無効です。
次の各メッセージは、H2cpy に入力された C ヘッダーファイル内で、ANSI C に正しく準拠しないコードが検出されたことを示します。COBOL への変換は実行されません。該当するヘッダーファイルを ANSI C に準拠するよう正しく修正し、H2cpy による変換を再試行してください。エラーの詳しい情報を得るには、適切な構文チェック機能を有する C の開発ツールを使用する必要があります。
Copyright © 2002 Micro Focus International Limited. All rights reserved.
本書、ならびに使用されている固有の商標と商品名は国際法で保護されています。
| 複数の言語による開発 | アプリケーション構成システム |