SBMJOB時のCALL 引数の仕様
SBMJOB時のCALL 引数の仕様には以下の言及がある。しかし、IBMi(V7R2,V7R5で検証)実際の挙動は少し違ったりする。
例10:パラメーターのタイプおよび長さの省略時値を使用する新規ジョブでのプログラムの呼び出し
SBMJOBコマンドの実行時に定数に変換されます。
...中略...
文字定数が,(変数値の長さが32未満の場合,左寄せで,ブランクが埋め込まれて)渡されます。
...中略...
呼び出し先プログラムで最初のパラメーターが50バイトとして渡されることが予期されている場合,33バイト目から50バイト目までが参照されると,問題が生じます。
...中略...
値は数値定数に変換され,合計15桁,小数部5桁のパック10進数値として渡されます。
例えば以下の様な CLLE コーディングの時
PGM
DCL VAR(&@PSTR1 ) TYPE(*CHAR) LEN(01 ) /* 文字列 */
DCL VAR(&@PSTR2 ) TYPE(*CHAR) LEN(50 ) /* 文字列 */
DCL VAR(&@PDEC1 ) TYPE(*DEC ) LEN(08 0) /* 数値 */
CHGVAR VAR(&@PSTR1 ) VALUE('+
U+
')
CHGVAR VAR(&@PSTR2 ) VALUE('+
ABCDEFGHIJ+
KLMNOPQRST+
abcdefghij+
klmnopqrst+
uvwxyzZYXW+
')
CHGVAR VAR(&@PDEC1 ) VALUE(+
12345678+
)
SBMJOB CMD( +
CALL USHIDA/USC_SBMJ12 +
PARM( +
&@PDEC1 +
&@PSTR1 +
&@PSTR2 +
) +
) JOBQ(QBATCH)
PGM PARM( +
&@PDEC1 +
&@PSTR1 +
&@PSTR2 +
) +
DCL VAR(&@PSTR1 ) TYPE(*CHAR) LEN(01 ) /* 文字列 */
DCL VAR(&@PSTR2 ) TYPE(*CHAR) LEN(50 ) /* 文字列 */
DCL VAR(&@PDEC1 ) TYPE(*DEC ) LEN(08 0) /* 数値 */
DMPCLPGM
SNDPGMMSG MSG('&@PSTR1 を参照 ')
IF COND(&@PSTR1 *EQ ' ') THEN(DO)
ENDDO
SNDPGMMSG MSG('&@PSTR2 を参照 ')
IF COND(&@PSTR2 *EQ ' ') THEN(DO)
ENDDO
SNDPGMMSG MSG('&@PDEC1 を参照 ')
IF COND(&@PDEC1 *EQ 1) THEN(DO)
ENDDO
ENDPGM
文字列引数の挙動
この言及によると &@PSTR1
と &@PSTR2
は両方とも 32バイト 定数に変換され、USC_SBM12
はエラーを発生させそうだが、実際はそうではなく。ダンプを見る限り、文字列引数は、綺麗に渡されている。
変数 タイプ 長さ 値 16 進値
*...+....1....+....2....+ * . . . + . . . . 1 . . . . + . . . . 2 . . .
&@PDEC1 *DEC 8 0 1234567
&@PSTR1 *CHAR 1 'U' E4
&@PSTR2 *CHAR 50 'ABCDEFGHIJKLMNOPQRSTabcde' C1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E381828
+26 'fghijklmnopqrstuvwxyzZYXW' 86878889919293949596979899A2A3A4A5A6A7A8A9E9E
数値引数の挙動
一方数値はというと &@PDEC1
は言及通り 15桁-小数部5桁のパック10進数の定数 に変換されており おかしな事 になっている。そのため USC_SBM12
は実際に次のような10進数エラーを発生する。
そしてこれを回避するには、受け取りパラメータを TYPE(*DEC) LEN(15 5)
で定義する必要がある。そうすれば、以下のように正しく数値が渡る。この辺りは、結構 IBM i 特有の魔物が潜んでいる事があるので気をつけましょう。