コマンド

35. 複合パラメータから値を取得するには (2)

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は次のようになる。

【 サンプルCLP:TESTCMD2CL 】




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で変数として使ってきたものは実はポインタを表現していたのかもしれない。
そう思うとボインタを身近なものとして感じて頂ければ幸いである。