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 で扱うときに
必要となってくる。
高度な使用方法ではあるがポインターを理解する上でよいサンプルである。
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
に置換えることができる。