CL

95. 文字形式の PACK を数字に変換するには ?

i5/OS Ver7.2 から CLP の組込み関数として
%CHAR, %DEC, *INT, %CHECK などいろいろな組込み関数が追加されている。
これらの使用方法はいずれ紹介することにして今回のテクニックは
文字形式の PACK 10進数をどのようにして
数字の PACK 10進数に変換するかということである。

どういうことかと言うと、

             DCL        VAR(&CHAR03) TYPE(*CHAR) LEN(3) +
                          VALUE(X'01240F')                                     

と定義されている文字の PACK 10進数(ここでは値は 1240 ) の 3 バイト文字を

             DCL        VAR(&PACK05) TYPE(*DEC) LEN(5 0)

という長さ 5,0 の PACK 10進数に入れるにはどのようにすればよいかを
考えてみよう。
もちろん、

             CHGVAR   &PACK05 &CHAR03

という単純な CHGVAR では、変換してくれないどころか

  
	CPF0818 : 値を受け入れ側のタイプに変換することができない 。

という変換エラーとなってしまう。
これは Ver7.2 で追加された組込み関数を駆使しても解決することはできないし
Ver7.2 でも CPF0818 の変換エラーは発生する。
この問題はポインターという概念を良く理解していれば
ポインターによる解決方法が直ちに思い浮かぶはずである。
ポインターというと何やら難しく感じるかも知れないが
ポインターとはメモリ空間の番地のことである。
凡そプログラムで処理する変数とは、その変数の開始位置(ポインター) + 長さ によって
定義されている。そしてその型とともに変数がどのようなものであるか決まる。
今回は異なる型の変数の中にある値をコピーしたいということであるが
ポインターということに絞ればどのような変数どうしであっても
ポインターという要素は共通して持っているものである。
そこで次のような定義を行う。

     DCL        VAR(&CHAR03) TYPE(*CHAR) LEN(3) +           
                  VALUE(X'01240F')                          
     DCL        VAR(&CHAR03_P) TYPE(*PTR) ADDRESS(&CHAR03 0)

新たに定義した &CHAR03_P という変数は 変数 &CHAR03 のポインター、つまり
&CHAR03 の値が保管されている場所の開始位置を示している。
次に

     DCL        VAR(&PACK05_P) TYPE(*PTR)                     
     DCL        VAR(&PACK05) TYPE(*DEC) STG(*BASED) LEN(5 0) +
                  BASPTR(&PACK05_P) 

まず &PACK05_P とはポインターである。
そして &PACK05 という長さ(5,0) の PACK 10進数は &PACK05_P というポインターを
開始位置とする PACK 10進数として定義されている。
従って &PACK05_P というポインターの値が決まらないことには &PACK05 の実体も
決まらないことになる。

そこで &PACK05_P&CHAR03_P というポインターを入れてみよう。
すると &PACK05 という PACK 10進数は &PACK05_P, つまり &CHAR_03_P
開始位置(ポインター)として定義される変数ということになり、
&PAC05 の PACK 10進数としての値は 1240 となる。
つまり &CHAR03&PACK05 という PACK 10進数として置換えて解釈したことになる。
これらの演算で値を移動したりコピーしたりはしていないのだが、ポインター操作によって
PACK 10進数の値を取得することができるようになったわけである。

まだ納得できない方も次の CLP ソースを眺めてポインター操作による演算の方法を
習得して欲しい。
文字形式の PACK はコマンドのパラメータや API の結果の値を CLP で扱うときに
必要となってくる。
高度な使用方法ではあるがポインターを理解する上でよいサンプルである。

【サンプル・ソース: TESTPACK 】
0001.00              PGM                                                       
0002.00 /*-------------------------------------------------------------------*/
0003.00 /*   TESTPACK  : PACK 十進数から文字列への変換                       */
0004.00 /*                                                                   */
0005.00 /*   2017/02/13  作成                                                */
0006.00 /*-------------------------------------------------------------------*/
0007.00              DCL        VAR(&CHAR03) TYPE(*CHAR) LEN(3) +              
0008.00                           VALUE(X'01240F')                             
0009.00              DCL        VAR(&CHAR03_P) TYPE(*PTR) ADDRESS(&CHAR03 0)   
0010.00              DCL        VAR(&PACK05_P) TYPE(*PTR)                      
0011.00              DCL        VAR(&PACK05) TYPE(*DEC) STG(*BASED) LEN(5 0) + 
0012.00                           BASPTR(&PACK05_P)                            
0013.00              DCL        VAR(&CHAR5) TYPE(*CHAR) LEN(5)                 
0014.00              DCL        VAR(&SURYO) TYPE(*DEC) LEN(5 0)                
0015.00                                                                        
0016.00              /*( 文字 3 桁 (PACK05C)->PACK(5, 0) */                    
0017.00              CHGVAR     VAR(&PACK05_P) VALUE(&CHAR03_P)                
0018.00              /*( PACK(5,0) -> 文字 5 桁 (CHAR05) )*/                   
0019.00              CHGVAR     VAR(&CHAR5) VALUE(&PACK05)                     
0020.00              SNDPGMMSG  MSG('SURYO=' *CAT &CHAR5) MSGTYPE(*DIAG)       
0021.00              RETURN
0022.00                    
0023.00              ENDPGM                                         
【解説】
     CHGVAR     VAR(&PACK05_P) VALUE(&CHAR03_P)   

によって
変数 &PACK05 のポインター(開始位置)は
変数 &CHAR03 のポインターと同じになるので
変数 &PACK05 の値は 1240 となる。
次に 

     CHGVAR     VAR(&CHAR5) VALUE(&PACK05)

によって PACK 10進数であっても CHGVAR によって
単純に文字列 &CHAR05 に置換えることができる。