(57)【特許請求の範囲】
【請求項１】
コンピュータに、
第1のプログラム言語で記述されたソースコードをコンパイルする際に、前記ソースコードの中から、第2のプログラム言語で記述された関数を特定し、
特定された前記関数に設定されている第1の引数以外の引数であって当該関数に設定されていない第2の引数用のレジスタ領域に、前記関数の実行により前記レジスタ領域がアクセスされると、エラーが発生する所定のデータを記憶する命令を生成する
処理を実行させることを特徴とするコンパイラ。
【請求項２】
前記レジスタ領域は、引数のデータが記憶される領域を示すアドレスが記憶されるレジスタの領域であって、
前記命令の生成の前に、前記第1の引数用の第1の領域、および、前記第2の引数用の第2の領域を前記レジスタに確保する命令を生成し、
前記記憶において、前記第1の領域に前記第1の引数のデータが記憶される領域を示すアドレスを記憶し、前記第2の領域に前記所定のデータを記憶する命令を生成する
処理をコンピュータに実行させることを特徴とする請求項1に記載のコンパイラ。
【請求項３】
前記特定において、予め記憶された前記関数を呼び出す命令文と、前記ソースコードに記述された命令文とが一致する場合に、前記ソースコードに記述された命令文における前記関数を特定する
処理をコンピュータに実行させることを特徴とする請求項1に記載のコンパイラ。
【請求項４】
第2のプログラム言語で記述された関数を含む、第1のプログラム言語で記述されたソースコードを記憶する記憶装置と、
前記ソースコードをコンパイルする処理装置とを有し、
前記処理装置は、前記ソースコードをコンパイルする際に、前記ソースコードの中から、前記関数を特定し、特定された前記関数に設定されている第1の引数以外の引数であって当該関数に設定されていない第2の引数用のレジスタ領域に、前記関数の実行により前記レジスタ領域がアクセスされると、エラーが発生する所定のデータを記憶する命令を生成する
ことを特徴とするコンパイル装置。
【請求項５】
コンパイル装置で実行されるコンパイル方法であって、
前記コンパイル装置は、
第1のプログラム言語で記述されたソースコードをコンパイルする際に、前記ソースコードの中から、第2のプログラム言語で記述された関数を特定し、
特定された前記関数に設定されている第1の引数以外の引数であって当該関数に設定されていない第2の引数用のレジスタ領域に、前記関数の実行により前記レジスタ領域がアクセスされると、エラーが発生する所定のデータを記憶する命令を生成する
ことを特徴とするコンパイル方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、コンパイラ、コンパイル装置、および、コンパイル方法に関する。
【背景技術】
【０００２】
第1のプログラミング言語で記述されたソースコードに、第2のプログラミング言語で記述された関数を呼び出す命令文が含まれる場合がある。この命令文が実行されると、第2のプログラミング言語で記述された関数が実行される。第1のプログラミング言語は、例えば、コボル(COmmon Business Oriented Language、COBOL)言語である。第2のプログラミング言語は、例えば、C言語やJAVA（登録商標）である。
【０００３】
また、各種のプログラミング言語で記述された関数に設定されている引数のチェックを行う技術が様々提案されている。
【先行技術文献】
【特許文献】
【０００４】
【特許文献１】特開平２−２０５９３０号公報
【特許文献２】特開２０１３−１４０４７０号公報
【特許文献３】特開平２−２４０７４３号公報
【発明の概要】
【発明が解決しようとする課題】
【０００５】
第2のプログラミング言語で記述された関数を呼び出す命令文が含まれた、第1のプログラミング言語で記述されたソースコード（以下、外部関数の呼び出し命令文を含むソースコードと適宜記す）をコンパイルする場合を想定する。外部関数の呼び出し命令文を含むソースコードをコンパイルする場合、いわゆる共通のフレームワークを利用したり、同一コンパイラによるコンパイルを利用することは困難である。
【０００６】
ここで、共通のフレームワークは、コボル言語(以下、コボルと適宜記す)、C言語に共通のフレームワークである。なお、フレームワークは、例えば、アプリケーションソフトウェアの開発時に高頻度で利用される汎用的機能を提供するソフトウェアである。
【０００７】
かかる困難さのため、コンパイラは、外部関数の呼び出し命令文を含むソースコードをコンパイルする場合、外部関数に設定された引数の数が正しくない場合、その旨を例えば開発者に指摘することは困難である。
【０００８】
このように、外部関数に設定された引数の数が正しくないこと（引数の不一致とも呼ぶ）を指摘できないため、引数の不一致に起因して障害が発生した場合、障害原因(問題箇所とも呼ぶ)の特定が困難になり、障害解決に時間がかかることがある。障害原因の特定が困難になる具体的な理由については、図1〜図3で説明する。
【０００９】
本実施の形態の一つの側面では、障害原因の特定を容易にすることを目的とする。
【課題を解決するための手段】
【００１０】
一つの側面は、コンピュータに、第1のプログラム言語で記述されたソースコードをコンパイルする際に、前記ソースコードの中から、第2のプログラム言語で記述された関数を特定し、特定された前記関数に設定されている第1の引数以外の引数であって当該関数に設定されていない第2の引数用のレジスタ領域に、前記関数の実行により前記レジスタ領域がアクセスされると、エラーが発生する所定のデータを記憶する命令を生成する処理を実行させることを特徴とするコンパイラである。
【発明の効果】
【００１１】
一つの側面によれば、障害原因の特定を容易にすることができる。
【図面の簡単な説明】
【００１２】
【図１】図1は、引数の不一致に起因して発生する障害について説明する第1の図である。
【図２】図2は、引数の不一致に起因して発生する障害について説明する第2の図である。
【図３】図3は、引数の不一致に起因して発生する障害について説明する第3の図である。
【図４】図4は、本実施の形態におけるコンパイル装置1のハードウェアブロック図である。
【図５】図5は、引数をレジスタまたはスタック上に保存する領域の例を示す図である。
【図６】図6は、図4のコンパイルプログラムPGを説明するソフトウェアブロック図である。
【図７】図7は、コンパイルプログラムPGの処理の流れを説明するフロー図である。
【図８】図8は、図4のソースコードSRCの一部分を示す図である。
【図９】図9は、構文解析情報の一例を示す図である。
【図１０】図10は、構文解析情報CAIに基づき生成された中間情報の一部を説明する図である。
【図１１】図11は、図7の意味解析(S3)を説明するフロー図である。
【図１２】図12は、レジスタ引数とスタック引数を模式的に示す図である。
【図１３】図13は、図7の割り付け(S5)を説明するフロー図である。
【発明を実施するための形態】
【００１３】
［関連技術］
図1〜図3は、引数(パラメータとも呼ぶ)の不一致に起因して発生する障害について説明する第1〜第3の図である。なお、以下の図の説明において、同じ要素については同一の符号を付して、一度した説明を省略する。
【００１４】
図1は、コボルで記述されたソースコード(符号CBS1参照)と、C言語で記述されたソースコード(符号CS1)を示す。以下、コボルで記述されたソースコードをコボルのコードと適宜記す。また、C言語で記述されたソースコードをC言語のコードと適宜記す。なお、ソースコードは、プログラムコードとも呼ばれる。
【００１５】
コボルのコードCBS1において、「CALL "SUBC" USING P1 P2.」と記述されたコードは、C言語で記述された関数"SUBC"に引数"P1"、"P2"を設定し、関数"SUBC"を呼び出すことを示す。関数"SUBC"は、前記した外部関数である。
【００１６】
C言語で記述された関数"SUBC"のC言語のコードCS1について説明する。C言語のコードCS1は、戻り値が"long long int"型であり、3つの引数が設定される関数"SUBC"のC言語のコードを示す。引数1は、"long int"型の変数"p1"のポインタ("long int *p1 "参照)である。引数2は、"long int"型の変数"p2"のポインタ("long int *p2 "参照)である。引数3は、"long int"型の変数"p3"のポインタ("long int *p3 "参照)である。
【００１７】
関数"SUBC"は、変数"p3"に、変数"p3"と"10"とを加算した値を設定する("*p3 = *p3 +10;"参照)。関数"SUBC"は、この設定後、関数"func_a"に引数として変数"p3"を設定し、この関数"func_a"を実行する("func_a(*p3);"参照)。次いで、関数"SUBC"は、"0"を呼び出し元に戻して終了する("return(0);"参照)。
【００１８】
ここで、C言語の関数"SUBC"の引数は、3つである。しかし、コボルのコードCBS1において、「CALL "SUBC" USING P1 P2.」と記述されているように、C言語の関数"SUBC"を呼び出すソースコードでは、引数が2つしか設定されていない。換言すれば、コボルのコードCBS1では、引数"p3"が設定されない。この引数"p3"が設定されていない原因は、例えば、コボルのコードCBS1を記述したプログラマのミスである（いわゆるバグ）。
【００１９】
C言語の関数を呼び出す際に設定された引数の数と、このC言語の関数に設定する必要がある引数の数との間に不一致があると、様々な問題が発生する。以下、様々な問題について説明する。
【００２０】
かかるバグを有するコボルのコードCBS1がコンパイルされ、機械語で記述されたバイナリ形式の実行ファイル(exeファイルとも呼ばれる)が生成され、この実行ファイルがコンピュータにより実行される。この実行ファイルの実行において、「CALL "SUBC" USING P1 P2.」が実行されると、C言語の関数"SUBC"が呼び出される。ここで、C言語の関数"SUBC"を呼び出すソースコードでは、引数"p3"が設定されていないので、引数"p3"のポインタ(メモリアドレス)は不定になる。変数"p3"に設定される値は、不定のポインタが示すメモリ領域に記憶された値であるので、かかる値も不定である。
【００２１】
その結果、C言語の関数"SUBC"内で、変数"p3"に、変数"p3"と"10"とを加算した値が設定される処理("*p3 = *p3 +10;"参照)が正常に実行されることがある。そして、不定の値である変数"p3"が設定された関数"func_a"が実行されることがある("func_a(*p3);"参照)。
【００２２】
このように、変数"p3"に設定される値が不定のまま処理が実行されると、プログラムのテスト時において、予期せぬ箇所で、誤動作したり、プログラムが異常終了(アベンドとも呼ぶ)することがある。他にも、このように変数"p3"に設定される値が不定のまま処理が実行されると、プログラムのテスト時には障害が発生せずに、そのまま製品として出荷される場合がある。そして、出荷後、ユーザが、このプログラムを実行した場合、予期せぬ箇所で、誤動作したり、プログラムが異常終了することがある。なお、この箇所は、ソースコード内の箇所である。
【００２３】
以上説明したように、予期せぬ箇所で、プログラムが異常終了したり、誤動作すると、その発生原因の特定に時間がかかる。
【００２４】
なお、コボルのコードCBS1における各コードの内容を説明する。"IDENTIFICATION DIVISION."は、プログラム名や属性を指定する見出し部である。"PROGRAM-ID. MAINCOB."は、プログラム名"MAINCOB"を指定する。"DATA DIVISION."は、手続きで使用するためのデータを定義するデータ部であることを示す。"WORKING-STORAGE SECTION."は、手続きで使用するためのデータを定義する作業場所節を示す。
【００２５】
"01 P1 PIC S9(9) COMP-5."において、"P1"はデータ名を示し、"PIC"でデータの形式を指定する。ここで、"S"はデータが符号付きであることを示し、"9(9)"は、データが9桁の数字であることを示す。" COMP-5."は、データが2進数であることを示す。"01 P2 PIC S9(9) COMP-5."において、"P2"はデータ名を示す。"PIC"、"S"、"9(9)"、" COMP-5."の説明は、前記した説明と同じである。"PROCEDURE DIVISION."は、処理を記述する手続き部である。
【００２６】
また、呼び出す関数が動的に実行される場合でも、引数の数に不一致があると、図2、図3に示すように、この関数が呼び出された際に障害が発生する。
【００２７】
図2において、コボルのコードCBS2には、「CALL "SUBC" USING P1 P2.」が記述されている。コボルのコードCBS2からコボルの実行ファイルMe2が生成される("実行ファイル"参照)。
【００２８】
コボルの実行ファイルMe2は、「CALL "SUBC" USING P1 P2.」を実行することを示している。
【００２９】
ここで、エントリ情報について説明する。エントリ(Entry)情報は、プログラムの構造が動的プログラム構造の場合に必要な情報である。エントリ情報は、呼び出す関数の実行データ(バイナリデータ)が格納されているダイナミックリンクライブラリ(Dynamic Link Library,DLL)を特定するために使用される。
【００３０】
エントリ情報Ent21は、呼び出す関数"SUBC"が格納されているDLLが"C1.DLL"(符号DL21参照)であることを示す。DLL"C1.DLL"における関数"SUBC"のC言語のコードの一部を符号CS21に示す。C言語のコードCS21において、関数"SUBC"は、戻り値が"long long int"型であり、引数1、引数2が設定される関数である。引数1は、"long int"型の変数"p1"のポインタ("long int *p1 "参照)である。引数2は、"long int"型の変数"p2"のポインタ("long int *p2 "参照)である。
【００３１】
エントリ情報Ent22は、呼び出す関数"SUBC"が格納されているDLLが"C2.DLL"(符号DL22参照)であることを示す。DLL"C2.DLL"における関数"SUBC"のC言語のコードの一部を符号CS22に示す。C言語のコードCS22において、関数"SUBC"は、戻り値が"long long int"型であり、引数1〜引数3が設定される関数である。引数1は、"long int"型の変数"p1"のポインタ("long int *p1 "参照)である。引数2は、"long int"型の変数"p2"のポインタ("long int *p2 "参照)である。引数3は、"long int"型の変数"p3"のポインタ("long int *p3 "参照)である。
【００３２】
コボルの実行ファイルMe2が実行されると、「CALL "SUBC" USING P1 P2.」が実行される。「CALL "SUBC" USING P1 P2.」の実行により、C言語の関数"SUBC"が呼び出される。ここで、C言語の関数"SUBC"を呼び出すソースコードでは、引数"p3"が設定されていない。
【００３３】
コボルの実行ファイルMe2の実行時に、エントリ情報Ent21が指定されると、DLL"C1.DLL"(符号DL21参照)が呼び出される。この場合、C言語の関数"SUBC"の引数の個数は2個である。従って、引数の不一致がない("引数の数：一致"参照)。一方、コボルの実行ファイルMe2の実行時に、エントリ情報Ent22が指定されると、DLL"C2.DLL"(符号DL22参照)が呼び出される。この場合、C言語の関数"SUBC"の引数の個数は3個であり、引数の数に不一致がある("引数の数：不一致"参照)。
【００３４】
次に、図3の説明に移る。図3において、コボルのコードCBS3には、
「IF SYSTEM = WINDOWS THEN
MOVE “SUBC” TO SUBP
ELSE
MOVE “SUBD” TO SUBP
END-IF
CALL SUBP USING P1 P2.」
が記述されている。
【００３５】
この記述内容は、"SYSTEM"が" WINDOWS "の場合、引数"P1"、"P2"を設定した関数"SUBC"を呼び出し、"SYSTEM"が" WINDOWS "でない場合、引数"P1"、"P2"を設定した関数"SUBD"を呼び出すことを示している。
【００３６】
コボルのコードCBS3からコボルの実行ファイルMe3が生成される("実行ファイル"参照)。コボルの実行ファイルMe3は、「CALL "SUBP" USING P1 P2.」を実行することを示している。この関数"SUBP"は、"SYSTEM"が" WINDOWS "の場合、関数"SUBC"であり、"SYSTEM"が" WINDOWS "でない場合、関数"SUBD"である。「CALL "SUBP" USING P1 P2.」は、関数"SUBP"に引数"P1"、"P2"を設定し、関数"SUBP"を呼び出すことを示す。
【００３７】
エントリ情報Ent3は、呼び出す関数"SUBC"が格納されているDLLが"C1.DLL"(符号DL31参照)であり、呼び出す関数"SUBD"が格納されているDLLが"C2.DLL"(符号DL32または符号DL32m参照)であることを示す。
【００３８】
DLL"C1.DLL"(符号DL31)における関数"SUBC"のC言語のコードの一部を符号CS31に示す。また、DLL"C2.DLL"(符号DL32)における関数"SUBD"のC言語のコードの一部を符号CS32に示す。
【００３９】
関数"SUBC"、"SUBD"は、戻り値が"long long int"型であり、引数1、引数2が設定される関数である。引数1は、"long int"型の変数"p1"のポインタ("long int *p1 "参照)である。引数2は、"long int"型の変数"p2"のポインタ("long int *p2 "参照)である。
【００４０】
コボルの実行ファイルMe3が実行されると、"SYSTEM"が" WINDOWS "の場合、C言語の関数"SUBC"が呼び出され、"SYSTEM"が" WINDOWS "でない場合、C言語の関数"SUBD"が呼び出される。
【００４１】
コボルのコードCBS3では、C言語の関数"SUBC"、"SUBD"には2つの引数が設定されている。そして、C言語のコードCS31では、C言語の関数"SUBC"の引数は2つ、C言語のコードCS32では、C言語の関数"SUBD"の引数は2つである。従って、引数の不一致がない。
【００４２】
しかし、バージョンアップやバグの修正により、DLLのプログラムを修正する場合がある(図3の"プログラム修正")。例えば、DLL"C2.DLL"(符号DL32)をDLL"C2.DLL"(符号DLm32)に修正する。この修正において、DLL"C2.DLL"(符号DL32m)における関数"SUBD"のC言語のコードの一部を符号CS32mに示す。
【００４３】
修正後の関数"SUBD"は、戻り値が"long long int"型であり、引数1〜引数3が設定される関数である。引数1は、"long int"型の変数"p1"のポインタ("long int *p1 "参照)である。引数2は、"long int"型の変数"p2"のポインタ("long int *p2 "参照)である。引数3は、"long int"型の変数"p3"のポインタ("long int *p3 "参照)である。
【００４４】
このようにDLLの修正において、関数の引数が追加された場合、プログラマは、引数が追加された関数を呼び出す側のソースコードにおいて、この関数に設定する引数を追加する必要がある。図3の例では、プログラマは、引数3が追加された修正後の関数"SUBD"を呼び出す側のコードCBS3において、修正後の関数"SUBD"に対応して引数3を追加する必要がある。しかし、プログラマが、かかる追加を忘れた場合、前記した引数の不一致が発生する。
【００４５】
以上、図1〜図3で説明したように、プログラマのミスにより、関数を呼び出す際に設定された引数の数と、この関数に設定する必要がある引数の数との間に不一致が発生する。すると、かかる不一致により、この関数が呼び出された際に障害が発生する。そして、前記したように、この障害の発生原因を特定するまでに時間がかかる。そこで、引数の数に不一致がある場合でも、テスト実行時に障害を確実に発生させて、障害の発生原因を特定するまでに時間が短縮できるようにするコンパイル装置を提供する。
【００４６】
［本実施の形態］
(ハードウェアブロック図)
図4は、本実施の形態におけるコンパイル装置1のハードウェアブロック図である。コンパイル装置1は、いわゆるコンピュータであり、バスBに接続された、CPU101と、RAM102と、ROM103と、通信装置104と、ストレージ装置105と、外部記憶媒体読み取り装置106とを有する。なお、CPUは、" Central Processing Unit "の略語、RAMは"Random Access Memory"の略語、ROMは、" Read Only Memory"の略語である。
【００４７】
CPU101は、コンパイル装置1の全体を制御する中央演算処理装置である。CPU101は、レジスタ群101aを有する。
【００４８】
RAM102は、CPU101が実行する処理や、コンパイルプログラムPGが実行する各ステップにおいて生成(算出)されたデータなどを一時的に記憶する装置である。コンパイルプログラムは、コンパイラとも呼ばれる。RAM102は、例えばDRAM(Dynamic Random Access Memory)などの半導体メモリである。また、RAM102は、各種データ、例えば、各種情報INFを記憶する。RAMは、メモリとも呼ばれる。
【００４９】
コンパイルプログラムPGは、プログラミング言語で記述されているソースコードを、機械語や、オブジェクトコードに変換するプログラムである。オブジェクトコードは、バイトコードなどの中間言語により記述されるコードである。
【００５０】
ROM103は、各種データを記憶する。通信装置104は、LAN(Local Area Network)などのネットワークに接続する装置である。なお、通信装置104は、例えばネットワークインターフェイスカード(NIC：Network Interface Card)を有する。
【００５１】
ストレージ装置105は、例えばハードディスクドライブや、ソリッドステートドライブや、不揮発性の半導体メモリなどのデータ格納装置である。ストレージ装置105は、例えば、ソースコードSRCを記憶する。
【００５２】
外部記憶媒体読み取り装置106は、外部記憶媒体MDに記憶されたデータを読み取る装置である。外部記憶媒体MDは、不揮発性の記憶媒体であり、例えば、CD-ROM(Compact Disc Read Only Memory)、DVD(Digital Versatile Disc)などの可搬型記憶媒体である。
【００５３】
コンパイルプログラムPGの実行ファイルは、例えばストレージ装置105に記憶されている。CPU101は、コンパイル装置1の起動時に、ストレージ装置105からコンパイルプログラムPGの実行ファイルを読み込み、RAM102に展開する。
【００５４】
なお、コンパイルプログラムPGの実行ファイルを、外部記憶媒体MDに記憶してもよい。この場合、CPU101は、コンパイル装置1の起動時に、外部記憶媒体MDからコンパイルプログラムPGの実行ファイルを読み込み、RAM102に展開する。
【００５５】
(レジスタ)
図5は、引数をレジスタまたはスタック上に保存する領域の例を示す図である。図4において、四角形の枠が各引数のメモリアドレス(以下、アドレスと適宜記す)が記憶されるレジスタを示している。レジスタRGm(小文字mは、1〜nの整数、小文字nは、8以上の整数)は、関数のm番目の引数のアドレスが記憶されるレジスタを示している。図5において、"RCX"、"RDX"、"R8"、"R9"は、レジスタ名である。
【００５６】
換言すれば、レジスタRGmは、引数のデータが記憶されるメモリ領域を示すアドレスが記憶されるレジスタ領域である。このアドレスは、プログラムの実行ファイルを実行するコンピュータに設けられたRAMのアドレスである。このアドレスで示すRAMの領域に、引数のデータが記憶される。このコンピュータは、例えば、図4のコンパイル装置1であるが、他の情報処理装置であってもよい。
【００５７】
符号R0で示す領域は、レジスタパラメタ域であり、レジスタ群101aに常に確保される。符号R1で示す領域は、スタックパラメタ域であり、引数の数に応じて、レジスタ群101aに適宜確保される。レジスタパラメタ域、スタックパラメタ域のレジスタは、いわゆる引数用のレジスタとも呼ばれる。
【００５８】
(ソフトウェアブロック図)
図6は、図4のコンパイルプログラムPGを説明するソフトウェアブロック図である。コンパイルプログラムPGは、字句解析部11と、構文解析部12と、意味解析部13と、最適化部14と、割付部15と、オブジェクト生成部16とを有する。
【００５９】
字句解析部11は、ストレージ装置105に記憶されているソースコードSRCを読み出し、RAM102に展開し、展開されたソースコードSRCに対して字句解析を実行する。字句解析部11は、この字句解析において、ソースコードSRCをトークン(単語のかたまり)に分割する。
【００６０】
構文解析部12は、字句解析部11が分割したトークンが構文規則にしたがっているか解析する。そして、構文解析部12は、解析結果を示す構文解析情報を生成しRAM102に記憶する。
【００６１】
意味解析部13は、ソースコードSRCの内容、すなわち字句が意味的に正しいか解析する。意味解析部13は、例えば、未定義の変数が使用されていないかを解析する。そして、意味解析部13は、構文解析情報に基づいて、中間情報(中間コードとも呼ぶ)を生成し、RAM102に記憶する。
【００６２】
最適化部14は、プログラムの実行スピードを高速化するため、各種処理を実行する。最適化部14は、例えば、中間情報を変換して最適化する。割付部15は、中間情報に基づき、レジスタ割り付けを実行する。オブジェクト生成部16は、オブジェクトコードを生成し、オブジェクトファイルとして、RAM102やストレージ装置105に記憶する。
【００６３】
（フロー図）
図7は、コンパイルプログラムPGの処理の流れを説明するフロー図である。なお、フロー図の説明において、Ss(小文字のsは整数)は、ステップSsを示す。
【００６４】
ステップS1: 字句解析部11は、ストレージ装置105に記憶されているソースコードSRCを読み出し、RAM102に展開し、展開されたソースコードSRCに対して字句解析を実行する。
【００６５】
ステップS2:構文解析部12は、S1で分割された字句が構文規則に従っているか解析し、構文解析情報を生成する。
【００６６】
ステップS3:意味解析部13は、構文解析情報に基づき、中間情報を生成する。
【００６７】
ステップS4:最適化部14は、中間情報を変換して最適化する。
【００６８】
ステップS5:割付部15は、中間情報に基づき、レジスタ割り付けを実行する。
【００６９】
ステップS6: オブジェクト生成部16は、オブジェクトコードを生成する。
【００７０】
［具体例］
次に、図5〜図14を参照し、コンパイルプログラムPGの処理の流れを具体的に説明する。コンパイルプログラムPGは、図4のソースコードSRCをコンパイルする。ソースコードSRCは、例えば、図1に示した、コボルのコードCBS1と、C言語のコードCS1を含む。
【００７１】
(字句解析、構文解析)
図8は、図4のソースコードSRCの一部分を示す図である。コードCBS4は、コボルで記述されたコードである。「CALL "SUBC" USING P1 P2.」の説明については、図1などで説明したので、その説明を省略する。図9は、構文解析情報の一例を示す図である。
【００７２】
字句解析部11は、ソースコードSRCに対して字句解析を実行する(S1)。構文解析部12は、例えば、コードCBS4の「CALL "SUBC" USING P1 P2.」について構文解析を実行し、図9の構文解析情報CAIを生成する(S2)。
【００７３】
例えば、字句解析部11は、コードCBS4の「CALL "SUBC" USING P1 P2.」の左から順に、「CALL "SUBC" USING P1 P2.」をトークンに分解する(S1)。そして、構文解析部12は、分解された順に各トークンの内容を解析し、解析結果を構文解析情報CAIとして生成する。なお、構文解析に必要な情報は、予めストレージ装置105に記憶されている。
【００７４】
構文解析情報CAIにおける［STA］は、トークンが文であることを示し、［DIR］は、トークンが利用者データであることを示し、［KYW］は、トークンが予約語であることを示す。図9において、符号CAI1で示す枠内の［STA］は、トークン"CALL"が文であることを示す。符号CAI2で示す枠内の［DIR］は、トークン"SUBC"が利用者データであることを示す。符号CAI3で示す枠内の［KYW］は、"USING"が予約語であることを示す。符号CAI4で示す枠内の［DIR］は、トークン"P1"が利用者データであることを示す。符号CAI5で示す枠内の［DIR］は、トークン"P2"が利用者データであることを示す。
【００７５】
字句解析部11は、以上説明したように、コボルのソースコードSRCに含まれる複数の文の各々について字句解析を行う。そして、構文解析部12は、字句解析の解析結果に基づき、複数の文の各々の構文解析情報を生成する。なお、文の種類としては、例えば、DISPLAY文、IF〜THEN文など様々な文がある。
【００７６】
(意味解析)
次に、図9〜図11を参照して、意味解析について説明する。図10は、構文解析情報CAIに基づき生成された中間情報の一部を説明する図である。図11は、図7の意味解析(S3)を説明するフロー図である。
【００７７】
図10の中間情報MIは、「CALL "SUBC" USING P1 P2.」(コードCBS4参照)の引数用のレジスタを初期化する命令を含む中間情報の一例である。
【００７８】
中間情報MIにおける"[SETPRM]"は、引数の集合である引数リストの1エントリに引数を設定する命令である。
【００７９】
符号MI1で示す「［SETPRM］SETPRM(アドレス)  PARM1, P1」は、"PARM1"というエントリに引数"p1"のアドレス(ポインタ)を設定する命令である。符号MI2で示す「［SETPRM］SETPRM(アドレス)  PARM2, P2」は、"PARM2"というエントリに引数"p2"のアドレスを設定する命令である。符号MI3で示す「［SETPRM］SETPRM(アドレス)  PARMx, NULL」は、"PARMx"というエントリにNULLを設定する命令である。小文字xは、3以上の整数である。NULLは、ヌルポインタ（換言すれば、空ポインタ）である。プログラムの実行時に、ヌルポインタが参照されると、このプログラムは例えば強制終了する。
【００８０】
中間情報MIにおける"[CALLX] "は、外部プログラムを呼び出す命令である。この外部プログラムは、例えば、C言語で記述されたプログラムである。符号MI4で示す「［CALLX］CALLX  Temp, “SUBC”,  PML」は、PML（引数リスト）を引数として、外部プログラムの関数"SUBC"を呼び出す命令である。なお、"Temp"は外部プログラムの関数"SUBC"が復帰値を返却する一時域を示す。
【００８１】
次に、図11を参照して、図7の意味解析(S3)の流れを説明する。
【００８２】
ステップS31:意味解析部13は、RAM102に記憶された、ソースコードSRCの各文の構文解析情報の中から未取得の構文解析情報を取得する。この取得順序は、例えば、構文解析情報が生成された順である。意味解析部13は、例えば、図9の構文解析情報CAIを取得する。
【００８３】
ステップS32:意味解析部13は、取得した構文解析情報に呼び出し命令が含まれるか判定する。呼び出し命令は、前記した"CALL"や"INVOKE"文である。具体的には、意味解析部13は、取得した構文解析情報にトークンが文であることを示す"［STA］"として"CALL"または"INVOKE"が含まれているか判定する。意味解析部13は、取得した構文解析情報にトークンが文であることを示す"［STA］"として"CALL"または"INVOKE"が含まれている場合には、取得した構文解析情報に呼び出し命令が含まれると判定する。
【００８４】
取得した構文解析情報に呼び出し命令が含まれない場合(S32/NO)、ステップS36に移る。取得した構文解析情報に呼び出し命令が含まれる場合(S32/YES)、ステップS33に移る。
【００８５】
図9の構文解析情報CAIにおいては、"［STA］"として"CALL"が含まれている。従って、意味解析部13は、取得した構文解析情報CAIに呼び出し命令が含まれると判定する。
【００８６】
ステップS33:意味解析部13は、取得した構文解析情報に基づき、呼び出し命令に実際に設定されている引数に対応する中間情報を生成する。
【００８７】
具体的には、意味解析部13は、取得した構文解析情報の中から、呼び出し命令により呼び出される外部関数に設定される引数を抽出する。そして、意味解析部13は、この抽出した引数に対応するエントリにこの引数のアドレスを設定する命令を含む中間情報を生成する。この引数の抽出において、意味解析部13は、取得した構文解析情報にトークンが予約後であることを示す"［KYW］"として"USING"が含まれている場合、"［KYW］"の次に記述されている、利用者データであるトークンを、引数として抽出する。なお、トークンが利用者データであることを示す文字列は、"［DIR］"である。
【００８８】
図9の例では、取得した構文解析情報CAIにトークンが予約後であることを示す"［KYW］"として"USING"が含まれている。従って、意味解析部13は、"［KYW］"の次に記述されている、利用者データであるトークン"P1"、"P2"を引数として抽出する。詳しく説明すると、意味解析部13は、図9において、符号CAI4、CAI15で示す枠内のトークン"P1"、"P2"を引数として抽出する。
【００８９】
そして、意味解析部13は、この抽出した引数"P1"、"P2"に対応するエントリに、この引数のアドレスを設定する命令を含む中間情報を生成する。
【００９０】
図10の例では、意味解析部13は、"PARM1"というエントリに引数"p1"のアドレスを設定する命令(図10の符号MI1参照)と、"PARM2"というエントリに引数"p2"のアドレスを設定する命令(図10の符号MI2参照)とを含む中間情報を生成する。なお、この引数"p1"、"p2"のアドレスは、実行用コンピュータに設けられたRAMのアドレスである。
【００９１】
そして、意味解析部13は、外部プログラムを呼び出す命令をこの生成した中間情報に含ませる。具体的には、意味解析部13は、取得した構文解析情報の中から、呼び出し命令により呼び出される関数名を抽出する。意味解析部13は、この抽出において、呼び出し命令"CALL"または"INVOKE"の次に記述されている、利用者データであるトークンを、関数名として抽出する。
【００９２】
そして、意味解析部13は、抽出した関数名に基づき、外部プログラムを呼び出す命令を生成する。図9の例では、意味解析部13は、呼び出し命令"CALL"の次に記述されている、利用者データであるトークン"SUBC"を関数名として抽出する。意味解析部13は、図10の例では、PML（引数リスト）を引数として、外部プログラムの関数"SUBC"を呼び出す命令(符号MI4参照)を前記生成した中間情報に含ませる。
【００９３】
ステップS34:意味解析部13は、実際に設定された引数以外の引数用のレジスタを初期化する命令をS33で生成された中間情報に含める。
【００９４】
図9、図10の例では、外部プログラムの関数"SUBC"に実際に設定された引数は、"P1"、"P2"であった。従って、意味解析部13は、実際に設定された引数"P1"、"P2"以外の引数用のレジスタを初期化する命令をS33で生成された中間情報に含める。実際に設定された引数"P1"、"P2"以外の引数用のレジスタを初期化する命令は、"PARMx"というエントリにヌルポインタを設定する命令(符号MI3)である。
【００９５】
図9、図10の例では、S34終了後の中間情報が、図10の中間情報MIである。
【００９６】
ステップS35:意味解析部13は、RAM102に記憶された、ソースコードSRCの各文の構文解析情報の中に未取得の構文解析情報があるか判定する。未取得の構文解析情報がある場合(S35/YES)、S31に移る。未取得の構文解析情報がない場合(S35/NO)、中間情報の生成処理(S3)を終了し、最適化処理(S4)に移る。未取得の構文解析情報がない場合とは、直近に取得した構文解析情報が最後の構文解析情報であることを意味する。
【００９７】
ステップS36:意味解析部13は、文の構文解析情報に基づき、この文の中間情報を生成する。S36の処理は、コンパイラで一般に実行されている処理なので、その説明を省略する。S36の処理が終了するとS31に移る。
【００９８】
中間情報の生成処理が終了すると、最適化部14は、最適化のため各種処理を実行する(S4)。
【００９９】
以上説明したように、コンパイルプログラムPGが、第1のプログラム言語で記述されたソースコードSRCをコンパイルする際に、意味解析部13は、ソースコードSRCの中から、第2のプログラム言語で記述された関数(例えば、C言語の"SUBC")を特定する。第1のプログラム言語は、コボルであり、第2のプログラム言語は、C言語である。
【０１００】
意味解析部13は、特定において、予めストレージ装置105などに記憶された、関数を呼び出す命令文と、ソースコードSRCに記述された命令文とが一致する場合に、ソースコードSRCに記述された命令文における関数(例えば、C言語の"SUBC")を特定する。なお、予め記憶された関数を呼び出す命令文は、前記した構文解析に必要な情報であり、例えば、例えば、文字列"CALL"や"INVOKE"で示される。
【０１０１】
(割り付け)
最適化終了後、割付部15は、S3で生成された中間情報に基づき、レジスタ割り付けを実行する(S5)。図10、図12、図13を参照して、割り付けについて説明する。
【０１０２】
図12は、レジスタ引数とスタック引数を模式的に示す図である。図13は、図7の割り付け(S5)を説明するフロー図である。
【０１０３】
図12において、レジスタ群RGは、引数用のレジスタの一部分を模式的に示している。図12の引数用のレジスタ群RGは、図5において、"n"が7の場合を例示している。図12において、レジスタRG1には、引数"P1"のアドレスが記憶(設定)されていることを模式的に示している。さらに、レジスタRG2には、引数"P2"のアドレスが記憶されていることを模式的に示している。
【０１０４】
レジスタRG3〜RG7には、それぞれ、ヌルポインタ(NULL)が記憶されていることを模式的に示している。次に、図13を参照して、図7の割り付け(S5)の流れを説明する。
【０１０５】
ステップS51:割付部15は、RAM102に記憶された、ソースコードSRCの各文の中間情報の中から未取得の中間情報を取得する。この取得順序は、例えば、中間情報が生成された順である。割付部15は、例えば、図10の中間情報MIを取得する。
【０１０６】
ステップS52:割付部15は、取得した中間情報に引数を設定する命令が含まれるか判定する。具体的には、割付部15は、取得した中間情報に［SETPRM］が含まれているか判定する。割付部15は、取得した中間情報に［SETPRM］が含まれている場合には、取得した中間情報に引数を設定する命令が含まれると判定する。
【０１０７】
取得した中間情報に引数を設定する命令が含まれない場合(S52/NO)、ステップS57に移る。取得した中間情報に引数を設定する命令が含まれる場合(S52/YES)、ステップS53に移る。
【０１０８】
図10の中間情報MIにおいては、"［SETPRM］"が含まれている。従って、割付部15は、取得した中間情報MIに引数を設定する命令が含まれると判定する。
【０１０９】
ステップS53:割付部15は、S51で取得した中間情報に基づき、外部関数の呼び出し命令に実際に設定されている引数のアドレスを、この引数用のレジスタに記憶する命令をオブジェクト生成部16に出力する。外部関数の呼び出し命令に実際に設定されている引数は、この外部関数に実際に設定されている引数である。
【０１１０】
図10の中間情報MIの例では、割付部15は、引数"P1"のアドレスを引数"P1"用のレジスタに記憶する命令(以下、命令1と記す)をオブジェクト生成部16に出力する。命令1は、引数"P1"用の領域を実行用コンピュータのレジスタに確保する命令を含む。この領域は、図12の符号RG1で示す、レジスタ群RGの領域である。ここで、図12のレジスタ群RGは、実行用コンピュータのレジスタである。なお、実行用コンピュータは、ソースコードSRCの実行ファイルを実行するコンピュータである。
【０１１１】
そして、図10の中間情報MIの例では、割付部15は、引数"P2"のアドレスを引数"P2"用のレジスタに記憶する命令(以下、命令2と記す)をオブジェクト生成部16に出力する。命令2は、引数"P2"用の領域を実行用コンピュータのレジスタに確保する命令を含む。この領域は、図12の符号RG2で示す、レジスタ群RGの領域である。
【０１１２】
これら2つの命令1、命令2により、図12に示すように、実行用コンピュータは、関数"SUBC"の実行時に、引数"P1"のアドレスを引数"P1"用のレジスタに記憶し(図12のレジスタRG1参照)、さらに、引数"P2"のアドレスを引数"P2"用のレジスタに記憶する(図12のレジスタRG2参照)。
【０１１３】
ステップS54:割付部15は、S51で取得した中間情報の中に、実際に設定された引数以外の引数用のレジスタを初期化する命令が含まれるか判定する。S51で取得した中間情報の中に、実際に設定された引数以外の引数用のレジスタを初期化する命令が含まれる場合とは、S51で取得した中間情報の中に、あるエントリにヌルポインタを設定する命令が含まれる場合である。具体的には、S51で取得した中間情報の中に、NULLを示す情報が含まれる場合である。
【０１１４】
前記した初期化する命令が含まれない場合(S54/NO)、S56に移る。前記した初期化する命令が含まれる場合(S54/YES)、S55に移る。
【０１１５】
図10の中間情報MIの例では、S51で取得した中間情報MIの中に、NULLを示す情報が含まれる。従って、割付部15は、S54でYESと判定する。
【０１１６】
ステップS55:割付部15は、残りのレジスタを初期化する命令をオブジェクト生成部16に出力する。具体的には、割付部15は、実際に設定された引数以外の引数用のレジスタを初期化する命令(以下、命令3と適宜記す)をオブジェクト生成部16に出力する。この初期化は、レジスタにヌルポインタ（NULL）を記憶する処理である。
【０１１７】
命令3は、実際に設定された引数"P1"、"P2"以外の引数用の領域を実行用コンピュータのレジスタに確保する命令を含む。この領域は、図12の符号RG3〜RG7で示す、レジスタ群RGの領域である。
【０１１８】
図10の例では、割付部15は、実際に設定された引数"P1"、"P2"以外の引数用のレジスタを初期化する命令をオブジェクト生成部16に出力する。この命令により、図12に示すように、実行用コンピュータは、関数"SUBC"の実行時に、実際に設定された引数"P1"、"P2"以外の引数用のレジスタ（RG3〜RG7）にヌルポインタを記憶する(図12のレジスタ(RG3〜RG7)内の"（NULL）"参照)。
【０１１９】
ステップS56: 割付部15は、RAM102に記憶された、ソースコードSRCの各文の中間情報の中に未取得の中間情報があるか判定する。未取得の中間情報がある場合(S56/YES)、S51に移る。未取得の中間情報がない場合(S56/NO)、オブジェクトコード生成処理(S6)に移る。未取得の中間情報がない場合とは、直近に取得した中間情報が最後の中間情報であることを意味する。
【０１２０】
ステップS57:割付部15は、それぞれの中間情報に基づき、この中間情報に対する割り付けを実行する。S57の処理は、コンパイラで一般に実行されている処理なので、その説明を省略する。S57の処理が終了するとS56に移る。
【０１２１】
以上説明したように、割付部15は、外部関数に設定されている第1の引数以外の引数であって外部関数に設定されていない第2の引数用のレジスタ領域に、所定のデータを記憶する命令を生成し、オブジェクト生成部16に出力する(ステップS55)。
【０１２２】
この外部関数は、例えば、意味解析部13が特定した外部関数"SUBC"である。そして、外部関数に設定されている第1の引数は、例えば、引数"P1"、及び、引数"P2"である。所定のデータは、外部関数の実行によりレジスタ領域がアクセスされると、エラーが発生するデータであり、例えば、ヌルポインタ(ヌル値)である。このエラーは、例えば強制終了である。
【０１２３】
ここで、レジスタ領域は、引数のデータが記憶される領域を示すアドレス(ポインタ)が記憶されるレジスタの領域である。この引数のデータが記憶される領域は、実行用コンピュータのRAMの領域である。そして、このレジスタは、実行用コンピュータのレジスタである。
【０１２４】
割付部15は、前記した命令の生成前に、第1の引数用の第1の領域、および、第2の引数用の第2の領域をレジスタに確保する命令を生成し、オブジェクト生成部16に出力する。図12の例では、第1の引数用の第1の領域は、レジスタRG1、RG2である。また、図12の例では、第2の引数用の第2の領域は、レジスタRG3〜レジスタRG7である。
【０１２５】
そして、割付部15は、前記した第1の引数のデータが記憶される記憶領域を示すアドレスを第1の領域に記憶する命令を生成し、オブジェクト生成部16に出力する。さらに、割付部15は、ヌルポインタを前記した第2の領域に記憶する命令を生成し、オブジェクト生成部16に出力する。
【０１２６】
(オブジェクトコードの生成)
中間情報の生成処理が終了すると、オブジェクト生成部16は、オブジェクトコードを生成し、RAM102に記憶する(S6)。
【０１２７】
オブジェクト生成部16は、外部関数の呼び出し命令に実際に設定されている引数のアドレスを、この引数用のレジスタに記憶する命令が出力されている場合(ステップS53参照)、以下の処理を実行する。すなわち、オブジェクト生成部16は、外部関数の呼び出し命令に実際に設定されている引数のアドレス(ポインタ)を、この引数用のレジスタに記憶する命令コマンド(以下、第1の命令コマンドと適宜記す)をオブジェクトコードに含める。
【０１２８】
図12の例では、第1の命令コマンドは、引数"P1"のアドレスを引数"P1"用のレジスタRG1に記憶し、引数"P2"のアドレスを引数"P2"用のレジスタRG2に記憶する命令コマンドである。
【０１２９】
オブジェクト生成部16は、実際に設定された引数以外の引数用のレジスタを初期化する命令が出力されている場合(ステップS55参照)、以下の処理を実行する。すなわち、オブジェクト生成部16は、実際に設定された引数以外の引数用のレジスタにヌルポインタを記憶する命令コマンド(以下、第2の命令コマンドと適宜記す)をオブジェクトコードに含める。
【０１３０】
図12の例では、第2の命令コマンドは、実際に設定された引数"P1"、"P2"以外の引数用のレジスタ（RG3〜RG7）にヌルポインタを記憶する命令コマンドである。
【０１３１】
(実行ファイル)
以後、コンパイルプログラムPGは、生成されたオブジェクトコードをリンクし、実行ファイルを生成し、例えば、ストレージ装置105に記憶する。この実行ファイルは、コボルのコードCBS1と、C言語のコードCS1を含むソースコードSRCの実行ファイルである。この実行ファイルは、前記した第1の命令コマンド、第2の命令コマンドを含む。
【０１３２】
プログラムの品質管理を行う者(テスターとも呼ぶ)は、実行用コンピュータ(例えば、コンパイル装置1)に、この実行ファイルを実行させて、この実行ファイルに不具合がないか確認する。
【０１３３】
この実行において、関数"SUBC"(図1参照)が呼び出されて実行される。この実行において、実行用コンピュータは、前記した第1の命令コマンドを実行する。実行用コンピュータは、第1の命令コマンドの実行により、図12に示すように、第1の引数用のレジスタRG1および第2の引数用のレジスタRG2を確保し、レジスタRG1に引数"P1"のアドレスを記憶し、レジスタRG2に引数"P2"のアドレスを記憶する。
【０１３４】
さらに、実行用コンピュータは、第2の命令コマンドを実行し、レジスタRG3〜レジスタRG7を確保し、レジスタRG3〜レジスタRG7にヌルポインタを記憶する。
【０１３５】
前記した設定の終了後、実行用コンピュータは、関数"SUBC"(図1参照)を実行する。図1で説明したように、関数"SUBC"は、変数"p3"(引数"p3")に、変数"p3"と"10"とを加算した値を設定する("*p3 = *p3 +10;"参照)。この加算処理を行うため、実行用コンピュータは、変数"p3"のアドレス(ポインタ)が記憶されているレジスタRG3にアクセスする。
【０１３６】
ここで、レジスタRG3にはヌルポインタが記憶されている。従って、実行用コンピュータは、このレジスタRG3にアクセスして、ヌルポインタで示されるメモリ領域(換言すれば、RAMの領域)を参照すると、強制終了する。
【０１３７】
このように、外部関数"SUBC"を呼び出す際に設定された引数の数と、外部関数"SUBC"に設定する必要がある引数の数との間に不一致がある場合に、外部関数"SUBC"が実行されると、強制終了する。そのため、プログラムの開発者は、外部関数の呼び出しにより強制終了すると、前記した不一致があるか否かを確認すれば、強制終了の原因が前記した不一致であることを容易に確認できる。その結果、障害原因の特定を容易にすることができる。
【０１３８】
以上の実施の形態をまとめると、次の付記のとおりである。
【０１３９】
（付記１）
コンピュータに、
第1のプログラム言語で記述されたソースコードをコンパイルする際に、前記ソースコードの中から、第2のプログラム言語で記述された関数を特定し、
特定された前記関数に設定されている第1の引数以外の引数であって当該関数に設定されていない第2の引数用のレジスタ領域に、前記関数の実行により前記レジスタ領域がアクセスされると、エラーが発生する所定のデータを記憶する命令を生成する
処理を実行させることを特徴とするコンパイラ。
【０１４０】
（付記２）
前記レジスタ領域は、引数のデータが記憶される領域を示すアドレスが記憶されるレジスタの領域であって、
前記命令の生成の前に、前記第1の引数用の第1の領域、および、前記第2の引数用の第2の領域を前記レジスタに確保する命令を生成し、
前記記憶において、前記第1の領域に前記第1の引数のデータが記憶される領域を示すアドレスを記憶し、前記第2の領域に前記所定のデータを記憶する命令を生成する
処理をコンピュータに実行させることを特徴とする付記1に記載のコンパイラ。
【０１４１】
（付記３）
前記特定において、予め記憶された前記関数を呼び出す命令文と、前記ソースコードに記述された命令文とが一致する場合に、前記ソースコードに記述された命令文における前記関数を特定する
処理をコンピュータに実行させることを特徴とする付記1に記載のコンパイラ。
【０１４２】
（付記４）
前記所定のデータは、ヌル値である
ことを特徴とする付記1に記載のコンパイラ。
【０１４３】
（付記５）
第2のプログラム言語で記述された関数を含む、第1のプログラム言語で記述されたソースコードを記憶する記憶装置と、
前記ソースコードをコンパイルする処理装置とを有し、
前記処理装置は、前記ソースコードをコンパイルする際に、前記ソースコードの中から、前記関数を特定し、特定された前記関数に設定されている第1の引数以外の引数であって当該関数に設定されていない第2の引数用のレジスタ領域に、前記関数の実行により前記レジスタ領域がアクセスされると、エラーが発生する所定のデータを記憶する命令を生成する
ことを特徴とするコンパイル装置。
【０１４４】
（付記６）
コンパイル装置で実行されるコンパイル方法であって、
前記コンパイル装置は、
第1のプログラム言語で記述されたソースコードをコンパイルする際に、前記ソースコードの中から、第2のプログラム言語で記述された関数を特定し、
特定された前記関数に設定されている第1の引数以外の引数であって当該関数に設定されていない第2の引数用のレジスタ領域に、前記関数の実行により前記レジスタ領域がアクセスされると、エラーが発生する所定のデータを記憶する命令を生成する
ことを特徴とするコンパイル方法。
【符号の説明】
【０１４５】
1…コンパイル装置、101…CPU、101a…レジスタ群、102…RAM、103…ROM、104…通信装置、105…ストレージ装置、106…外部記憶媒体読み取り装置、11…字句解析部、12…構文解析部、13…意味解析部、14…最適化部、15…割付部、16…オブジェクト生成部。
【図１】
0006409638.tif 000002
【図２】
0006409638.tif 000003
【図３】
0006409638.tif 000004
【図４】
0006409638.tif 000005
【図５】
0006409638.tif 000006
【図６】
0006409638.tif 000007
【図７】
0006409638.tif 000008
【図８】
0006409638.tif 000009
【図９】
0006409638.tif 000010
【図１０】
0006409638.tif 000011
【図１１】
0006409638.tif 000012
【図１２】
0006409638.tif 000013
【図１３】
0006409638.tif 000014