複数プロシージャーのあるモジュール例

ここで、複数プロシージャー・モジュールの例を見てみます。 この「ミニ・アプリケーション・プログラム」では、勘定が遅れているすべての得意先の 報告書を作成するために、プログラム ARRSRPT を作成しています。 モジュールとして基本報告書を作成するので、必要な場合には他のモジュール とバインドすることができます。 このモジュールに必要な次の 2 つのメインタスクがあります。

  1. 得意先ファイルからの勘定のレコードが滞納しているかどうかを判別する。
  2. データを報告書に適した様式に様式設定する。

各タスクをサブプロシージャーとしてコーディングすることを決定します。 概念的には、モジュールは 図 17 に示されたものと類似したものになります。

図 17. ARRSRPT モジュールの構成要素

ここで、図 18 に示されている最初のサブプロシージャー InArrears を考えてみます。InArrears は、現行レコードが滞納中であるかどうかを調べるためにメイン ・プロシージャーによって呼び出されます。

ヒント

グローバル・フィールドを使用するサブプロシージャーをコーディングする 時には、グローバルである項目を表示する命名規則を確立する必要がある場合 があります。 この例では、大文字のフィールド名は DDS フィールドを指示して います。 別のオプションは、グローバルの有効範囲を指示する、接頭部 'g_' または 何か他のストリングとなります。

レコードが滞納中である場合には、サブプロシージャーはメイン・プロシージャー に '1' を戻します。

図 18. サブプロシージャー InArrears のソース
 //--------------------------------------------------------------
 // InArrears
 //
 // パラメーター: (なし)
 // グローバル:   DUEDATE, AMOUNT, CurDate
 //
 // 戻り:         得意先が滞納中であれば '1'
 //--------------------------------------------------------------
P InArrears       B                      1 
D InArrears       PI             1A      2 
 // ローカルの宣言
D DaysLate        S             10I 0    3 
D DateDue         S               D      3 
 // プロシージャー本体
 /free
     DateDue = %date (DUEDATE: *ISO);
     DaysLate = %diff (CurDate: DateDue: *d);

     // 入力ファイルの中のデータは別のタイプの
     // コンピューターからのデータで、AMOUNTC フィールドは、
     // 数値を含む文字ストリングです。
     // このストリングは、印刷の場合は数値の AMOUNT フィールドに
     // 変換しなければなりません。
     AMOUNT = %dec(AMOUNTC : 31 : 9);
     if DaysLate > 60 AND AMOUNT > 100.00;
        return '1';                      4 
     endif;
     return '0';                         4   5 
 /end-free
P InArrears       E                      1 

図 18 はすべてのサブプロシージャーに共通な主要な要素を 示しています。

 1 
すべてサブプロシージャーはプロシージャー仕様書で始まり、終わります。
 2 
開始プロシージャー仕様書 (プロシージャー仕様書の 24 桁目に B) の後に、プロシージャー・インターフェース 定義をコーディングします。 戻り値 (ある場合) は PI 仕様書で 定義します。 PI 仕様書の後にパラメーターがリストされます。
 3 
サブプロシージャーで使用される変数またはプロトタイプは、 プロシージャー・インターフェース定義の後に定義します。
 4 
戻り値 (指定した場合) は、RETURN 命令のある呼び出し元に戻されます。
 5 
そのレコードが滞納中でない場合は、サブプロシージャーは '0' をメイン・プロシージャーに 戻します。

すべてのサブプロシージャーの場合、およびプロトタイプ入り口パラメーターの あるメイン・プロシージャーの場合も、プロシージャー・インターフェースを 定義する必要があります。 プロシージャー・インターフェース定義は、プロシージャーの定義 内のプロトタイプ情報の反復です。 これは、プロシージャーの入り口パラメーターを定義するために使用されます。 プロシージャー・インターフェース定義は、プロシージャーの内部定義が 外部定義 (プロトタイプ) と一貫性があることを確認するためにも使用されます。 InArrears の場合には、入り口パラメーターはありません。

図 19 に示す次のサブプロシージャー FmtCust について考えてみます。 FmtCust は、 レコードの関連フィールドを最終報告書の出力レコードに様式設定するために、 ARRSRPT によって呼び出されます。 (レコードは滞納している勘定を表しています。) FmtCust は、グローバル・データを使用しているので、入力パラメーターをも っていません。これはデータを 2 つの出力フィールドに様式設定します。名前用に 1 つと アドレス用に 1 つです。

図 19. サブプロシージャー FmtCust のソース
 //--------------------------------------------------------------
 // FmtCust は、CUSTNAME、CUSTNUM、STREETNAME などを
 // 読み取り可能な様式に様式設定します。
 //
 // パラメーター: Name     (出力)
 //               Address  (出力)
 // グローバル:   CUSTNAME、CUSTNUM、STREETNUM、STREETNAME、CITY
 //               STATE、ZIP
 //--------------------------------------------------------------

P FmtCust         B
D FmtCust         PI
D  Name                        100A
D  Address                     100A

 /free

     //--------------------------------------------------------------
     // CUSTNAME と CUSTNUM は次のように様式設定されます。
     // A&P Electronics     (得意先番号 157)
     //--------------------------------------------------------------
     Name = CUSTNAME + ' ' + '(得意先番号 '
                        + %char(CUSTNUM) + ')';

     //--------------------------------------------------------------
     //   FmtAddr プロシージャーを呼び出してアドレスを処理します。
     //--------------------------------------------------------------

 Address = FmtAddress (STREETNUM : STREETNAME :
                              CITY : STATE : ZIP);
 /end-free
P FmtCust         E

最後に、このアプリケーション・プログラムの最後のサブプロシージャー FmtAddr を考えてみます。 図 17 に示すように、FmtAddr は ARRSRPT モジュールにはないことに注意してください。 FmtAddr は FMTPROCS という別のモジュールに入れることにしました。 FMTPROCS は、他のモジュールで必要となる変換プロシージャーを入れるユーティリティー・モジュールです。

図 20 に、モジュール FMTPROCS のソースを示します。 これはプロトタイプ・プロシージャーであるため、 使用可能なプロトタイプが必要です。プロトタイプは共用できるので、プロトタイプを /COPY ファイルに 入れました。

図 20. サブプロシージャー FmtAddr を含む、モジュール FMTPROCS のソース
    //=================================================================
    // モジュール FMTPROCS のソース。このモジュールは NOMAIN という
    // キーワードが示しているとおり、メイン・プロシージャーを持ちません。
    //=================================================================
   H NOMAIN
    //-----------------------------------------------------------------
    // プロトタイプ・プロシージャーを持つモジュールのそれぞれについて
    // プロトタイプが使用可能である必要があります。
    // /COPY を指定すると、FmtAddr 用のプロトタイプを呼び込みます。
    //-----------------------------------------------------------------
   D/COPY QRPGLESRC,FMTPROC_P
   P FmtAddr         B                     EXPORT
   D FmtAddr         PI           100A     VARYING
   D   streetNum                   10I 0   CONST
   D   streetName                  50A     CONST
   D   city                        20A     CONST
   D   state                       15A     CONST
   D   zip                          5P 0   CONST
    /free
        
        //--------------------------------------------------------------
        // STREETNUM、STREETNAME、CITY、STATE、および ZIP は次のように
        // 形式設定されます
        //   27 Garbanzo Avenue, Smallville IN 51423
        //--------------------------------------------------------------
        return  %char(streetNum) + ' ' + %trimr(streetName)
                      + ', ' + %trim(city) + ' ' + %trim(state)
                     + ' ' + %editc(zip : 'X');
   P FmtAddr         E

FMTPROCSNOMAIN モジュールです。 つまり、サブプロシージャーだけから構成されていて、メイン・プロシージャーはありません。 NOMAIN モジュールは、モジュールのために作成されるサイクル・コードがない ために、高速でコンパイルされ、少ない記憶域しか必要としません。 制御仕様書で NOMAIN キーワードをコーディングすることによって NOMAIN モジ ュールを指定します。 NOMAIN モジュールの詳細については、プログラムの作成を参照してくだ さい。