「プロシージャーを公開する」ではプロシージャーを含むプログラムを
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
を行えばよい。

これでサービス・プログラムの開発方法も理解して頂けたことと思う。
