RPG

410. RPGでポインタを学習する(4)

C*-------------------------------------------------------------------------+ 
C     *ENTRY        PLIST                                                  | 
C                   PARM                    TOMBR            10            | 
C*-------------------------------------------------------------------------+ 

RPGの *ENTRYパラメータの受け渡しでは
パラメータ値を変更して戻すと相手側のプログラムにも
変更値が戻されるようになっていてRPGの開発者は
よくご存知であると思うがこれは一般的に開発言語では
むしろ例外的なことでありパラメータそのものは
値を渡すだけなので渡した側のプログラムに
パラメータ値が反映されて戻ることはあり得ない。
 
RPGのプロシージャーの場合も他言語と同様であり
プロシージャーのパラメータ値に値が反映されて
戻ることはない。
しかし意図的にパラメータに値を戻したい場合がある。
そのようなときには他言語ではパラメータを
ポインタとして渡す手法が用いられる。
ポインタであればそこからの値を変更してやれば
ポインタ自体は変わっていなくてもその位置(ポインタ)からの
値を変えることができるからである。

このことを示す例を紹介しよう。
プロシージャーを使う場合に複数の値を戻したいときに
役に立つはずである。

[ RPG: TESTPROC2 ]

ソースはこちらから

0001.00 H DFTNAME(TESTPROC2) DATEDIT(*YMD/) BNDDIR('QC2LE')                           
0002.00 F********** プロシージャーのテスト (2)*********************************       
0003.00 F*                                                                            
0004.00 F**********************************************************************       
0005.00                                                                               
0006.00  * CRTBNDRPG PGM(MYLIB/TESTPROC2) SRCFILE(MYSRCLIB/QRPGLESRC) DFTACTGRP(*NO)  
0007.00  *  ACTGRP(*NEW) DBGVIEW(*SOURCE) AUT(*ALL)                                   
0008.00                                                                               
0009.00  *-------------------------------------------------------------------*        
0010.00  *  2021/10/28 : 作成                                                         
0011.00  *-------------------------------------------------------------------*        
0012.00  *( 作業変数 )                                                                
0013.00 D TRUE#           S              4B 0 INZ(0)                                  
0014.00 D FALSE#          S              4B 0 INZ(-1)                                 
0015.00 D DATA1           S              7A   INZ('AA11111')                          
0016.00 D DATA2           S              7A   INZ('BB22222')                          
0017.00 D DATA2_P         S               *   INZ(%ADDR(DATA2))                       
0018.00 D ANS             S              1A                                           
0019.00                                                                               
0020.00 D*( MYPROC        のプロトタイプ宣言 )                                        
0021.00 D MYPROC          PR             4B 0                                         
0022.00 D  DATA1                         7A   Value                                   
0023.00 D  DATA2                          *   Value OPTIONS(*NOPASS)                  
0024.00                                                                     
0025.00 C*( メイン・ルーチンの始まり )                                      
0026.00  /FREE                                                              
0027.00     IF MYPROC(DATA1: DATA2_P) = FALSE#;                             
0028.00        DSPLY ('DATA1=' + DATA1);                                    
0029.00        DSPLY ('DATA2=' + DATA2);                                    
0030.00        DSPLY ' 結果を確認してください。 '  '' ANS;                  
0031.00     ENDIF;                                                          
0032.00  /END-FREE                                                          
0033.00 C                   SETON                                        LR 
0034.00 C                   RETURN                                          
0042.00  *********************************************************          
0043.00  *   MYPROC:     メッセージを現在の CALLSTACK に送信     *          
0044.00  *********************************************************          
0045.00  *---( MYPROC    PROCEDURE  ここから )------------------------*     
0046.00 P MYPROC          B                   EXPORT                        
0047.00 D                 PI             4B 0                               
0048.00 D  DATA1                         7A   Value                       
0049.00 D  DATA2_P                        *   value OPTIONS(*NOPASS)      
0050.00                                                                   
0051.00 D DATA2           S              7A   BASED(DATA2_P)              
0052.00                                                                   
0053.00  /FREE                                                            
0054.00    DATA1 = 'XX22222';                                             
0055.00    DATA2 = 'YY22222';                                             
0056.00  /END-FREE                                                        
0057.00 C                   RETURN                  FALSE#                
0058.00 P                 E                                               
0059.00  *---( MYPROC       PROCEDURE  ここまで )------------------------*


  

[コンパイル]

CRTBNDRPG PGM(MYLIB/TESTPROC2) SRCFILE(MYSRCLIB/QRPGLESRC) DFTACTGRP(*NO) ACTGRP(*NEW) DBGVIEW(*SOURCE) AUT(*ALL)

[解説]
プロシージャー : MYPROC には2つのパラメータがあり
ひとつは値を渡していてもうひとつのパラメータはポインタを渡している。

0020.00 D*( MYPROC        のプロトタイプ宣言 )                                        
0021.00 D MYPROC          PR             4B 0                                         
0022.00 D  DATA1                         7A   Value                                   
0023.00 D  DATA2                          *   Value OPTIONS(*NOPASS) 

最初には初期値をそれぞれにセットしておく

0015.00 D DATA1           S              7A   INZ('AA11111')                          
0016.00 D DATA2           S              7A   INZ('BB22222')

これを受取ったプロシージャーが側では両方とも次のように更新して戻す。

0053.00  /FREE                                                            
0054.00    DATA1 = 'XX22222';                                             
0055.00    DATA2 = 'YY22222';                                             
0056.00  /END-FREE                                                        
0057.00 C                   RETURN                  FALSE#

受取った値は次の命令で表示される。

0028.00        DSPLY ('DATA1=' + DATA1);                                    
0029.00        DSPLY ('DATA2=' + DATA2);                                    
0030.00        DSPLY ' 結果を確認してください。 '  '' ANS; 

またこのDSPLY命令の使い方にも注目して欲しい。
フリーメフォーマットでDSPLY命令を使うと見やすくわかりやすくなる。
実行結果は次のようになる。

                        プログラム・メッセージの表示
                      
DSPLY  DATA1=AA11111                                 
DSPLY  DATA2=YY22222                                
DSPLY   結果を確認してください。                   
                                                     
 応答を入力して,実行キーを押してください。          
   応答 . . .                                        
                                                     
                                                     
F3= 終了    F12= 取消し                              

[解説]

DATA1は 最初の AA11111 の値のままであり変化はないが
ポインタ渡しにしたDATA2 は YY22222 と

0055.00    DATA2 = 'YY22222'; 

で更新した値が反映されている。
このように結果が成功したか失敗したかは結果を RETURN 命令で
RETURN TRUE# や FALSE# で戻して更新した値はパラメータに反映して
戻すというやり方はオープン系の開発言語でよく行われる手法である。

プロシージャーのパラメータはポインタであればパラメータ値の変更を反映させることができる

ILE-RPGでもポインタ渡しをこのように有効に活用することが望ましい。・