【COBOL】引数の使い方完全ガイド|BY REFERENCE・BY CONTENT・LINKAGE SECTION・RETURN-CODE

COBOLで複数のプログラムモジュールを組み合わせる際、データをどう受け渡すかが設計の要になります。CALL文でサブプログラムを呼び出すのは基本ですが、引数の渡し方にはBY REFERENCE・BY CONTENT・BY VALUEの3種類があり、それぞれ動作が異なります。

この記事では、LINKAGE SECTIONの定義方法から引数の渡し方の違い、動的CALLと静的CALLの使い分け、RETURN-CODEによる戻り値処理まで、COBOLの引数まわりを完全に解説します。

この記事でわかること

  • LINKAGE SECTIONの定義ルールと注意点
  • BY REFERENCE・BY CONTENT・BY VALUEの動作と使い分け
  • 複数引数・グループ項目・OCCURS配列の渡し方
  • 動的CALLと静的CALLの違いとメモリ管理
  • RETURN-CODEとON EXCEPTIONによる異常処理
  • 実践3パターン(税計算・バリデーション・件数返却)
スポンサーリンク

COBOLの引数渡しの全体像

COBOLでは、呼び出し元(呼び元プログラム)がCALL文のUSING句で引数を指定し、呼び出し先(サブプログラム)がLINKAGE SECTIONとPROCEDURE DIVISION USING句で受け取ります。

呼び元プログラム(基本形)
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN-PGM.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-AMOUNT     PIC 9(7)V99.
01 WS-TAX-RATE   PIC V9(2).          *> 小数: 0.10 = 10%
01 WS-TAX-AMT    PIC 9(7)V99.

PROCEDURE DIVISION.
    MOVE 15000.00 TO WS-AMOUNT
    MOVE .10      TO WS-TAX-RATE      *> 10% = 0.10
    CALL 'TAXCALC' USING WS-AMOUNT
                         WS-TAX-RATE
                         WS-TAX-AMT
    DISPLAY '消費税額: ' WS-TAX-AMT
    STOP RUN.
サブプログラム(基本形)
IDENTIFICATION DIVISION.
PROGRAM-ID. TAXCALC.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-WORK       PIC 9(10)V99.

LINKAGE SECTION.                    *> 引数受け取り専用セクション
01 LK-AMOUNT     PIC 9(7)V99.       *> USING 1番目
01 LK-TAX-RATE   PIC 9(3)V2.        *> USING 2番目
01 LK-TAX-AMT    PIC 9(7)V99.       *> USING 3番目

PROCEDURE DIVISION USING LK-AMOUNT
                         LK-TAX-RATE
                         LK-TAX-AMT.
    COMPUTE LK-TAX-AMT = LK-AMOUNT * LK-TAX-RATE / 100
    GOBACK.
ポイント: LINKAGE SECTIONの役割
LINKAGE SECTIONは呼び元のデータ領域に対する「別名(エイリアス)定義」です。サブプログラム内で独立したメモリを持つわけではなく、呼び元のアドレスを参照します。そのため、LINKAGE SECTION内の項目にVALUE句で初期値を設定してもコンパイルエラーになるか無視されます。

LINKAGE SECTIONの定義ルール

LINKAGE SECTIONは呼び出し先プログラムのDATA DIVISIONに記述します。定義の順序はCALL文のUSING句と一致させる必要があります。

ルール 説明
レコード番号 01〜49・66・77・88が使用可能。01レベルまたは77レベルで宣言するのが一般的
型の一致 呼び元と呼び先でPIC句の桁数・型を一致させる(不一致はデータ破損の原因)
VALUE句 使用不可(コンパイラによりエラーまたは無視)
OCCURS句 可変長OCCURS(DEPENDING ON)はサポートに差異あり。固定OCCURSは使用可能
FILLER項目 定義可能。ただし実際に参照されないため意味はない
REDEFINES LINKAGE SECTION内でのREDEFINESは使用可能(呼び元の構造に合わせた再定義)
LINKAGE SECTIONのよくある定義例
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-WORK         PIC 9(5).

LINKAGE SECTION.
*> 77レベル(単純な数値・文字)
77 LK-CODE         PIC X(4).

*> 01レベル(グループ項目)
01 LK-CUSTOMER.
   05 LK-CUST-ID   PIC 9(10).
   05 LK-CUST-NAME PIC X(40).
   05 LK-CUST-AGE  PIC 9(3).

*> 配列(固定OCCURS)
01 LK-SCORES.
   05 LK-SCORE     PIC 9(5) OCCURS 10 TIMES.

PROCEDURE DIVISION USING LK-CODE
                         LK-CUSTOMER
                         LK-SCORES.
注意: WORKING-STORAGEとLINKAGEの混同に注意
サブプログラム内でセッションをまたいで保持したいデータはWORKING-STORAGEに置きます。LINKAGE SECTIONは「呼び元から渡されたアドレスを参照する」だけの定義領域です。「保存用はWS、受け取り用はLK」という命名規則を徹底すると混乱を防げます。

引数の渡し方3種類

COBOLの引数渡しには3つのモードがあります。BY REFERENCEがデフォルトで、用途に応じて使い分けます。

渡し方 内部動作 呼び元への変更反映 用途
BY REFERENCE
(省略時デフォルト)
アドレスを渡す あり(呼び元に反映) 入出力引数
BY CONTENT 値のコピーを渡す なし(呼び元に影響しない) 入力専用引数
BY VALUE スタックに値を積む なし C言語との連携・システムAPI呼び出し

BY REFERENCE(参照渡し)

引数のメモリアドレスを渡します。サブプログラム側で値を変更すると、呼び元の変数が直接書き換わります。最もよく使われるモードです。

BY REFERENCE(省略可・明示両方OK)
*> 省略(デフォルトでBY REFERENCE)
CALL 'SUBPGM' USING WS-DATA1 WS-DATA2.

*> 明示的に指定
CALL 'SUBPGM' USING BY REFERENCE WS-DATA1
                     BY REFERENCE WS-DATA2.

*--- サブプログラム側での変更は呼び元に反映される ---
*SUBPGM:
PROCEDURE DIVISION USING LK-DATA1 LK-DATA2.
    MOVE 'UPDATED' TO LK-DATA1.   *> 呼び元WS-DATA1も'UPDATED'になる
    GOBACK.

BY CONTENT(値渡し・コピー)

引数のコピー(複製)を渡します。サブプログラムがデータを変更しても呼び元には影響しません。入力専用として渡す場合に使います。

BY CONTENT(値のコピーを渡す)
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-INPUT       PIC X(20) VALUE 'ORIGINAL'.
01 WS-RESULT      PIC X(20).

PROCEDURE DIVISION.
    CALL 'FORMATTER' USING BY CONTENT WS-INPUT    *> 入力専用
                            BY REFERENCE WS-RESULT *> 出力用
    DISPLAY WS-INPUT.   *> 'ORIGINAL'のまま(変更されていない)
    DISPLAY WS-RESULT.  *> サブプログラムが加工した結果
    STOP RUN.

*--- FORMATTER サブプログラム ---
LINKAGE SECTION.
01 LK-INPUT       PIC X(20).
01 LK-RESULT      PIC X(20).

PROCEDURE DIVISION USING LK-INPUT LK-RESULT.
    MOVE LK-INPUT TO LK-RESULT.
    INSPECT LK-RESULT CONVERTING SPACES TO '*'.   *> 加工
    *> LK-INPUTを変更してもBY CONTENTなので呼び元に反映されない
    GOBACK.

BY VALUE(値渡し・スタック経由)

値をスタックに積んで渡します。COBOL間では使用頻度が低く、主にC言語など他言語とのインターフェース(CEEやシステムAPI)で使います。

BY VALUE(他言語連携時)
*> C言語のint型関数を呼び出す例(IBM Enterprise COBOL想定)
CALL 'C-FUNC' USING BY VALUE WS-NUMERIC-PARAM
                    BY REFERENCE WS-RESULT-PARAM.

*> リテラルをBY VALUEで渡すことも可能
CALL 'SYS-API' USING BY VALUE 1
                      BY VALUE ZERO.
3種類の選び方まとめ

  • サブプログラムで値を変更し、呼び元に返したい → BY REFERENCE
  • 入力専用で誤った上書きを防ぎたい → BY CONTENT
  • C言語など他言語APIとの連携 → BY VALUE

同一CALL文で引数ごとに異なるモードを混在させることができます。

複数引数・グループ項目・配列の渡し方

グループ項目をまるごと渡す

グループ項目(01レベルの構造体)はそのままUSING句に指定できます。サブプログラム側でもグループ項目として受け取るか、グループ内の集合体として受け取るか選択できます。

グループ項目の引数受け渡し
*=== 呼び元 ===
WORKING-STORAGE SECTION.
01 WS-ORDER.
   05 WS-ORDER-ID   PIC 9(10).
   05 WS-ITEM-CODE  PIC X(8).
   05 WS-QTY        PIC 9(5).
   05 WS-UNIT-PRICE PIC 9(7)V99.
01 WS-TOTAL-PRICE   PIC 9(9)V99.

PROCEDURE DIVISION.
    MOVE 1001      TO WS-ORDER-ID
    MOVE 'ITEM-A'  TO WS-ITEM-CODE
    MOVE 3         TO WS-QTY
    MOVE 1200.00   TO WS-UNIT-PRICE
    CALL 'ORDERCALC' USING WS-ORDER       *> グループ項目ごと渡す
                           WS-TOTAL-PRICE
    STOP RUN.

*=== サブプログラム ===
LINKAGE SECTION.
01 LK-ORDER.
   05 LK-ORDER-ID   PIC 9(10).
   05 LK-ITEM-CODE  PIC X(8).
   05 LK-QTY        PIC 9(5).
   05 LK-UNIT-PRICE PIC 9(7)V99.
01 LK-TOTAL         PIC 9(9)V99.

PROCEDURE DIVISION USING LK-ORDER LK-TOTAL.
    COMPUTE LK-TOTAL = LK-QTY * LK-UNIT-PRICE
    GOBACK.

OCCURS配列を渡す

配列(OCCURS句)を含む項目を渡す場合も、親グループ項目をUSINGに指定します。要素数(DEPENDING ON用変数)を別引数で渡す方法がよく使われます。

OCCURS配列の引数渡し
*=== 呼び元 ===
WORKING-STORAGE SECTION.
01 WS-SCORE-TABLE.
   05 WS-SCORE     PIC 9(3) OCCURS 50 TIMES.
01 WS-SCORE-COUNT  PIC 9(2) VALUE 5.
01 WS-AVERAGE      PIC 9(3)V99.

PROCEDURE DIVISION.
    MOVE 80 TO WS-SCORE(1)
    MOVE 90 TO WS-SCORE(2)
    MOVE 75 TO WS-SCORE(3)
    MOVE 88 TO WS-SCORE(4)
    MOVE 95 TO WS-SCORE(5)
    CALL 'AVGCALC' USING WS-SCORE-TABLE
                         WS-SCORE-COUNT
                         WS-AVERAGE
    DISPLAY '平均点: ' WS-AVERAGE
    STOP RUN.

*=== サブプログラム ===
LINKAGE SECTION.
01 LK-SCORE-TABLE.
   05 LK-SCORE     PIC 9(3) OCCURS 50 TIMES.
01 LK-COUNT        PIC 9(2).
01 LK-AVERAGE      PIC 9(3)V99.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-SUM          PIC 9(6).
01 WS-IDX          PIC 9(2).

PROCEDURE DIVISION USING LK-SCORE-TABLE LK-COUNT LK-AVERAGE.
    MOVE 0 TO WS-SUM
    PERFORM VARYING WS-IDX FROM 1 BY 1
              UNTIL WS-IDX > LK-COUNT
        ADD LK-SCORE(WS-IDX) TO WS-SUM
    END-PERFORM
    COMPUTE LK-AVERAGE = WS-SUM / LK-COUNT
    GOBACK.

動的CALLと静的CALL

CALLには静的CALL動的CALLがあります。実行環境や保守性の要件に応じて使い分けます。

種類 CALL先の指定 リンク方式 特徴 用途
静的CALL リテラル(文字列定数) リンク時に結合 起動高速、モジュール入れ替え不可 固定モジュール呼び出し
動的CALL データ名(変数) 実行時にロード 起動に若干のオーバーヘッド、モジュール交換可能 複数パターンの切り替え、プラグイン的な設計
静的CALLと動的CALLの書き方
*=== 静的CALL(プログラム名はリテラル)===
CALL 'TAXCALC' USING WS-AMOUNT WS-RATE WS-TAX.

*=== 動的CALL(プログラム名は変数)===
WORKING-STORAGE SECTION.
01 WS-MODULE-NAME  PIC X(8).

PROCEDURE DIVISION.
    *> 条件によって呼び出しモジュールを切り替える
    IF WS-REGION = 'JP'
        MOVE 'TAXCALCJ' TO WS-MODULE-NAME
    ELSE
        MOVE 'TAXCALCE' TO WS-MODULE-NAME
    END-IF

    CALL WS-MODULE-NAME USING WS-AMOUNT WS-RATE WS-TAX
        ON EXCEPTION
            DISPLAY 'モジュールが見つかりません: ' WS-MODULE-NAME
            MOVE 'NG' TO WS-STATUS
    END-CALL.
注意: 動的CALLのCANCEL文
動的CALLでロードされたモジュールは、CANCEL文を使って明示的にメモリから解放できます。長時間稼働するバッチで多数の動的モジュールを呼び出す場合、CANCEL文を使わないとメモリが圧迫されることがあります。
CANCEL 'TAXCALC'.
CANCEL後に再度CALLすると再初期化された状態でロードされます。WORKING-STORAGEの値もリセットされます。

RETURN-CODEとON EXCEPTIONで結果を受け取る

サブプログラムの処理結果は引数で返すほか、RETURN-CODE特殊レジスタを使う方法があります。ON EXCEPTIONはCALLが失敗した場合(モジュール未存在など)に処理を分岐させます。

RETURN-CODEによる戻りコード

RETURN-CODEの設定と確認
*=== サブプログラム: 処理結果をRETURN-CODEで返す ===
PROCEDURE DIVISION USING LK-INPUT LK-OUTPUT.
    *> 正常処理
    MOVE LK-INPUT TO LK-OUTPUT
    INSPECT LK-OUTPUT CONVERTING LOWER-ALPHA TO UPPER-ALPHA
    MOVE 0 TO RETURN-CODE.          *> 正常: 0
    GOBACK.

    *> 異常時は0以外をセット
ERROR-EXIT.
    MOVE 8 TO RETURN-CODE.          *> 異常: 8(業務慣習に合わせて定義)
    GOBACK.

*=== 呼び元: RETURN-CODEを確認する ===
PROCEDURE DIVISION.
    CALL 'VALIDATE' USING WS-INPUT WS-OUTPUT
    EVALUATE RETURN-CODE
        WHEN 0
            DISPLAY '正常終了'
        WHEN 4
            DISPLAY '警告あり'
        WHEN 8
            DISPLAY '処理エラー'
            GO TO ERROR-EXIT
        WHEN OTHER
            DISPLAY '予期せぬエラー: ' RETURN-CODE
            GO TO ERROR-EXIT
    END-EVALUATE.

ON EXCEPTIONとNOT ON EXCEPTION

ON EXCEPTION / NOT ON EXCEPTIONの使い方
CALL 'PROCMODULE' USING BY REFERENCE WS-DATA
                         BY CONTENT   WS-CTRL
                         BY REFERENCE WS-RESULT
    ON EXCEPTION
        *> モジュールが見つからない・ロード失敗時に実行
        DISPLAY 'CALLエラー: PROCMODULE が見つかりません'
        MOVE 'NG' TO WS-STATUS
        MOVE 99   TO RETURN-CODE
    NOT ON EXCEPTION
        *> CALL成功時に実行(任意)
        MOVE 'OK' TO WS-STATUS
END-CALL.
RETURN-CODEの設計慣習

  • 0: 正常終了
  • 4: 警告(処理は継続可能だが注意あり)
  • 8: 異常(処理エラー、呼び元で判断が必要)
  • 12以上: 重大エラー(即時中断)

数値の意味はプロジェクト標準で統一しておくと保守性が高まります。

実践パターン3選

消費税計算モジュール(入力専用+出力引数)

金額と税率を入力専用(BY CONTENT)で渡し、計算結果を出力用引数(BY REFERENCE)で返すパターンです。

呼び元: MAIN-BATCH
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN-BATCH.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-PRICE        PIC 9(7)V99.
01 WS-TAX-RATE     PIC V9(2)  VALUE .10.    *> 0.10 = 10%
01 WS-TAX          PIC 9(7)V99.
01 WS-TOTAL        PIC 9(8)V99.

PROCEDURE DIVISION.
    MOVE 18000.00  TO WS-PRICE
    CALL 'TAXSUB' USING BY CONTENT   WS-PRICE     *> 入力専用
                         BY CONTENT   WS-TAX-RATE  *> 入力専用
                         BY REFERENCE WS-TAX       *> 出力(税額)
                         BY REFERENCE WS-TOTAL     *> 出力(税込合計)
    DISPLAY '税抜: '     WS-PRICE
    DISPLAY '消費税: '   WS-TAX
    DISPLAY '税込合計: ' WS-TOTAL
    STOP RUN.
サブプログラム: TAXSUB
IDENTIFICATION DIVISION.
PROGRAM-ID. TAXSUB.

DATA DIVISION.
LINKAGE SECTION.
01 LK-PRICE        PIC 9(7)V99.
01 LK-RATE         PIC V9(2).         *> 呼び元と同じPIC句
01 LK-TAX          PIC 9(7)V99.
01 LK-TOTAL        PIC 9(8)V99.

PROCEDURE DIVISION USING LK-PRICE LK-RATE LK-TAX LK-TOTAL.
    COMPUTE LK-TAX   = LK-PRICE * LK-RATE    *> 15000.00 * 0.10 = 1500.00
    COMPUTE LK-TOTAL = LK-PRICE + LK-TAX
    MOVE 0 TO RETURN-CODE
    GOBACK.

入力バリデーションモジュール(RETURN-CODEで結果返却)

入力値を検証して、問題があればRETURN-CODEに非0をセットして返すパターンです。引数が増えないのでCALL文がシンプルになります。

呼び元: 入力チェック呼び出し
CALL 'INPUTCHK' USING BY REFERENCE WS-INPUT-DATA
    ON EXCEPTION
        DISPLAY 'バリデーションモジュールが見つかりません'
        STOP RUN
END-CALL
IF RETURN-CODE NOT = 0
    DISPLAY '入力エラー: コード=' RETURN-CODE
    GO TO INPUT-ERROR
END-IF.
サブプログラム: INPUTCHK
IDENTIFICATION DIVISION.
PROGRAM-ID. INPUTCHK.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-NUM-CHECK    PIC X(1).

LINKAGE SECTION.
01 LK-INPUT-DATA.
   05 LK-CUST-ID   PIC 9(10).
   05 LK-AMOUNT    PIC S9(9)V99.
   05 LK-CATEGORY  PIC X(2).

PROCEDURE DIVISION USING LK-INPUT-DATA.
    *> 顧客IDが0はNG
    IF LK-CUST-ID = ZEROS
        MOVE 4 TO RETURN-CODE
        GOBACK
    END-IF
    *> 金額が負数はNG
    IF LK-AMOUNT < 0
        MOVE 8 TO RETURN-CODE
        GOBACK
    END-IF
    *> カテゴリコードの値チェック
    EVALUATE LK-CATEGORY
        WHEN '01' WHEN '02' WHEN '03'
            CONTINUE
        WHEN OTHER
            MOVE 12 TO RETURN-CODE
            GOBACK
    END-EVALUATE
    MOVE 0 TO RETURN-CODE
    GOBACK.

件数カウントモジュール(入力ファイルパスと出力件数)

ファイル名を受け取り、レコードを読んで件数を返すパターンです。ファイルアクセス処理を別モジュールに集約できます。

呼び元: REPORT-MAIN
WORKING-STORAGE SECTION.
01 WS-FILE-NAME    PIC X(40).
01 WS-REC-COUNT    PIC 9(7).
01 WS-ERR-STATUS   PIC X(2).

PROCEDURE DIVISION.
    MOVE '/data/input/orders.dat' TO WS-FILE-NAME
    CALL 'FILECNT' USING BY CONTENT   WS-FILE-NAME
                          BY REFERENCE WS-REC-COUNT
                          BY REFERENCE WS-ERR-STATUS
    EVALUATE RETURN-CODE
        WHEN 0
            DISPLAY '件数: ' WS-REC-COUNT
        WHEN 4
            DISPLAY 'ファイルが空です'
        WHEN 8
            DISPLAY 'ファイルオープンエラー: ' WS-ERR-STATUS
    END-EVALUATE
    STOP RUN.
サブプログラム: FILECNT
IDENTIFICATION DIVISION.
PROGRAM-ID. FILECNT.

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT ORDER-FILE ASSIGN TO LK-FILE-NAME
           ORGANIZATION IS LINE SEQUENTIAL
           FILE STATUS IS WS-FILE-STATUS.

DATA DIVISION.
FILE SECTION.
FD  ORDER-FILE.
01  ORDER-RECORD  PIC X(200).

WORKING-STORAGE SECTION.
01 WS-FILE-STATUS PIC X(2).
01 WS-EOF-FLAG    PIC X(1) VALUE 'N'.
   88 WS-EOF      VALUE 'Y'.

LINKAGE SECTION.
01 LK-FILE-NAME   PIC X(40).
01 LK-COUNT       PIC 9(7).
01 LK-ERR-STATUS  PIC X(2).

PROCEDURE DIVISION USING LK-FILE-NAME LK-COUNT LK-ERR-STATUS.
    MOVE 0   TO LK-COUNT
    MOVE 'N' TO WS-EOF-FLAG

    OPEN INPUT ORDER-FILE
    IF WS-FILE-STATUS NOT = '00'
        MOVE WS-FILE-STATUS TO LK-ERR-STATUS
        MOVE 8 TO RETURN-CODE
        GOBACK
    END-IF

    PERFORM UNTIL WS-EOF
        READ ORDER-FILE
            AT END SET WS-EOF TO TRUE
            NOT AT END ADD 1 TO LK-COUNT
        END-READ
    END-PERFORM

    CLOSE ORDER-FILE

    IF LK-COUNT = 0
        MOVE 4 TO RETURN-CODE
    ELSE
        MOVE 0 TO RETURN-CODE
    END-IF
    GOBACK.

よくある落とし穴と対策

落とし穴 問題の内容 対策
型不一致(PIC句の桁数ズレ) 呼び元PIC 9(5)・呼び先PIC 9(7) のように桁数が違うと、LINKAGE SECTIONでアドレス計算がずれてデータ破損が発生する COPY句でデータ定義を共有し、呼び元と呼び先で同一PIC句を使う
BY REFERENCEの意図しない上書き サブプログラムが引数を変更する想定がなかったのに、誤ってMOVEしてしまい呼び元のデータが壊れる 入力専用引数にはBY CONTENTを明示して誤上書きを防ぐ
LINKAGE SECTIONにVALUE句を書く VALUE句は無視されるかコンパイルエラー。LINKAGE SECTIONは初期化の場所ではない 初期値は呼び元で設定してから渡す。または呼び先のWORKING-STORAGEで管理する
動的CALL後のCANCEL忘れ ループ内で動的CALLを繰り返すとロードされたモジュールのWORKING-STORAGEが初期化されず、前回の残存値が混入する 毎回再初期化が必要な場合はCALL後にCANCELを実行するか、BY REFERENCEで初期化フラグを渡す
RETURN-CODEの上書き CALLの直後に別のCALLをするとRETURN-CODEが上書きされる CALL直後にRETURN-CODEをWORKING-STORAGEの変数に退避してから判定する
RETURN-CODE退避のパターン
WORKING-STORAGE SECTION.
01 WS-RC1          PIC S9(9) COMP.
01 WS-RC2          PIC S9(9) COMP.

PROCEDURE DIVISION.
    CALL 'SUBPGM1' USING WS-DATA1
    MOVE RETURN-CODE TO WS-RC1     *> すぐに退避

    CALL 'SUBPGM2' USING WS-DATA2
    MOVE RETURN-CODE TO WS-RC2     *> すぐに退避

    IF WS-RC1 NOT = 0
        DISPLAY 'SUBPGM1エラー: ' WS-RC1
    END-IF
    IF WS-RC2 NOT = 0
        DISPLAY 'SUBPGM2エラー: ' WS-RC2
    END-IF.

よくある質問

QPROCEDURE DIVISION USINGの引数の順序は関係ありますか?
Aはい、順序は重要です。CALL文のUSING句に指定した順番と、サブプログラムのPROCEDURE DIVISION USING句の順番が対応します。順序を間違えると、型が同じ場合はコンパイルエラーにならず、実行時にデータが意図しない変数に入るバグが発生します。COPY句で呼び元と呼び先で定義を共有すると間違いを防げます。
QLINKAGE SECTIONに定義した項目数より少ない引数を渡せますか?
Aコンパイラによっては可能ですが、省略された引数へのアクセスは未定義動作になるため危険です。引数の数を可変にしたい場合は、呼び元で「引数の個数」を別引数として渡す設計にするか、使用しない引数に対応するダミー領域を渡す方法があります。
QGOBACKとSTOP RUNの違いは何ですか?
AGOBACK は呼び元に制御を返す(サブプログラムで使う)のに対し、STOP RUN はジョブ全体を終了します。サブプログラムでSTOP RUNを書くと、CALLした呼び元に戻らずプログラム全体が終了してしまいます。サブプログラムの終了には必ずGOBACKを使いましょう。
QBY REFERENCEで渡したデータは呼び先で保護できますか?
ACOBOLには引数のconst修飾子はありません。保護する方法として①BY CONTENTで渡す、②サブプログラム側でLINKAGE SECTIONの項目を変更しない規約を徹底する、③入力引数を受け取ったらすぐにWORKING-STORAGEに複製して作業する、の3つがあります。
Qサブプログラムから別のサブプログラムを呼び出せますか?
Aはい、CALLはネストして呼び出せます。サブプログラムAがサブプログラムBを呼び出すことが可能です。深いネストはデバッグを複雑にするため、通常は3階層程度を上限とするプロジェクト標準が多いです。なお、再帰呼び出し(自身をCALLする)は多くのCOBOLコンパイラで禁止または非推奨です。

まとめ

COBOLの引数まわりのポイントをまとめます。

要素 説明
LINKAGE SECTION サブプログラム側で引数を定義するセクション。呼び元のアドレスを参照する別名定義
BY REFERENCE(デフォルト) アドレス渡し。サブプログラムでの変更が呼び元に反映される
BY CONTENT コピー渡し。入力専用引数の保護に使う
BY VALUE スタック渡し。主に他言語連携で使う
動的CALL 変数でモジュール名を指定。ON EXCEPTIONでロード失敗を検知できる
RETURN-CODE サブプログラムが設定する戻りコード。CALLの直後に退避して使う
GOBACK サブプログラムの終了命令。呼び元に制御を返す(STOP RUNと混同しない)

引数の渡し方をしっかり設計することで、モジュール間のデータ連携が明確になり、テストや保守が格段にしやすくなります。BY CONTENTで入力専用を明示し、RETURN-CODEで処理結果を返す設計を習慣にしましょう。

COBOLのデータ操作については、MOVE文でデータを転送する方法や、CALL文の基本的な使い方も合わせてご参照ください。引数の流れを理解した上でUSING句の詳細な仕様を確認すると、より深く理解できます。