2つ以上のパラメータから成る複合パラメータの取得の方法について
先に紹介したがここではもう少し高度なテクニックを必要とする例について紹介する。
2つめのパラメータが数字である場合である。
プリンターの開始2 (TESTCMD2) 選択項目を入力して,実行キーを押してください。 フォント: 種類 . . . . . . . . . . . . *DEFAULT サイズ . . . . . . . . . . . *CALC 4-36, *CALC
[解説]
複合パラメータ: フォントは種類(14バイト) + サイズ(2バイトの数字)から成る。
従ってこのコマンドを処理するCLPでは
PGM PARM(&FONTINFOP) /*-------------------------------------------------------------------*/ /* TESTCMD2 : ブリンターの開始 2 */ /*-------------------------------------------------------------------*/ DCL VAR(&FONTINFOP) TYPE(*CHAR) LEN(18)
のようにして 14 + 2 + 2(パラメータ数) = 18バイトの変数: &FONTINFOP を受取り変数として定義する。
パラメータ数が 1の場合はこれまでと同じで
IF COND(%BIN(&PRMSU) *EQ 1) THEN(DO) CHGVAR VAR(&FONT) VALUE(%SST(&FONTINFOP 3 14)) ENDDO
となるのだが後続の2桁の数字を取得することが難しい
DCL VAR(&FTSIZE) TYPE(*DEC) LEN(2 0)
のように「サイズ」を数字として定義したのでは
CHGVAR VAR(&FTSIZE) VALUE(%SST(&FONTINFOP 3 17))
として &FTSIZEを取得しようとすると &FTSIZEは文字変数ではないので文法エラーとなってしまう。
そこで
DCL VAR(&FLD2) TYPE(*CHAR) LEN(2) : CHGVAR VAR(&FLD2) VALUE(%SST(&FONTINFOP 3 17)) CHGVAR VAR(&FTSIZE) VALUE(&FLD2)
としても CHGVAR VAR(&FTSIZE) VALUE(&FLD2)は実行時のエラーとなってしまう。
&FLD2にはパック形式の数字が保管されるのでそのままMOVEはできない。
パック形式の数字をゾーン10進数に変換する関数があればいいのだが
見つからないのでこの方法もできない。
そこで紹介するのがポインタによる処理である。
CLPでもポインタを使うことができるようになっているので
DCL VAR(&FONTINFOB) TYPE(*CHAR) LEN(18) DCL VAR(&FTSIZE_P) TYPE(*PTR) ADDRESS(&FONTINFOB 16) DCL VAR(&FTSIZE) TYPE(*DEC) STG(*BASED) LEN(2 0) + BASPTR(&FTSIZE_P)
として定義する。
これは &FONTINFOB という18バイトの文字変数に対して
&FTSIZE_P は &FONTINFOBの 16バイトをオフセット(変数の始まり:開始位置)とする
ポインタとして定義している。
そして &FTSIZE という2桁の数字変数はこの &FTSIZE_Pというポインタを基底とする変数である。
つまりは &FTSIZEは &FONTINFOB の16バイト目からの2バイトを開始位置とする
変数であることになる。
そこで
CHGVAR VAR(&FONTINFOB) VALUE(&FONTINFOP)
として &FONTINFOBに &FONTINFOの値を入れると
&FTSIZEには求める「サイズ」を数として取得することができる。
これをまとめるとCLPは次のようになる。
0001.00 PGM PARM(&FONTINFOP) 0002.00 /*-------------------------------------------------------------------*/ 0003.00 /* TESTCMD2 : ブリンターの開始 2 */ 0004.00 /*-------------------------------------------------------------------*/ 0005.00 DCL VAR(&FONTINFOP) TYPE(*CHAR) LEN(18) 0006.00 DCL VAR(&FONTINFOB) TYPE(*CHAR) LEN(18) 0007.00 DCL VAR(&FONTINFO) TYPE(*CHAR) LEN(16) 0008.00 DCL VAR(&PRMSU) TYPE(*CHAR) LEN(2) /* 2 進数 */ 0009.00 DCL VAR(&FONT) TYPE(*CHAR) LEN(14) 0010.00 DCL VAR(&FTSIZE_P) TYPE(*PTR) ADDRESS(&FONTINFOB 16) 0011.00 DCL VAR(&FTSIZE) TYPE(*DEC) STG(*BASED) LEN(2 0) + 0012.00 BASPTR(&FTSIZE_P) 0013.00 DCL VAR(&FLD2) TYPE(*CHAR) LEN(2) 0014.00 DCL VAR(&FTSIZEC) TYPE(*CHAR) LEN(2) 0015.00 DCL VAR(&FLD8) TYPE(*CHAR) LEN(8) 0016.00 0017.00 /*( FONTINFO パラメータの取得 )*/ 0018.00 CHGVAR VAR(&FONTINFOB) VALUE(&FONTINFOP) 0019.00 CHGVAR VAR(&PRMSU) VALUE(%SST(&FONTINFOP 1 2)) 0020.00 IF COND(%BIN(&PRMSU) *EQ 1) THEN(DO) 0021.00 CHGVAR VAR(&FONT) VALUE(%SST(&FONTINFOP 3 14)) 0022.00 ENDDO 0023.00 ELSE CMD(DO) 0024.00 CHGVAR VAR(&FONT) VALUE(%SST(&FONTINFOP 3 14)) 0025.00 CHGVAR VAR(&FLD8) VALUE(&FTSIZE) 0026.00 CHGVAR VAR(&FTSIZEC) VALUE(%SST(&FLD8 6 2)) 0027.00 ENDDO 0028.00 CHGVAR VAR(&FONTINFO) VALUE(&FONT *CAT &FTSIZEC) 0029.00 0030.00 SNDPGMMSG MSG('FONTINFO=' *CAT &FONTINFO) + 0031.00 MSGTYPE(*DIAG) 0032.00 ENDPGM
ここでは複合パラメータの数字の処理を例に挙げるとともにCLPにおけるポインタの処理を紹介した。
CLPにおいてもポインタを使うと処理は柔軟となり応用範囲が広がる。
ポインタというと何やら難しそうであるがポインタとは変数の場所(開始位置)を示す概念である。
私達が日常的に使っている変数とは
変数 = ポインタ(開始位置) + 長さ
として定義されている。
つまりすべての変数はどこかの場所から
xxバイトの長さの分が確保されて変数として定義される。
すべての変数はポインタと呼ばれる開始位置があるはずである。
そう考えるとポインタとは難しい概念ではない。
参考までに C言語ではある変数 : VALUE のポインタは &VALUE のように
前に文字「&」を付加して表現する。
CLPで変数を一般的に &VALUEのように「&」をつけて表現するのは
決して偶然ではなく IBM による意図的なものであると思われる。
CLPで変数として使ってきたものは実はポインタを表現していたのかもしれない。
そう思うとボインタを身近なものとして感じて頂ければ幸いである。