CLP に組み込むメッセージ送信は SNDPGMMSG であるが
メッセージのタイプには *INFO
, *DIAG
, *ESCAPE
, ... など
種類があるが、どのように使い分ければよいのだろうか?
*INFO |
通知メッセージ。 主に QSYSOPR(*SYSOPR) などに通知するために使用される。自分自身へのメッセージを *INFO で送信してもDSPMSG で表示しないとメッセージは表示されない。SNDMSG でメッセージ送信したのと同じことである。従って CLP で QSYSOPR に送信するときは *INFO でもよいが自分自身(実行したジョブ)へのメッセージ送信には使用しない。 |
---|---|
*DIAG |
*DIAG とは DIALOG, つまり直訳すると「日記」の意味であり結果の通知となりメッセージが表示として残ることになる。 メニューやプログラムの実行直後に「XXXを実行しました」などの メッセージが最後に出力されているのは *DIAG メッセージである。従って自分自身への結果の報告のために出力するメッセージ・タイプ として最も多く利用されている。 |
*ESCAPE |
ESCAPE とは直訳すると「脱出」や「非難」、「抜け出す」などの 意味であるがエラーが発生して実行中の処理から抜け出すのに 利用される。 上位のプログラムは *ESCAPE メッセージを受け取ると MONMSG していないと異常終了となる。従って CLP の中でもエラーを報告するのであれば *DIAG や*INFO ではなく、*ESCAPE で出力するようにしておくべきである。逆に何かチェックする CLP プログラムを作って *ESCAPE で結果を出力するようにしておくと上位のプログラムは MONMSG で *ESCAPE を判断することができる。 |
次は弊社で CLP を作成するときのテンプレートとしている CLP ソースであり
基本的に CLP は、この CLP ソースを元に開発されている。
CLP はバッチ環境で実行されれば結果のメッセージは
QSYSOPR に報告されるように作成されており、
対話式環境であれば自分自身 (*TOPGMQ
) に報告されるように設計されている。
0001.00 PGM 0002.00 /*-------------------------------------------------------------------*/ 0003.00 /* AA_SAMPLE : テンプレート・サンプル CLP */ 0004.00 /* */ 0005.00 /* 2017/02/01 作成 */ 0006.00 /*-------------------------------------------------------------------*/ 0007.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132) 0008.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) 0009.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) 0010.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) 0011.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132) 0012.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1) 0013.00 DCL VAR(&TOPGMQ) TYPE(*CHAR) LEN(10) 0014.00 DCL VAR(&MSGTYPE) TYPE(*CHAR) LEN(10) + 0015.00 VALUE('*ESCAPE ') 0016.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) + 0017.00 VALUE(X'000074') /* 2 進数 */ 0018.00 DCL VAR(&NULL4) TYPE(*CHAR) LEN(4) + 0019.00 VALUE(X'00000000') 0020.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) 0021.00 0022.00 /*( 環境の取得 )*/ 0023.00 RTVJOBA TYPE(&TYPE) 0024.00 IF COND(&TYPE *EQ '0') THEN(DO) /* バッチ */ 0025.00 CHGVAR VAR(&TOPGMQ) VALUE('*SYSOPR ') 0026.00 ENDDO /* バッチ */ 0027.00 ELSE CMD(DO) /* 対話式 */ 0028.00 CHGVAR VAR(&TOPGMQ) VALUE('*TOPGMQ ') 0029.00 ENDDO /* 対話式 */ 0030.00 0031.00 IF COND(%SST(&APIERR 5 4) *NE &NULL4) THEN(DO) 0032.00 SNDPGMMSG + 0033.00 MSG('API: QUHDSPH の実行で次のエラーが発生 + 0034.00 しました。 ') MSGTYPE(*DIAG) 0035.00 GOTO APIERR 0036.00 ENDDO 0037.00 RETURN 0038.00 0039.00 APIERR: 0040.00 CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 9 7)) 0041.00 CHGVAR VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100)) 0042.00 CHGVAR VAR(&MSGF) VALUE('QCPFMSG ') 0043.00 CHGVAR VAR(&MSGFLIB) VALUE('QSYS ') 0044.00 GOTO SNDMSG 0045.00 0046.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) + 0047.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) + 0048.00 MSGFLIB(&MSGFLIB) 0049.00 SNDMSG: IF COND(&MSGID *EQ ' ') THEN(DO) 0050.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) + 0051.00 TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE) 0052.00 ENDDO 0053.00 ELSE CMD(DO) 0054.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + 0055.00 MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) + 0056.00 MSGTYPE(&MSGTYPE) 0057.00 ENDDO 0058.00 ENDPGM
この CLP はテンプレートなので、これをそのまま動作させることはできない。
「環境の取得」では、このCLPが対話式環境で実行されているのか、
それともバッチ式環境で実行されているのかを検出して
&TOPGMQ
: どこにメッセージ報告すべきかを決定している。
メッセージ・タイプは、始めは
0014.00 DCL VAR(&MSGTYPE) TYPE(*CHAR) LEN(10) + 0015.00 VALUE('*ESCAPE ')
として *ESCAPE
として設定されているが、
内部で RPG/COBOL などを実行して &MSG
を
完了メッセージとして受け取ったのであれば
CHGVAR &MSGTYPE VALUE('*DIAG ') GOTO SNDMSG
とすればメッセージ &MSG
を報告メッセージとして出力することができる。
APIERR
の部分は
DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) + VALUE(X'000074') /* 2 進数 */ : CALL PGM(QSYSETPT) PARM(&PROFTOKN &APIERR) IF COND(%SST(&APIERR 5 4) *NE &NULL4) THEN(DO) + /* APIERR */ SNDPGMMSG + MSG('API:QSYSETPT の実行でエラーが発生しま + した。 ') TOMSGQ(&TOPGMQ) MSGTYPE(*DIAG) GOTO APIERR ENDDO /* APIERR */
のようにして何かの API を実行したときに APIERR
に飛ばせば
APIERR
の内容を取り出して報告してくれる仕組みとなっている。
この CLP: AA_SAMPLE は、いつか読者に紹介しようと思っていたが
CLP のベースとしてあらゆる条件が加味されているので是非活用されたい。