「プロシージャーを公開する」ではプロシージャーを含むプログラムを
CRTRPGMOD + SRVSRVPGM
によってサービス・プログラムを生成した。
つまり本来はプログラムとして動作していたモジュールのソースを使って
サービス・プログラム(*SRVPGM)を作成したのだがこれでよいのだろうか?
始めからサービス・プログラム(*SRVPGM)として開発する場合は
少し様子がちがう。
RPGソース: TESTPROC には次のようなメイン・ルーチンが存在していたことを
思い出して欲しい。
: 0025.00 C*( メイン・ルーチンの始まり ) 0026.00 C CALLP SNDPGMMSG(MSR(1)) 0027.00 C SETON LR 0028.00 C RETURN 0029.00 C*( メイン・ルーチンの終わり ) :
ところで
CRTRPGMOD + SRVSRVPGM
としてサービス・プログラム(*SRVPGM)を生成する場合はこのメイン・ルーチンは
全く機能していないはずである。
従ってサービス・プログラム(*SRVPGM)として作成する場合のソースは
次のようになる。
[ サービス・プログラム: TESTSRV ]
ソースはこちらから
0001.00 H NOMAIN 0002.00 F********** サービス・プログラム ************************************** 0003.00 F* 0004.00 F********************************************************************** 0005.00 0006.00 * CRTRPGMOD OBJ(QTEMP/TESTSRV) SRCFILE(R610SRC/QRPGLESRC) 0007.00 * DBGVIEW(*SOURCE) AUT(*ALL) 0008.00 0009.00 * CRTSRVPGM SRVPGM(OBJLIB/TESTSRV) MODULE(QTEMP/TESTSRV) SRCFILE(SRCLIB/QSR 0010.00 * VSRC) ACTGRP(*CALLER) AUT(*ALL) 0011.00 0012.00 *-------------------------------------------------------------------* 0013.00 * 2020/08/09 : 作成 0014.00 *-------------------------------------------------------------------* 0015.00 *( 作業変数 ) 0016.00 D MSR S 80 DIM(1) CTDATA PERRCD(1) 配列 0017.00 D AR S 1A DIM(256) 0018.00 D N S 4S 0 0019.00 0020.00 **************************************************** 0021.00 * プロシージャーのプロトタイプ宣言 * 0022.00 **************************************************** 0023.00 D*( SNDPGMMSG のプロトタイプ宣言 ) 0024.00 D SNDPGMMSG PR 0025.00 D MSG 3000A Value 0026.00 D MSGTYPE_IN 10A value OPTIONS(*NOPASS) 0027.00 D CALLSTACKC_IN 10I 0 CONST OPTIONS(*NOPASS) 0028.00 0029.00 **************************************************** 0030.00 * プロシージャーの本体の記述 * 0031.00 **************************************************** 0032.00 ********************************************************* 0033.00 * SNDPGMMSG: メッセージを現在の CALLSTACK に送信 * 0034.00 ********************************************************* 0035.00 *---( SNDPGMMSG PROCEDURE ここから )------------------------* 0036.00 P SNDPGMMSG B EXPORT 0037.00 D PI 0038.00 D MSG 3000A Value 0039.00 D MSGTYPE_IN 10A value OPTIONS(*NOPASS) 0040.00 D CALLSTACKC_IN 10I 0 CONST OPTIONS(*NOPASS) 0041.00 0042.00 D APIERR DS 0043.00 D GETBYT 1 4B 0 INZ(160) 0044.00 D AVLBYT 5 8B 0 INZ(0) 0045.00 D MSGID 9 15 0046.00 D MSGDTA 17 160 0047.00 0048.00 D QMHSNDPM PR ExtPgm('QMHSNDPM') 0049.00 D MSGID 7A CONST 0050.00 D MSGFILE 20A CONST 0051.00 D MSGDATA 6000A CONST OPTIONS(*varsize) 0052.00 D MSGDATALEN 10I 0 CONST 0053.00 D MSGTYPE 10A CONST 0054.00 D CALLSTACKE 10A CONST 0055.00 D CALLSTACKC 10I 0 CONST 0056.00 D MSGKEY 4A 0057.00 D APIERR LIKEDS(APIERR) 0058.00 D OPTIONS(*VARSIZE) 0059.00 D PARMS S 4S 0 0060.00 D MSGKEY S 4A 0061.00 D CALLSTACKC S 10I 0 INZ(1) 0062.00 D MSGTYPE S 10A INZ('*DIAG ') 0063.00 0064.00 C EVAL PARMS = %PARMS() 0065.00 C SELECT 0066.00 C WHEN PARMS = 1 0067.00 C WHEN PARMS = 2 0068.00 C EVAL MSGTYPE = MSGTYPE_IN 0069.00 C WHEN PARMS = 3 0070.00 C EVAL CALLSTACKC = CALLSTACKC_IN 0071.00 C EVAL MSGTYPE = MSGTYPE_IN 0072.00 C ENDSL 0073.00 /FREE 0074.00 QMHSNDPM('CPF9897':'QCPFMSG *LIBL':MSG: 0075.00 %LEN(%TRIM(MSG)):MSGTYPE:'*PGMBDY': 0076.00 CALLSTACKC:MSGKEY:APIERR); 0077.00 /END-FREE 0078.00 C RETURN 0079.00 P E 0080.00 *---( SNDPGMMSG PROCEDURE ここまで )------------------------*
[解説]
サービス・プログラムなのでメイン・ルーチンはない。
それどころか
0001.00 H NOMAIN
としているのはRPGサイクルのモジュールも不要として除去されている。
若い開発者はご存知ないと思うがRPGはそのままコンパイルすると
自動的にRPGサイクルなるメイン・モジュールがコンパイラーによって
挿入される。
VisualBASICやVC++にも実はメイン・ルーチンはある。
それはこっそりとMicrosoftによってメイン・ルーチンが挿入されているに
過ぎない。
RPGの場合も同じで H NOMAIN はメイン・ルーチンの挿入を拒否している。
*INZSR という特殊な最初だけ実行されるサブ・ルーチンも実は
RPGサイクルの一部なので H NOMAIN を指示すると *INZSRサブ・ルーチンは
使えなくなるので念のため注意をされたい。
このように最初からサービス・プログラムの生成の基となるRPGソースには
メイン・ルーチンは記述しないのが基本である。
このソースから
CRTRPGMOD + CRTSRVPGM
を行えばよい。
これでサービス・プログラムの開発方法も理解して頂けたことと思う。