COBOL 処理パターン　外部サブプログラム呼ぶ

[「COBOL 処理パターン　テーブル展開」](https://qiita.com/mikomokaru-jpn/items/ffb340cb0d647fc56597)におけるマスターファイルの読み込みをサブプログラムで行う。

### 機能仕様
サブプログラムで顧客マスターファイルを読み込み、顧客マスターテーブルを作成する。

メインプログラムはサブプログラムから顧客マスターテーブルを取得する。
サブプログラムから戻り値を取得するには、メイン側で戻り値の領域を確保し、その参照を受け渡す方法をとる（引数の参照渡し）。

CALL GIVING により得られる戻り値は、サブルーチンが変数 RERURN-CODE に代入する値であり、これは数値のみしか扱えないので、一般的にはコンディションコードとして利用する。RERURN-CODE はシステムで宣言されたグローバル変数である。

### 入出力構成図

<img src="http://mikomokaru.sakura.ne.jp/cobol/5/cob05_01.png" alt="[cob05_01.png]" width="300">

### ソースコード
### メインプログラム
引数を指定してサブプログラムを呼び出すとき、サブプログラムが戻り値を設定する領域の参照渡を引数に指定する。

```
 IDENTIFICATION              DIVISION.
 PROGRAM-ID.                 MAIN01.

 ENVIRONMENT                 DIVISION.
 INPUT-OUTPUT                SECTION.
 FILE-CONTROL.
*入力ファイル 行順編成ファイル(テキストファイル)  
 SELECT  F1  ASSIGN  TO  "./R002.txt"
 ORGANIZATION IS LINE SEQUENTIAL
 ACCESS  MODE  IS  SEQUENTIAL.  
*出力ファイル 行順編成ファイル(テキストファイル)  
 SELECT  F2  ASSIGN  TO  "./R003.txt"
 ORGANIZATION IS LINE SEQUENTIAL
 ACCESS  MODE  IS  SEQUENTIAL.  

 DATA                        DIVISION.
 FILE                        SECTION.
* 入力ファイル
 FD  F1.
 01  F1R.
     05  CUST-CODE           PIC 9(04). 
     05  SALES               PIC 9(10).
* 出力ファイル
 FD  F2.
 01  F2R.
     05  CUST-CODE           PIC 9(04). 
     05  SALES               PIC 9(10).
     05  CUST-NAME           PIC X(20).

 WORKING-STORAGE             SECTION.
 01  END-FLG                 PIC 9(01).
 01  I                       PIC 9(02).
 01  RETURN-VALUE            PIC 9(03).
* 顧客マスターテーブル有効件数（戻り値）
 01 CUST-COUNT               PIC 9(02).
* 顧客マスターテーブル（戻り値）
 01 CUST-TABLE.
     05 CUSTOMER OCCURS 10 TIMES.
         10 CUST-CODE        PIC 9(04).
         10 CUST-NAME        PIC X(20).

 PROCEDURE                   DIVISION.
******************************************************************
* 主処理 
****************************************************************** 
 PERFORM INIT-RTN
 PERFORM LOOP-RTN UNTIL END-FLG NOT = 0
 PERFORM END-RTN
 STOP RUN.
******************************************************************
* 前処理 
******************************************************************
 INIT-RTN.
*    変数の初期化
     INITIALIZE END-FLG
*    ファイルオープン
     OPEN INPUT F1
     OPEN OUTPUT F2
*    サブルーチンCALL
     CALL "SUB01" USING BY REFERENCE CUST-COUNT
                        BY REFERENCE CUST-TABLE
                  GIVING RETURN-VALUE
     PERFORM VARYING I FROM 1 BY 1 UNTIL I > CUST-COUNT
         DISPLAY CUST-CODE OF CUSTOMER(I) " "
                 CUST-NAME OF CUSTOMER(I)
     END-PERFORM
*    1件目のレコードの入力
     PERFORM READ-RTN.
 INIT-RTN-EX. 
     EXIT.
******************************************************************
* 繰り返し処理 
******************************************************************
 LOOP-RTN.
*    出力レコードの編集 
     INITIALIZE F2R
     MOVE CUST-CODE OF F1R TO CUST-CODE OF F2R 
     MOVE SALES OF F1R TO SALES OF F2R 
     MOVE SALES OF F1R TO SALES OF F2R 
*    顧客マスターの検索 
     PERFORM VARYING I FROM 1 BY 1 UNTIL I > CUST-COUNT
         IF CUST-CODE OF F1R = CUST-CODE OF CUSTOMER(I)
             MOVE CUST-NAME OF CUSTOMER(I) TO CUST-NAME OF F2R     
             MOVE 99 TO I
         END-IF
     END-PERFORM           
*    レコードの出力     
     WRITE F2R
*    次のレコードの読み込み 
     PERFORM READ-RTN.
 LOOP-RTN-EX. 
     EXIT.
******************************************************************
* 後処理 
******************************************************************
 END-RTN.
     CLOSE  F1 F2.
 END-RTN-EX.
     EXIT.
******************************************************************
* 入力処理  
******************************************************************
 READ-RTN.
     READ  F1 
         AT END
             ADD 1 TO END-FLG
     END-READ.
 READ-RTN-EX.
     EXIT.
```

### サブプログラム
引数として受け取る領域は DATA DIVISION の LINKAGE SECTION に定義する。

PROCEDURE DIVISION宣言にUSING句で引数名を指定する。参照渡しで渡された引数の領域に値をセットすれば呼び出し側で参照することができる。

呼び出し側に戻るときは GOBACK文を実行する。

```
******************************************************************
* サブルーチン
* 引数：顧客マスターテーブルの参照
* 顧客マスターテーブルの内容を顧客マスターテーブルにセットして呼び出し元に返す。
****************************************************************** 
 IDENTIFICATION              DIVISION.
 PROGRAM-ID.                 SUB01.
 ENVIRONMENT                 DIVISION.
 INPUT-OUTPUT                SECTION.
 FILE-CONTROL.
*顧客マスターファイル 
 SELECT  M1  ASSIGN  TO  "./M001.txt"
 ORGANIZATION IS LINE SEQUENTIAL
 ACCESS  MODE  IS  SEQUENTIAL.  
 DATA                        DIVISION.
 FILE                        SECTION.
*顧客マスターレコード
 FD  M1.
 01  M1R.
     05 CUST-CODE            PIC 9(04).
     05 CUST-NAME            PIC X(20).       
 WORKING-STORAGE             SECTION.
 01  END-FLG                 PIC 9(01).
* 添え字
 01 I                        PIC 9(02).
 01 RETURN-VALUE             PIC 9(02).  
 LINKAGE                     SECTION.
* 顧客マスターテーブル（引数）
 01 CUST-COUNT               PIC 9(02).        
 01 CUST-TABLE.
     05 CUSTOMER OCCURS 10 TIMES.
         10 CUST-CODE        PIC 9(04).
         10 CUST-NAME        PIC X(20).              

 PROCEDURE  DIVISION USING BY REFERENCE CUST-COUNT CUST-TABLE.
 PERFORM MAIN-RTN
*呼び出し元に返る
 GOBACK.
******************************************************************
* 顧客マスターテーブルの作成
******************************************************************
 MAIN-RTN.
*    変数の初期化
     INITIALIZE END-FLG CUST-COUNT 
*    ファイルオープン
     OPEN INPUT M1
*    顧客マスターの読み込み
     PERFORM UNTIL END-FLG > 0
         READ  M1 
             AT END
                 ADD 1 TO END-FLG
             NOT AT END
*                顧客マスターレコードをテーブルにセット            
                 ADD 1 TO CUST-COUNT 
                 MOVE CUST-CODE OF M1R 
                     TO CUST-CODE OF CUSTOMER(CUST-COUNT) 
                 MOVE CUST-NAME OF M1R 
                     TO CUST-NAME OF CUSTOMER(CUST-COUNT)  
         END-READ
     END-PERFORM
     MOVE 999 TO RETURN-CODE
*    ファイルオープン
     CLOSE M1.
 MAIN-RTN-EX. 
     STOP RUN.
```

### コンパイル・リンクの方法
### 静的リンク
一括してコンパイルする。

```
cobc -x -o main MAIN01.cbl SUB01.cbl 
```
サブプログラムを別にコンパイルする。

```
cobc -c SUB01.cbl //オブジェクト .o を作成
cobc -x -o main MAIN01.cbl SUB01.o
```

### 動的（ダイナミック）リンク

メインプログラムのコンパイルと実行ファイルの作成

```
cobc -x MAIN01.cbl -o main
```

サブプログラムのコンパイルと共用オブジェクト（.dylib）の作成

```
cobc -m SUB01.cbl
```

実行

```
./main
```

####コンパイルオプションについてはこちらを参照
[GnuCOBOL Manual](https://gnucobol.sourceforge.io/doc/gnucobol.html)

関連記事
[COBOL 処理パターン　多段階集計](https://qiita.com/mikomokaru-jpn/items/09f6b0f056e329550854)
[COBOL 処理パターン　マッチング](https://qiita.com/mikomokaru-jpn/items/ec75da8319cf642c33f5)
[COBOL 処理パターン　テーブル展開](https://qiita.com/mikomokaru-jpn/items/ffb340cb0d647fc56597)
[COBOL 処理パターン　C言語で作成した外部サブプログラムを呼ぶ](https://qiita.com/mikomokaru-jpn/items/85bb6a3b15dfe845b3e4)