CL

97. メッセージ・タイプの違いを学習しよう

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 ソースを元に開発されている。
CLP はバッチ環境で実行されれば結果のメッセージは
QSYSOPR に報告されるように作成されており、
対話式環境であれば自分自身 (*TOPGMQ) に報告されるように設計されている。

【サンプル・ソース: AA_SAMPLE 】
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 のベースとしてあらゆる条件が加味されているので是非活用されたい。