CL

134. RCVMSG の落とし穴

CLPの中で RCVMSG でエラー・メッセージを監視することは日常よく行われていることである。
例えば

 :
0021.00              MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
0022.00                                                                
  :
  :
0046.00                                                                        
0047.00  ERROR:      RCVMSG     MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) +            
0048.00                           MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +  
0049.00                           MSGFLIB(&MSGFLIB)                            
0050.00  SNDMSG:     IF         COND(&MSGID *EQ ' ') THEN(DO)                  
0051.00              SNDPGMMSG  MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) +    
0052.00                           TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE)            
0053.00              MONMSG     MSGID(CPF2400) EXEC(RETURN)                    
0054.00              ENDDO                                                     
0055.00              ELSE       CMD(DO)                                        
0056.00              SNDPGMMSG  MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +           
0057.00                           MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) +            
0058.00                           MSGTYPE(&MSGTYPE)                            
0059.00              MONMSG     MSGID(CPF2400) EXEC(RETURN)                    
  :

[解説]

0021.00              MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))

で、もし CPFエラーが発生したら ERROR タグにジャンプして

0047.00  ERROR:      RCVMSG     MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) +            
0048.00                           MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +  
0049.00                           MSGFLIB(&MSGFLIB)

で発生したエラーMSGID &MSGID, エラーメッセージ: &MSG, メッセージ・データ: &MSGDTA、
メッセージ・ファイル : &MSGF, メッセージ・ファイルのライブラリー : &MSGFLIB を
受取ってから

0050.00  SNDMSG:     IF         COND(&MSGID *EQ ' ') THEN(DO)                  
0051.00              SNDPGMMSG  MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) +    
0052.00                           TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE)            
0053.00              MONMSG     MSGID(CPF2400) EXEC(RETURN)                    
0054.00              ENDDO                                                     
0055.00              ELSE       CMD(DO)                                        
0056.00              SNDPGMMSG  MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +           
0057.00                           MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) +            
0058.00                           MSGTYPE(&MSGTYPE)         

のように SNDMSG を使って上位の呼出し元のプログラムに報告することができる。
これは一般的な処理方法であり弊社でもサンプルCLPとして長い間使用してきた。

ところがひとつ盲点が見つかった。
RCVMSG で

 0047.00  ERROR:      RCVMSG     MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) +            
 0048.00                           MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +  
 0049.00                           MSGFLIB(&MSGFLIB)

として MSGFLIB(&MSGFLIB) としてメッセージ・ファイルのライブラリー : &MSGFLIB を
受取っているがこれにはほとんど *LIBL という値しか戻されていない。
たまたまメッセージ・ファイル QCPFMSG はライブラリー: QSYS に存在しているので
*LIBL で検索しても QCPFMSG が見つかるのだが QEDTMSG の場合はこのメッセージ・ファイルは
ライブラリー QPDA に存在しており *LIBL で検索しても通常は見つかることはない。

それでは QEDTMSG のようなライブラリー・リストにはないようなエラーが発生したときは
どのようにすればよいのだろうか?
正しくは

 0047.00  ERROR:      RCVMSG     MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) +            
 0048.00                           MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +  
 0049.00                           SNDMSGFLIB(&MSGFLIB)

のようにして SNDMSGFLIBパラメータに &MSGFLIB を指定するとよい。
SNDMSGFLIBパラメータには元のメッセージ・ファイルのライブラリー名が正しく戻される。
98%以上は QCPFMSG なので通常の業務では発生する確率は低いが厳密な話となると
SNDMSGFLIBパラメータに指定するのが正しい方法と言える。