COBOLプログラムから別のプログラムを起動
-
COBOLプログラムから別のプログラムを起動する方法を幾つか紹介します。
別のプログラムを起動する方法は幾つかあり、大きく分けると「1.システムサブルーチンを使う、2.特殊レジスタPROGRAM−IDでプログラム終了時に別のプログラムを起動」の2種類があります。
また、A−VXのCOBOLプログラムからWindows上のプログラムを起動する方法も幾つかあり、「1.制御符号を使ってパソコン上のプログラムを起動、2.別売りのリモートAPCallという製品を使う、3.別売りのNT*A−VX JOB連携ユーティリティという製品を使う」などの方法があります。
Windows上のプログラムを起動する例は、別のところで紹介していますので、ここでは同じA−VX上のプログラムを実行する方法を紹介します。
- システムサブルーチンによるプログラム起動
-
SPAWNマクロ実行、RUNマクロ実行、CHAINマクロ実行という3種類のシステムサブルーチンが用意されています。
- ◆SPAWNマクロ実行
-
説明書から概要を下に抜き出します。
詳細は「COBOL85システムサブルーチン説明書」を参照してください。
機能
自プログラムを終了させることなく、要求されたプログラムを画面切り離し状態で起動します。
起動できるプログラムの種類は、ロードモジュール(COBOLで作ったプログラムなどのこと)、ジョブストリーム、パラメータ。
一般形式
CALL "SYSSPAWN" USING データ名1 データ名2 データ名3
データ名3:実行モード/実行結果
データ名1:コマンド/パラメータ
・ファイル節・作業場所節または連絡節で7桁以上、512桁以下のデータ項目を定義。
レベル番号は01か77です。RUNコマンドとパラメータを指定します。
[1]標準の形式
name,パラメータ1; パラメータ2 />
[2]パラメータ1を省略した形式
name; パラメータ2 />
[3]パラメータ2を省略した形式
name,パラメータ1;
[4]パラメータ1、パラメータ2共に省略した形式
name;
nameは6桁で、足りない場合は6桁になるまで空白で埋めます。
データ名2:桁数
・4桁の符号なし整数項目です。データ名1に設定する桁数を指定。
データ名3は、次のように定義します。
01 データ名3. 02 データ名3−1 PIC X(10). 02 データ名3−2 PIC X(02). 02 データ名3−3 PIC X(10). 02 FILLER PIC X(08) VALUE SPACE.
データ名3−1:本命令を実行したプログラムの実行モードを指定。
"MODE=DEFER"・・・本CALL命令を実行したプログラムは、起動したプログラムの終了に関係なく進行します。
"MODE=WAIT "・・・本CALL命令を実行したプログラムは、起動したプログラムが終了するまで停止します。
データ名3−2:実行結果が返却されます。
データ名3−3:参照、更新不可の場所。
サンプルプログラム3−1
SPAWNマクロを使用して、SA0031というプログラムから、SA003というプログラムを起動します。
CALL "SYSSPAWN"を実行するプログラム(MODEはDEFER)
000010*********************************************************** 000020* サンプルプログラム3−1 ** 000030* 別ジョブ起動(SPAWN) ** 000040*********************************************************** 000050 IDENTIFICATION DIVISION. 000060 PROGRAM-ID. SA0031. 000070 ENVIRONMENT DIVISION. 000080 DATA DIVISION. 000090 WORKING-STORAGE SECTION. 000100* SPAWN DATA AREA 000110 01 SP01 PIC X(30). 000120 01 SP02 PIC 9(04). 000130 01 SP03. 000140 05 SP03-1 PIC X(10). 000150 05 SP03-2 PIC X(02). 000160 05 SP03-3 PIC X(10). 000170 05 FILLER PIC X(08) VALUE SPACE. 000180 PROCEDURE DIVISION. 000190 MPRG. 000200 INITIALIZE SP01 SP02 SP03. 000210*ディスクMSD000のUSERLMLという名前のライブラリにあるSA003と 000220*いう名前のロードモジュールをSPAWNで起動します 000230 MOVE "SA003 ,FIL=USERLML;" TO SP01. 000240 MOVE 19 TO SP02. 000250 MOVE "MODE=DEFER" TO SP03-1. 000260 CALL "SYSSPAWN" USING SP01 SP02 SP03. 000270 IF SP03-2 NOT = "00" 000280 DISPLAY "SPAWN ERROR " SP03-2 000290 STOP "NG!!" 000300 GO TO MPRG-E 000310 END-IF. 000320 STOP "SA0031 OK!!". 000330 MPRG-E. 000340 STOP RUN.
CALL "SYSSPAWN"で起動するプログラム
000010*********************************************************** 000020* サンプルプログラム3−0 ** 000030* 別ジョブ起動 ** 000040*********************************************************** 000050 IDENTIFICATION DIVISION. 000060 PROGRAM-ID. SA003. 000070 ENVIRONMENT DIVISION. 000080 DATA DIVISION. 000090 PROCEDURE DIVISION. 000100 MPRG. 000110 DISPLAY COMPLETION-CODE. 000120 STOP "SA003 OK!". 000130 MPRG-E. 000140 STOP RUN.
ここでミソなのは、プログラムSA0031の23行目、データ名1にRUNコマンドをセットしていますが、"SA003△,FIL=USERLML;"とSA003と,の間に空白を1個入れて6桁にしていることです。(データ名1の説明箇所「nameは6桁で、足りない場合は6桁になるまで空白で埋めます。」)
これを"SA003,FIL=USERLML"と空白を抜かして5桁にするとエラー(データ名3−2に90:RUNコマンドパラメータエラー)になります。「;」以降に空白以外の文字があってもエラーになることがあります。
SA0031とSA003という2つのロードモジュールが出来たら、それらをMSDS000のUSERLMLというライブラリに入れます。
そして「SA0031,FIL=USERLML」とコマンドを実行してみると(うまくいけば)下のように「SA0031 OK!」のように画面に表示されます。
SA003は『画面切り離し状態で起動』しています。この「画面切り離し状態」というのは、Windowsでいうと「起動したプログラムのウインドウ(これがSA003の画面に相当します)」が、「前に出ているウインドウ(これがSA0031に相当します)」の後ろに隠れている状態です。
Windowsの場合、後ろに隠れているウインドウを前に出すために、タスクバーのアイコンをクリックしたり、「Alt」+「Tab」を押したりします。A−VXでは、システムコマンドの「画面接続コマンド」を使用します。
それではシステムコマンドの「画面接続コマンド」を使用して、SA003の画面を表に出しましょう。たくさんのジョブが動いている時は、目的の画面が出てくるまで何回もコマンドを実行します。
下の画面がSA003の画面です。
うまく別のプログラムを起動できていました。
SA003を終了するには、システムコマンドの「再開コマンド」を実行します。(終了するのに再開は変に思えるかもしれませんが、STOP命令でプログラムを一時停止しているので、「再開コマンド」でプログラムの実行を再開させ、STOP命令の次は終わりなので、プログラムが終了することになります。)
必要に応じて「画面接続コマンド」を使用して、SA0031の画面も表に出して、同じように「再開コマンド」を実行してプログラムを終了させましょう。
サンプルプログラム3−1(SA0031)はMODEはDEFERでしたが、WAITにするとどうなるかも試してみましょう。
25行目の"MODE=DEFER"を"MODE=WAIT "に変更して、ロードモジュールを作ります。
同じように実行してみると、今度は下のような画面になります。
「SA0031 OK!!」が表示されていません。これは26行目のCALL "SYSSPAWN"を実行したところで止まっているからです。
SA003が起動しているか確認してみましょう。
「画面接続コマンド」でSA003を表画面にします。
「再開コマンド」を実行してSA003を終了します。
「画面接続コマンド」を実行(必要に応じて複数回実行)して、SA0031を表画面にします。
SA003が終了したので、SA0031が動き出して「SA0031 OK!!」と表示されているはずです。
親プログラムが子プログラムを起動して、そこからまた孫プログラムを起動して・・・のようにも作れます。
- ◆RUNマクロ実行
説明書から概要を下に抜き出します。
詳細は「COBOL85システムサブルーチン説明書」を参照してください。
機能
可変パラメータで、ロードモジュール(COBOLで作ったプログラムなどのこと)、パラメータあるいはジョブストリームを起動します。
一般形式
CALL "CBLRUN" USING データ名1 データ名2
データ名1:コマンド/パラメータ
・ファイル節・作業場所節または連絡節で7桁以上、512桁以下のデータ項目を定義。
レベル番号は01か77です。RUNコマンドとパラメータを指定します。
[1]標準の形式
name,パラメータ1; パラメータ2 />
[2]パラメータ1を省略した形式
name; パラメータ2 />
[3]パラメータ2を省略した形式
name,パラメータ1;
[4]パラメータ1、パラメータ2共に省略した形式
name;
nameは6桁で、足りない場合は6桁になるまで空白で埋めます。
データ名2:桁数
・4桁の符号なし整数項目です。データ名1に設定する桁数を指定。
サンプルプログラム3−2
RUNマクロを使用して、SA0032というプログラムから、SA003というプログラムを起動します。
SA003は、SPAWNマクロ実行で使用したものをそのまま流用します。
000010*********************************************************** 000020* サンプルプログラム3−2 ** 000030* 別ジョブ起動(RUN) ** 000040*********************************************************** 000050 IDENTIFICATION DIVISION. 000060 PROGRAM-ID. SA0032. 000070 ENVIRONMENT DIVISION. 000080 DATA DIVISION. 000090 WORKING-STORAGE SECTION. 000100* SPAWN DATA AREA 000110 01 SP01 PIC X(30). 000120 01 SP02 PIC 9(04). 000130 PROCEDURE DIVISION. 000140 MPRG. 000150 INITIALIZE SP01 SP02 . 000160 STOP "再開コマンドでSA003を起動します". 000170*ディスクMSD000のUSERLMLという名前のライブラリにあるSA003と 000180*いう名前のロードモジュールをRUNで起動します 000190 MOVE "SA003 ,FIL=USERLML;" TO SP01. 000200 MOVE 19 TO SP02. 000210 CALL "CBLRUN" USING SP01 SP02. 000220 STOP "SA0032 OK!!". 000230 MPRG-E. 000240 STOP "SA0032は終了します". 000250 STOP RUN.
ここでミソなのは(SPAWNマクロ実行と同じですが)、19行目でデータ名1にRUNコマンドをセットしていますが、"SA003△,FIL=USERLML;"とSA003と,の間に空白を1個入れて6桁にしていることです。(データ名1の説明箇所「nameは6桁で、足りない場合は6桁になるまで空白で埋めます。」)
これを忘れて、"SA003,FIL=USERLML」とnameの部分が6桁以外だと、何も起動しないでプログラムが終わってしまいます。
SA0032とSA003(SPAWNマクロで説明しているプログラム)という2つのロードモジュールが出来たら、それらをMSDS000のUSERLMLというライブラリに入れます。
そして「SA0032,FIL=USERLML」とコマンドを実行してみると下のようになります。
再開コマンドを実行すると、RUNマクロ実行によってSA003が起動されます。
ここでさらに再開コマンドを実行すると、SA003が終了します。
RUNコマンド実行の次にある22行目や24行目は実行されないことに注意。つまりSA003の実行が終わっても戻ってくることはありません。RUNコマンド実行の前にやるべきこと(例えばSA0032でオープンしたファイルをクローズする)はやっておく必要があります。ファイルのオープンの情報は引き継がれないので、SA0032でオープンしたファイルをSA003でクローズする、というようなことはできません。
- ◆CHAINマクロ実行
説明書から概要を下に抜き出します。
詳細は「COBOL85システムサブルーチン説明書」を参照してください。
機能
自プログラムを終了させて、新たに要求されたプログラムを起動します。起動されたプログラムの終了後、再び元のプログラムを起動します。
一般形式
CALL "SYSCHAIN" USING データ名1 データ名2
データ名1:コマンド/パラメータ
・ファイル節・作業場所節または連絡節で7桁以上、512桁以下のデータ項目を定義。
レベル番号は01か77です。RUNコマンドとパラメータを指定します。
[1]標準の形式
name,パラメータ1; パラメータ2 />
[2]パラメータ1を省略した形式
name; パラメータ2 />
[3]パラメータ2を省略した形式
name,パラメータ1;
[4]パラメータ1、パラメータ2共に省略した形式
name;
nameは6桁で、足りない場合は6桁になるまで空白で埋めます。
データ名2:桁数
・4桁の符号なし整数項目です。データ名1に設定する桁数を指定。
サンプルプログラム3−3
CHAINマクロを使用して、SA0033というプログラムから、SA003というプログラムを起動します。
SA003は、SPAWNマクロ実行で使用したものをそのまま流用します。
000010*********************************************************** 000020* サンプルプログラム3−3 ** 000030* 別ジョブ起動(CHAIN) ** 000040*********************************************************** 000050 IDENTIFICATION DIVISION. 000060 PROGRAM-ID. SA0033. 000070 ENVIRONMENT DIVISION. 000080 DATA DIVISION. 000090 WORKING-STORAGE SECTION. 000100* SPAWN DATA AREA 000110 01 SP01 PIC X(30). 000120 01 SP02 PIC 9(04). 000130 PROCEDURE DIVISION. 000140 MPRG. 000150 INITIALIZE SP01 SP02 . 000160*ジョブ制御変数が123なら2回目の起動なので、SA0033を終了する 000170 IF COMPLETION-CODE = 123 GO TO MPRG-E. 000180* 000190 STOP "再開コマンドでSA003を起動します". 000200*SA003にジョブ制御変数=123を渡すために値を設定します 000210 MOVE 123 TO COMPLETION-CODE. 000220*ディスクMSD000のUSERLMLという名前のライブラリにあるSA003と 000230*いう名前のロードモジュールをRUNで起動します 000240 MOVE "SA003 ,FIL=USERLML;" TO SP01. 000250 MOVE 19 TO SP02. 000260 CALL "SYSCHAIN" USING SP01 SP02. 000270 STOP "SA0033 OK!!". 000280 MPRG-E. 000290 STOP "SA0033は終了します". 000300 STOP RUN.
ここで気をつけなければならないのは、24行目でデータ名1にRUNコマンドをセットしていますが、"SA003△,FIL=USERLML;"とSA003と,の間に空白を1個入れて6桁にしていることです。(データ名1の説明箇所「nameは6桁で、足りない場合は6桁になるまで空白で埋めます。」)
これを忘れて、"SA003,FIL=USERLML」とnameの部分が6桁以外だと、何も起動しないでそのまま又SA0033が起動してしまいます。
CHAINマクロ実行だと、COMPLETION-CODE(ジョブ制御変数)の値が次のプログラムに引き継がれます。このサンプルプログラムではSA0033で「123」という値をCOMPLETION-CODEにセットしていますが、その値がCALL "SYSCHAIN"で起動したSA003、そしてもう一度起動したSA0033に引き継がれていくのが分かると思います。
17行目は、そのままだとSA003を起動->SA0033が起動->SA003を起動->SA0033を起動・・・と無限に繰り返してしまうので、COMPLETION-CODEを見て2回目の起動だったら止めるようにしています。
下が実際に実行してみた結果です。
まずSA0033が起動します。
プログラム内部ではCOMPLETION-CODEに123という値を入れています。
再開コマンドを実行するとCHAINマクロ実行でSA003を起動します。
SA003が起動しました。COMPLETION-CODEの値が引き継がれていることが分かります。
それからSA0033は27行目の「SA0033 OK!!」であるとか28行目の「SA0033は終了します」というような表示しないで終了していることも分かります。
再開コマンドを実行するとSA003は終了します。
SA003が終わったので、自動的にSA0033が起動します。1回目のSA0033でセットしたCOMPLETION-CODEの値が引き継がれているので、17行目で29行目にジャンプ、「SA0033は終了します」と表示されました。
後は再開コマンドで終了します。
COBOLで自作のメニュー画面(アプリケーションのランチャー)を作りたいときなどに使えるかもしれません。CHAINマクロ実行で業務アプリケーションを起動、終わったら自動的にメニュー画面に戻ってくるのような・・・。
- 特殊レジスタPROGRAM−IDによるプログラム起動
-
特殊レジスタPROGRAM−IDというものを使うとプログラム終了時に別のプログラムを起動することができます。
説明書から概要を下に抜き出します。
詳細は「COBOL85言語説明書」などを参照してください。
機能
STOP(停止)命令は,実行単位の実行を完全にまたは一時的に休止させる。
一般形式
STOP {RUN | 定数-1 }
〜
(2)STOP RUN(状態停止)命令は、その一連の無条件命令の中の最後の命令でなければならない。
〜
本コンパイラのRUN指定では,特殊レジスタCOMPLETION-CODEの内容が完了コードとして実行管理システムへ渡される。また特殊レジスタPROGRAM-IDの内容にプログラム名などが設定されいれば(内容が空白でない)設定されているプログラムなどが自動的に実行開始される。特殊レジスタPROGRAM-IDの内容が空白のときは,実行用プログラムは終了し制御は実行管理プログラムに移る。
サンプルプログラム3−4
特殊レジスタPROGRAM−IDを使用して、SA0034というプログラムから、SA003というプログラムを起動します。
SA003は、SPAWNマクロ実行で使用したものをそのまま流用します。
000010*********************************************************** 000020* サンプルプログラム3−4 ** 000030* 別ジョブ起動(STOP命令) ** 000040*********************************************************** 000050 IDENTIFICATION DIVISION. 000060 PROGRAM-ID. SA0034. 000070 ENVIRONMENT DIVISION. 000080 DATA DIVISION. 000090 PROCEDURE DIVISION. 000100 MPRG. 000110 MOVE "SA003" TO PROGRAM-ID. 000120 STOP "SA0034 END". 000130 MPRG-E. 000140 STOP RUN.
11行目で実行したいプログラムの名前(この例ではSA003)を特殊レジスタに入れて、14行目でSTOP RUNを実行しています。(その前の12行目のSTOP命令では、メッセージを表示して一時停止しているだけで、このSTOP命令は別ジョブ起動とは関係ありません。)
たぶんシステム上にライブラリはたくさん(SYS@LML、SYS@JSL、誰かが作ったライブラリetc.)あると思います。また実行できるものはロードモジュールの他にジョブストリームやパラメータがあります。
今回の例では「SA003」という名前を特殊レジスタに入れていますが、SYS@LMLにも「SA003」という名前のLMが入っていて、SYS@JSLにも「SA003」という名前のJSが入っていて、USERLMLやTESTLMLという名前のライブラリにも「SA003」が入っていたときに、どこのライブラリに入っている「SA003」が起動されるのでしょうか?
『システム管理説明書』の「ジョブ起動ファイルの選定方法」に次のように書いてあります。
(DEV指定もFIL指定も無いとき)〜前略〜プログラム内の内部コール命令の場合、このスレッドのプライベートロードモジュールライブラリ−>SRV上のSYS@LML−>SYS@JSL−>SYS@PMLの順に指定のジョブを探します。プライベートロードモジュールライブラリが保持されていなければ、〜後略〜
上で挙げられている以外の任意のライブラリから起動したい時は、「SA003を起動するJSを1個作ってそのJSをSYS@JSLに入れる」(こっちが推奨案)か、先に説明した「RUNマクロ実行」を使うか、どちらかになります。
上のサンプルプログラム3−4を実行してみます。
12行目で一時停止したところ。ここで再開コマンド実行すると先に進みます。
14行目のSTOP RUNを実行した為、SA034(サンプルプログラム3−4)は終了し、特殊レジスタPROGRAM-IDの内容に従ってSA003が起動されました。
4つの違い
SPAWNマクロ実行、RUNマクロ実行、CHAINマクロ実行、特殊レジスタPROGRAM−IDによるプログラム起動の違いをまとめました。
PROGRAM-ID | RUNマクロ実行 | CHAINマクロ実行 | SPAWNマクロ実行(DEFER) | SPAWNマクロ実行(WAIT) | |
---|---|---|---|---|---|
種類 | 特殊レジスタ | システムサブルーチン | |||
元のプログラム はどうなるか | 終了 | 実行継続 | 一時停止 | ||
起動した プログラムが 終了すると? | 終わり | 元のプログラムが 最初から起動 | − | 元のプログラム再開 (CALLの次の命令 から実行再開) | |
パラメータ | 指定できない | 指定できる | |||
ジョブ制御変数 (JRCODE) (COMPLETION-CODE) | 子プログラムには 引き継がれる | 子プログラムには 引き継がれない | |||
センススイッチ (外部スイッチ) | 子プログラムには 引き継がれる | 子プログラムには 引き継がれない | |||
起動失敗したら? | 何事も無く プログラム終了 | 元のプログラムが 最初から起動 | エラーコードが返る |
「xxマクロ実行」でCALL命令を実行するプログラムとそれによって起動するプログラムの関係