今回も小技をご紹介します。IBM i の CLLE(※以後 CLP も同じです) のお話です。
IBM i V7R4 TRxx くらいからでしょうか? CALL コマンド の PARM に引数型を指定して呼び出すことが出来る様になっています。
参考リンク
今回のサンプルコード
以下の様な CLLE サンプルコード です。この CLLE では次の RPGLE の
- Q250101R サンプルコード
-
Q250801R サンプルコード
を使用しております。
RPGLE は単純にパック10進数を受け取り DSPLY 命令で出力しております。
/*****************************************************************/
/* */
/* システム名 :Qiitaアドベントカレンダー */
/* サブシステム名 :2025 */
/* プログラム名 :パック10進数の引数指定 */
/* プログラムID : Q250801C1 */
/* 会 社 名 :株式会社中部システム */
/* */
/* 作 成 者 : CSC)Y.USHIDA */
/* 作 成 日 : 2025/11/20 */
/* テンプレート№: _______________ */
/* */
/* 変 更 者 : */
/* 変 更 日 : ____/__/__ */
/* */
/* プログラム特記事項 */
/* */
/* */
/* */
/*****************************************************************/
PGM
/*======================================*/
/*変数定義 */
/*======================================*/
DCL VAR(&P@PARM1 ) TYPE(*DEC ) LEN(003 0)
DCL VAR(&W@PARM1 ) TYPE(*DEC ) LEN(005 0)
DCL VAR(&C@PARM1 ) TYPE(*CHAR) LEN(003 ) STG(*DEFINED ) DEFVAR(&W@PARM1 )
/*======================================*/
/*初期処理 */
/*======================================*/
/*CL内のCALLはコンパイルエラーとなり指定できない*/
/* CALL PGM(Q250101R) PARM((&P@PARM1 (*DEC 5 0))) */
/*------------------------------------*/
/*SBMJOBでは使うことができる*/
/*------------------------------------*/
CHGVAR VAR(&W@PARM1 ) VALUE(-123 )
/*従来)SBMJOB制約で同型でもエラー*/
SBMJOB CMD( +
CALL PGM(Q250101R) PARM( &W@PARM1 ) +
) JOB(Q250801C11 )
CHGVAR VAR(&W@PARM1 ) VALUE(-234 )
/*従来)SBMJOB制約の暗黙型15P 5に合わせれば正常*/
SBMJOB CMD( +
CALL PGM(Q250801R) PARM( &W@PARM1 ) +
) JOB(Q250801C12 )
/*従来)文字列相当にキャストして渡す方法*/
CHGVAR VAR(&W@PARM1 ) VALUE(-345 )
SBMJOB CMD( +
CALL PGM(Q250101R) PARM( &C@PARM1 ) +
) JOB(Q250801C13 )
/*型指定で正常に実行される*/
CHGVAR VAR(&P@PARM1 ) VALUE(-456 )
SBMJOB CMD( +
CALL PGM(Q250101R) PARM((&P@PARM1 (*DEC 5 0))) +
) JOB(Q250801C14 )
WRKACTJOB SBS(QBATCH )
/*終了*/
CALLSUBR SUBR(@END)
/*====================================================================*/
/*終了処理 */
/*====================================================================*/
SUBR @END
/* 終了*/
RETURN
ENDSUBR
ENDPGM
CL内 での CALL コマンド PARM の型指定の扱い
CLLE での CALL コマンド PARM の型指定の扱いを見ていきます。
まず、CL 内で CALL コマンドの PARM 型指定を行うとコンパイルエラーとなります。
/* CL内のCALLはコンパイルエラーとなり指定できない */
/* CALL PGM(Q250101R) PARM((&P@PARM1 (*DEC 5 0))) */
* CPD08A4 40 パラメーター 0001 値はパラメーターのタイプと長さに合っていない
これはコマンドラインで型指定ができた様に、あくまでもリテラル値をパースする処理で、指定型へ合わせにいっているだけで、CLの様な動的な変数(参照やポインタ)をキャストしている訳ではないということなのでしょうね。
CL内 での SBMJOB コマンドでの CALL PARM の型指定の扱い
続いて SBMJOB を見ていきます。こちらは、コマンドラインと同様に、あくまで主体は SBMJOB であり、親のジョブから切り離され、CALLコマンドは、CL変数の参照を受け取ることが出来ません。従ってコマンドライン同様に、PARM の型指定をすることができます。恐らく内部的にはコマンドライン同様のパーサーが使用されているからでしょうか?
まずは、さきほどのサンプル CL を実行した結果は次のとおりになります。
(C G D F) 10 進数データ・エラーが起こった。(※1)
DSPLY 引数は「 -234.00000 」(※2)
DSPLY 引数は「 -345 」(※3)
DSPLY 引数は「 -456 」(※4)
従来の SBMJOB での CALL 引数
PARM の型指定を行わない、且つ RPGLE の引数の型が PACKED(5 :0) の場合サンプルでは次のコードを実行しております。
CHGVAR VAR(&W@PARM1 ) VALUE(-123 )
/*従来)SBMJOB制約で同型でもエラー*/
SBMJOB CMD( +
CALL PGM(Q250101R) PARM( &W@PARM1 ) +
) JOB(Q250801C11 )
結果は (C G D F) 10 進数データ・エラーが起こった。(※1) となります。
これは SBMJOB 制約で数値は 15P 5 と定数変換されるため、RPG 側の型が不一致で10進数エラーとなります。
次に RPGLE を SBMJOB 制約 PACKED(15 :5) に合わせる形した場合は正常に実行されます。
CHGVAR VAR(&W@PARM1 ) VALUE(-234 )
/*従来)SBMJOB制約の暗黙型15P 5に合わせれば正常*/
SBMJOB CMD( +
CALL PGM(Q250801R) PARM( &W@PARM1 ) +
) JOB(Q250801C12 )
結果は DSPLY 引数は「 -234.00000 」(※2) となります。
また、RPGLE の型を変更せずに行う方法として以下の方法があります。
DCL VAR(&W@PARM1 ) TYPE(*DEC ) LEN(005 0)
DCL VAR(&C@PARM1 ) TYPE(*CHAR) LEN(003 ) STG(*DEFINED ) DEFVAR(&W@PARM1 )
/*従来)文字列相当にキャストして渡す方法*/
CHGVAR VAR(&W@PARM1 ) VALUE(-345 )
SBMJOB CMD( +
CALL PGM(Q250101R) PARM( &C@PARM1 ) +
) JOB(Q250801C13 )
結果は DSPLY 引数は「 -345 」(※3) となります。
SBMJOB での CALL 引数型指定
従来は、SBMJOB で変数を渡す場合は、ある一定の制約や少し神経質になる部分がありましたが、コマンドラインと同様型指定にて、渡すことでシンプルに記述することが出来ます。記述は次のとおりになります。
/*型指定で正常に実行される*/
CHGVAR VAR(&P@PARM1 ) VALUE(-456 )
SBMJOB CMD( +
CALL PGM(Q250101R) PARM((&P@PARM1 (*DEC 5 0))) +
) JOB(Q250801C14 )
結果は DSPLY 引数は「 -456 」(※4) となります。
文字列における SBMJOB 制約も型指定を行うことで制約を受けない記述方法となるので、古い記述がある場合はリファクタリングを行うと良いでのではないでしょうか。