【COBOL】USING句完全ガイド|CALL・PROCEDURE DIVISION・SORT/MERGE・OMITTED・パラメータ設計パターン

COBOLの「USING句」は、呼び出し元からサブプログラムへデータを渡す構文として知られていますが、実はCALL文以外にも登場します。PROCEDURE DIVISION・SORT文・MERGE文でもそれぞれ異なる意味で使われており、コンテキストを正確に把握することが重要です。

この記事では、USING句が現れる3つのコンテキストを整理したうえで、OMITTEDによる省略可能な引数、COPY句を使った定義の共有、そして実務でよく直面する「引数が多すぎる問題」へのパラメータ設計パターンまで解説します。

この記事でわかること

  • USING句が登場する3つのコンテキスト(CALL / PROCEDURE DIVISION / SORT・MERGE)
  • PROCEDURE DIVISION USINGのルールとLINKAGE SECTIONとの対応
  • SORT/MERGE文でのUSING句(複数ファイルを入力として指定する仕組み)
  • OMITTEDキーワードで省略可能な引数を実装する方法
  • COPY句を使って呼び元と呼び先のパラメータ定義を共有する方法
  • 引数が多くなったときのパラメータ設計パターン(グループ統合・フラグ統合)

引数の渡し方(BY REFERENCE / BY CONTENT / BY VALUE)とLINKAGE SECTIONの詳細な解説は引数の使い方完全ガイドをご参照ください。CALL文自体の詳細(動的CALL・CANCEL・ネストプログラム)はCALL文完全ガイドで扱っています。本記事はUSING句の全コンテキストとパラメータ設計に焦点を当てます。

スポンサーリンク

USING句が登場する3つのコンテキスト

コンテキスト 構文例 役割
CALL文のUSING句 CALL ‘SUBPGM’ USING 引数1 引数2 呼び元が引数をサブプログラムに渡す
PROCEDURE DIVISION USING句 PROCEDURE DIVISION USING 仮引数1 仮引数2. 呼び先(サブプログラム)が引数を受け取る
SORT/MERGE文のUSING句 SORT SORT-WK … USING 入力ファイル1 入力ファイル2 SORTの入力ファイルを複数指定する

CALL文のUSING句とPROCEDURE DIVISION USING句はペアで機能します。SORT/MERGEのUSING句は全く異なる意味(ファイル指定)で使われます。

CALL文のUSING句

CALL文のUSING句で渡す引数には、BY REFERENCE・BY CONTENT・BY VALUEの3つのモードがあります。省略するとBY REFERENCEが適用されます。

CALL文のUSING句(基本)
WORKING-STORAGE SECTION.
01  WS-AMOUNT       PIC 9(9)V99.
01  WS-TAX-RATE     PIC V99.
01  WS-TAX-AMT      PIC 9(7)V99.
01  WS-STATUS       PIC X(2).

PROCEDURE DIVISION.
    MOVE 50000.00 TO WS-AMOUNT
    MOVE .10      TO WS-TAX-RATE

    CALL 'TAXCALC' USING
            BY CONTENT   WS-AMOUNT     *> 入力専用(呼び元を保護)
            BY CONTENT   WS-TAX-RATE   *> 入力専用
            BY REFERENCE WS-TAX-AMT    *> 出力(計算結果を受け取る)
            BY REFERENCE WS-STATUS     *> 出力(処理結果コード)
        ON EXCEPTION
            DISPLAY 'モジュールが見つかりません'
            MOVE 8 TO RETURN-CODE
            STOP RUN
    END-CALL.

BY CONTENT(入力専用)とBY REFERENCE(出力可能)を明示することで、コードを読むだけで各引数の役割がわかります。BY REFERENCEのデフォルト動作・BY VALUE(他言語連携)を含む引数渡しの詳細は引数の使い方完全ガイドを参照してください。

CALL USING句のルール

項目 説明
引数の個数 0個から規格上は上限なし(実装により制限あり)
引数の型 変数・グループ項目・リテラル(BY CONTENTまたはBY VALUEのみ)
渡す順序 PROCEDURE DIVISION USING句の仮引数と位置で対応する
BY省略 デフォルトでBY REFERENCEが適用される
混在 引数ごとに異なるBYモードを混在させることができる

PROCEDURE DIVISION USING句

PROCEDURE DIVISION USING句は、サブプログラム側(受け取る側)で引数に名前を付ける構文です。LINKAGE SECTIONで定義した項目名を順番に列挙します。

PROCEDURE DIVISION USING句の構文
IDENTIFICATION DIVISION.
PROGRAM-ID. TAXCALC.

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

LINKAGE SECTION.                    *> 引数の定義(アドレス参照)
01  LK-AMOUNT   PIC 9(9)V99.        *> 1番目の引数
01  LK-RATE     PIC V99.            *> 2番目の引数
01  LK-TAX      PIC 9(7)V99.        *> 3番目の引数
01  LK-STATUS   PIC X(2).           *> 4番目の引数

*> PROCEDURE DIVISIONに列挙する順番 = CALL USINGの順番
PROCEDURE DIVISION USING LK-AMOUNT
                         LK-RATE
                         LK-TAX
                         LK-STATUS.
    IF LK-AMOUNT <= 0
        MOVE 'NG' TO LK-STATUS
        MOVE 0    TO LK-TAX
        GOBACK
    END-IF
    COMPUTE LK-TAX = LK-AMOUNT * LK-RATE
    MOVE 'OK' TO LK-STATUS
    GOBACK.

PROCEDURE DIVISION USING句のルール

ルール 説明
並び順 CALL文のUSING句と位置が対応する。名前は違っても構わない
LINKAGE SECTION必須 ここに列挙する変数はLINKAGE SECTIONに定義されている必要がある
VALUE句禁止 LINKAGE SECTIONの項目にVALUE句は使えない(コンパイラによりエラーまたは無視)
型の一致 呼び元と呼び先でPIC句を合わせる(不一致はデータ破損の原因)
終了はGOBACK サブプログラムの終了はGOBACK。STOP RUNはジョブ全体を終了するので禁止

名前は異なっても位置で対応する
呼び元の変数名(例: WS-AMOUNT)とサブプログラムの仮引数名(例: LK-AMOUNT)は異なっていても問題ありません。COBOLの引数は位置(順番)で対応します。ただし、型(PIC句)は必ず一致させてください。型が違うとコンパイルエラーにならず、実行時にデータが壊れるバグになります。

LINKAGE SECTIONとの対応関係

呼び元と呼び先のデータ対応
*=== 呼び元(MAIN-PGM)===
WORKING-STORAGE SECTION.
01  WS-CUST-REC.                      *> グループ項目を渡す
    05  WS-CUST-ID    PIC 9(10).
    05  WS-CUST-NAME  PIC X(30).
    05  WS-BALANCE    PIC S9(9)V99.
01  WS-RESULT-CODE    PIC X(2).

PROCEDURE DIVISION.
    CALL 'CUST-VALIDATE' USING WS-CUST-REC       *> 位置1
                               WS-RESULT-CODE     *> 位置2
    END-CALL.

*=== 呼び先(CUST-VALIDATE)===
LINKAGE SECTION.
01  LK-CUSTOMER.                      *> 呼び元WS-CUST-RECに対応(位置1)
    05  LK-CUST-ID    PIC 9(10).      *> 同じ構造で定義する
    05  LK-CUST-NAME  PIC X(30).
    05  LK-BALANCE    PIC S9(9)V99.
01  LK-RESULT         PIC X(2).       *> 呼び元WS-RESULT-CODEに対応(位置2)

PROCEDURE DIVISION USING LK-CUSTOMER LK-RESULT.
    IF LK-CUST-ID = ZEROS
        MOVE 'E1' TO LK-RESULT
        GOBACK
    END-IF
    IF LK-BALANCE < 0
        MOVE 'E2' TO LK-RESULT
        GOBACK
    END-IF
    MOVE 'OK' TO LK-RESULT
    GOBACK.

SORT/MERGE文のUSING句

USING句はSORT文とMERGE文にも登場します。こちらは引数の受け渡しとは無関係で、ソートまたはマージの入力ファイルを指定するための構文です。

SORT文でのUSING句

SORT文の構造
SORT文には入力の指定方法として「USING句(ファイル指定)」と「INPUT PROCEDURE(プログラムで制御)」の2種類があります。USING句を使うと、COBOLランタイムが自動でファイルを開いてすべてのレコードを読み込んでくれます。

SORT文 USINGの構文
SORT ソートワークファイル名
    ON {ASCENDING | DESCENDING} KEY キー項目名 ...
    [USING 入力ファイル名1 [入力ファイル名2 ...]]
    {GIVING 出力ファイル名 | OUTPUT PROCEDURE IS 手続き名}
SORT文 USING句の基本例(単一入力ファイル)
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT TRANS-FILE  ASSIGN TO 'TRANS.DAT'
           ORGANIZATION IS SEQUENTIAL.
    SELECT SORT-WORK   ASSIGN TO SORT-WORK-AREA.
    SELECT SORTED-FILE ASSIGN TO 'SORTED.DAT'
           ORGANIZATION IS SEQUENTIAL.

DATA DIVISION.
FILE SECTION.
FD  TRANS-FILE.
01  TRANS-RECORD  PIC X(80).

SD  SORT-WORK.                *> ソートワークはFDでなくSDで定義
01  SORT-RECORD.
    05  SK-DATE     PIC 9(8).
    05  SK-AMOUNT   PIC 9(9)V99.
    05  FILLER      PIC X(61).

FD  SORTED-FILE.
01  SORTED-RECORD  PIC X(80).

PROCEDURE DIVISION.
    *> USINGでTRANS-FILEを指定→自動でOPEN・READ・CLOSE
    *> GIVINGでSORTED-FILEへ出力→自動でOPEN・WRITE・CLOSE
    SORT SORT-WORK
        ON ASCENDING KEY SK-DATE
        ON DESCENDING KEY SK-AMOUNT
        USING TRANS-FILE
        GIVING SORTED-FILE

    DISPLAY 'ソート完了'
    STOP RUN.

SORT USING句の最大の特徴は、ファイルのオープン・読み込み・クローズをランタイムが自動で行う点です。入力ファイルを自分でOPEN/READする必要がなく、コードが簡潔になります。

SORT文 USING句で複数ファイルを入力する

USING句には複数のファイルを指定できます。ランタイムが各ファイルのすべてのレコードを読み込んで一括ソートします。年度をまたぐデータや、システムを分けて収集したデータを一度にソートする場面で使います。

複数ファイルをUSINGで指定
FILE-CONTROL.
    SELECT JAN-FILE    ASSIGN TO 'DATA-JAN.DAT' ORGANIZATION IS SEQUENTIAL.
    SELECT FEB-FILE    ASSIGN TO 'DATA-FEB.DAT' ORGANIZATION IS SEQUENTIAL.
    SELECT MAR-FILE    ASSIGN TO 'DATA-MAR.DAT' ORGANIZATION IS SEQUENTIAL.
    SELECT SORT-WORK   ASSIGN TO SORT-WORK-AREA.
    SELECT Q1-SORTED   ASSIGN TO 'Q1-SORTED.DAT' ORGANIZATION IS SEQUENTIAL.

DATA DIVISION.
FILE SECTION.
FD  JAN-FILE.   01  JAN-RECORD   PIC X(100).
FD  FEB-FILE.   01  FEB-RECORD   PIC X(100).
FD  MAR-FILE.   01  MAR-RECORD   PIC X(100).

SD  SORT-WORK.
01  SORT-RECORD.
    05  SK-CUST-CODE  PIC X(8).
    05  SK-TRANS-DATE PIC 9(8).
    05  FILLER        PIC X(84).

FD  Q1-SORTED.
01  Q1-RECORD    PIC X(100).

PROCEDURE DIVISION.
    *> 1月・2月・3月の3ファイルをまとめてソート
    SORT SORT-WORK
        ON ASCENDING KEY SK-CUST-CODE
        ON ASCENDING KEY SK-TRANS-DATE
        USING JAN-FILE FEB-FILE MAR-FILE    *> 3ファイルを一括入力
        GIVING Q1-SORTED                    *> 1つの出力ファイルへ

    DISPLAY '第1四半期データのソート完了'
    STOP RUN.
方式 特徴 向いているケース
SORT USING 複数ファイルOK・ランタイムが自動READ 入力ファイルをそのままソートしたい場合
SORT INPUT PROCEDURE 単一制御(RELEASEでソートに送り込む) フィルタリング・加工してからソートしたい場合

SORT USINGはOPEN/CLOSEが自動
SORT USING句で指定したファイルはランタイムが自動でOPEN・READします。SORT実行前に自分でOPENしてしまうと「既にオープン済み」エラーが発生します。同様にSORT後のCLOSEも不要です。

MERGE文でのUSING句

MERGE文はあらかじめソート済みの複数ファイルをひとつにまとめる命令です。MERGEのUSING句はSORT同様に入力ファイルを列挙します。ただしMERGEはSORT処理を行わないため、指定するファイルはすでにキー順にソート済みであることが前提です。

MERGE文でのUSING句(マージ済みファイルの統合)
FILE-CONTROL.
    SELECT REGION-EAST  ASSIGN TO 'EAST-SORTED.DAT'.
    SELECT REGION-WEST  ASSIGN TO 'WEST-SORTED.DAT'.
    SELECT REGION-NORTH ASSIGN TO 'NORTH-SORTED.DAT'.
    SELECT MERGE-WORK   ASSIGN TO MERGE-WORK-AREA.
    SELECT NATION-FILE  ASSIGN TO 'NATION.DAT'.

DATA DIVISION.
FILE SECTION.
FD  REGION-EAST.   01  EAST-RECORD  PIC X(80).
FD  REGION-WEST.   01  WEST-RECORD  PIC X(80).
FD  REGION-NORTH.  01  NORTH-RECORD PIC X(80).

SD  MERGE-WORK.
01  MERGE-RECORD.
    05  MK-PROD-CODE  PIC X(8).
    05  FILLER        PIC X(72).

FD  NATION-FILE.   01  NATION-RECORD PIC X(80).

PROCEDURE DIVISION.
    *> 東・西・北 3リージョンのソート済みファイルをマージ
    MERGE MERGE-WORK
        ON ASCENDING KEY MK-PROD-CODE
        USING REGION-EAST               *> ソート済みが前提
              REGION-WEST
              REGION-NORTH
        GIVING NATION-FILE              *> 統合後の全国ファイル

    DISPLAY 'マージ完了'
    STOP RUN.

OMITTEDキーワード(省略可能な引数)

CALL文のUSING句では、特定の引数を省略することを示すOMITTEDキーワードが使えます。呼び先でその引数が使われない場合に指定します。サブプログラム側ではADDRESS OF 仮引数名NULLかどうかで省略を検出できます。

OMITTED の構文
*> 引数を渡さないことを明示する
CALL 'SUBPGM' USING WS-INPUT
                     OMITTED          *> 2番目の引数を省略
                     WS-OUTPUT
END-CALL.
省略可能な引数を持つサブプログラムの実装
IDENTIFICATION DIVISION.
PROGRAM-ID. LOG-WRITER.
*> 引数: 1=メッセージ(必須)2=ログレベル(省略可)3=出力コード(省略可)

DATA DIVISION.
WORKING-STORAGE SECTION.
01  WS-DEFAULT-LEVEL   PIC X(1) VALUE 'I'.   *> デフォルト: INFO

LINKAGE SECTION.
01  LK-MESSAGE    PIC X(120).             *> 必須
01  LK-LOG-LEVEL  PIC X(1).               *> 省略可(省略時はINFO)
01  LK-OUT-CODE   PIC X(2).               *> 省略可(省略時は出力なし)

PROCEDURE DIVISION USING LK-MESSAGE LK-LOG-LEVEL LK-OUT-CODE.
    *> ログレベルが省略されたか確認
    IF ADDRESS OF LK-LOG-LEVEL = NULL
        MOVE 'I' TO WS-DEFAULT-LEVEL      *> デフォルト値を使う
    ELSE
        MOVE LK-LOG-LEVEL TO WS-DEFAULT-LEVEL
    END-IF

    *> 出力コードが省略されたか確認
    IF ADDRESS OF LK-OUT-CODE NOT = NULL
        MOVE 'OK' TO LK-OUT-CODE          *> 渡されていれば書き込む
    END-IF

    EVALUATE WS-DEFAULT-LEVEL
        WHEN 'D'  DISPLAY '[DEBUG] ' LK-MESSAGE
        WHEN 'I'  DISPLAY '[INFO]  ' LK-MESSAGE
        WHEN 'W'  DISPLAY '[WARN]  ' LK-MESSAGE
        WHEN 'E'  DISPLAY '[ERROR] ' LK-MESSAGE
    END-EVALUATE
    GOBACK.
OMITTEDを使った呼び出しパターン
WORKING-STORAGE SECTION.
01  WS-MSG       PIC X(120).
01  WS-LEVEL     PIC X(1).
01  WS-CODE      PIC X(2).

PROCEDURE DIVISION.
    *> パターン1: 全引数を渡す
    MOVE 'トランザクション開始' TO WS-MSG
    MOVE 'I' TO WS-LEVEL
    CALL 'LOG-WRITER' USING WS-MSG WS-LEVEL WS-CODE
    END-CALL

    *> パターン2: ログレベルは省略(デフォルトINFOを使う)
    MOVE '処理件数: 100件' TO WS-MSG
    CALL 'LOG-WRITER' USING WS-MSG OMITTED WS-CODE
    END-CALL

    *> パターン3: 出力コードも省略
    MOVE 'デバッグ情報' TO WS-MSG
    MOVE 'D' TO WS-LEVEL
    CALL 'LOG-WRITER' USING WS-MSG WS-LEVEL OMITTED
    END-CALL

    *> パターン4: オプション引数を両方省略
    MOVE 'エラー発生' TO WS-MSG
    CALL 'LOG-WRITER' USING WS-MSG OMITTED OMITTED
    END-CALL
    STOP RUN.

OMITTEDの主な用途: 追加機能を追加したいがインターフェースを変えたくない場合に、既存の呼び出し元はOMITTEDのまま、新機能を使う呼び出し元だけ実引数を渡す設計ができます。ただしADDRESS OFのチェックはランタイム環境によって動作が異なるため、プロジェクトの実行環境での動作確認を推奨します。

COPY句でパラメータ定義を共有する

呼び元と呼び先でPIC句をそれぞれ書くと、一方を修正したときに他方を更新し忘れてデータ破損が発生します。COPY句を使ってコピーブックに定義を一元管理すると、この問題を根本から防げます。

コピーブック(ORDERPARM.CPY)の定義
*> ファイル名: ORDERPARM.CPY
*> 注文処理サブプログラムの共通パラメータ定義
01  ORDER-PARAMS.
    05  OP-ORDER-ID     PIC 9(10).       *> 注文番号
    05  OP-CUST-CODE    PIC X(8).        *> 顧客コード
    05  OP-ITEM-CODE    PIC X(10).       *> 商品コード
    05  OP-QUANTITY     PIC 9(5).        *> 数量
    05  OP-UNIT-PRICE   PIC 9(7)V99.     *> 単価
    05  OP-DISCOUNT-RT  PIC V99.         *> 割引率
    05  OP-TOTAL-AMT    PIC 9(9)V99.     *> 合計金額(出力)
    05  OP-STATUS-CODE  PIC X(2).        *> 処理結果(出力)
    05  OP-ERROR-MSG    PIC X(60).       *> エラーメッセージ(出力)
呼び元(MAIN-BATCH)でCOPY句を使う
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN-BATCH.

DATA DIVISION.
WORKING-STORAGE SECTION.
COPY ORDERPARM.                  *> コピーブックをそのまま展開

PROCEDURE DIVISION.
    MOVE 1001        TO OP-ORDER-ID
    MOVE 'CUST-001'  TO OP-CUST-CODE
    MOVE 'ITEM-A001' TO OP-ITEM-CODE
    MOVE 3           TO OP-QUANTITY
    MOVE 1800.00     TO OP-UNIT-PRICE
    MOVE .05         TO OP-DISCOUNT-RT

    CALL 'ORDER-CALC' USING ORDER-PARAMS      *> グループ項目ごと渡す
    END-CALL

    IF OP-STATUS-CODE = 'OK'
        DISPLAY '合計金額: ' OP-TOTAL-AMT
    ELSE
        DISPLAY 'エラー: '   OP-ERROR-MSG
    END-IF
    STOP RUN.
呼び先(ORDER-CALC)でも同じCOPY句を使う
IDENTIFICATION DIVISION.
PROGRAM-ID. ORDER-CALC.

DATA DIVISION.
LINKAGE SECTION.
COPY ORDERPARM.              *> 呼び元と同一定義を展開

PROCEDURE DIVISION USING ORDER-PARAMS.
    *> 入力チェック
    IF OP-QUANTITY <= 0
        MOVE 'NG' TO OP-STATUS-CODE
        MOVE '数量は1以上を指定してください' TO OP-ERROR-MSG
        GOBACK
    END-IF

    *> 合計金額の計算(割引適用)
    COMPUTE OP-TOTAL-AMT =
        OP-UNIT-PRICE * OP-QUANTITY * (1 - OP-DISCOUNT-RT)

    MOVE 'OK' TO OP-STATUS-CODE
    MOVE SPACES TO OP-ERROR-MSG
    GOBACK.

COPYの恩恵: コピーブック(ORDERPARM.CPY)を1か所修正するだけで、CALLするすべてのプログラムに変更が反映されます。フィールドの追加・削除・桁数変更の漏れが原因のバグを防ぐ最も効果的な方法です。大規模バッチシステムでは共通インターフェース定義のコピーブックを作成するのが業界の標準的な実践です。

パラメータ設計パターン

実務のCOBOLプログラムでは引数が増えがちです。10個以上の引数を並べたCALL文は保守性が下がります。以下のパターンで引数の数をコントロールします。

パターン1: グループ項目にまとめる

関連する引数をひとつのグループ項目に集約します。最も基本的なパターンです。

NG: 引数が多い設計 / OK: グループにまとめる
*=== NG: 引数が10個並ぶ ===
CALL 'PROCESS' USING WS-CUST-ID WS-CUST-NAME WS-CUST-AGE
                     WS-ORDER-ID WS-ITEM-CODE WS-QTY WS-PRICE
                     WS-RESULT-CODE WS-ERROR-MSG WS-TIMESTAMP.

*=== OK: 顧客情報・注文情報・結果情報のグループに整理 ===
CALL 'PROCESS' USING WS-CUST-INFO     *> 顧客グループ(ID/名前/年齢)
                     WS-ORDER-INFO    *> 注文グループ(ID/コード/数量/価格)
                     WS-RESULT-INFO.  *> 結果グループ(コード/メッセージ/タイムスタンプ)

パターン2: 入出力を分離する

引数を「入力グループ」と「出力グループ」の2つに分ける設計です。BY CONTENTとBY REFERENCEの明示と合わせることで、インターフェースの意図が明確になります。

入力グループ / 出力グループ を分離
WORKING-STORAGE SECTION.
01  WS-CALC-INPUT.                  *> 入力グループ
    05  CI-AMOUNT     PIC 9(9)V99.
    05  CI-TAX-RATE   PIC V99.
    05  CI-DISCOUNT   PIC V99.
    05  CI-COUNTRY-CD PIC X(2).

01  WS-CALC-OUTPUT.                 *> 出力グループ
    05  CO-TAX-AMT    PIC 9(9)V99.
    05  CO-NET-AMT    PIC 9(9)V99.
    05  CO-TOTAL-AMT  PIC 9(10)V99.
    05  CO-STATUS     PIC X(2).

PROCEDURE DIVISION.
    CALL 'PRICE-CALC'
        USING BY CONTENT   WS-CALC-INPUT     *> 入力専用
              BY REFERENCE WS-CALC-OUTPUT    *> 出力先
    END-CALL.

パターン3: コントロールブロックで拡張可能にする

インターフェースに将来の拡張余地を持たせるパターンです。FILLERを含む「コントロールブロック」を渡し、将来的にはFILLER部分に新フィールドを追加できます。

コントロールブロックパターン
WORKING-STORAGE SECTION.
*> コントロールブロック(将来の拡張余地あり)
01  WS-CTRL-BLOCK.
    05  CB-VERSION     PIC 9(2) VALUE 01.  *> インターフェースバージョン
    05  CB-FLAGS.
        10  CB-DEBUG-FLG   PIC X VALUE 'N'.
        10  CB-TRACE-FLG   PIC X VALUE 'N'.
        10  CB-AUDIT-FLG   PIC X VALUE 'N'.
        10  FILLER         PIC X(7).       *> 将来の拡張用
    05  CB-TIMEOUT-SEC PIC 9(4) VALUE 0030.*> タイムアウト秒
    05  FILLER         PIC X(50).          *> 将来の拡張用

01  WS-INPUT-DATA     PIC X(200).
01  WS-OUTPUT-DATA    PIC X(200).
01  WS-RETURN-INFO    PIC X(10).

PROCEDURE DIVISION.
    CALL 'FLEX-SERVICE'
        USING WS-CTRL-BLOCK     *> 制御情報(常に1つ)
              WS-INPUT-DATA
              WS-OUTPUT-DATA
              WS-RETURN-INFO
    END-CALL.

パターン4: RETURN-CODEを戻り値として活用する

処理結果コードだけ返せば十分な場合は引数で結果コードを渡す必要はありません。RETURN-CODEを使うことでシグネチャをシンプルに保てます。

RETURN-CODEで結果を返し引数を削減
*=== 引数がシンプルになる設計 ===
WORKING-STORAGE SECTION.
01  WS-TARGET-DATE    PIC 9(8).
01  WS-RC-SAVE        PIC S9(9) COMP.

PROCEDURE DIVISION.
    MOVE 20260101 TO WS-TARGET-DATE

    *> 入力のみ渡し、結果はRETURN-CODEで受け取る
    CALL 'DATE-VALIDATE' USING BY CONTENT WS-TARGET-DATE
    END-CALL
    MOVE RETURN-CODE TO WS-RC-SAVE

    EVALUATE WS-RC-SAVE
        WHEN 0   DISPLAY '正常'
        WHEN 4   DISPLAY '過去の日付(警告)'
        WHEN 8   DISPLAY '無効な日付形式(エラー)'
        WHEN 12  DISPLAY '範囲外の日付(重大エラー)'
    END-EVALUATE.

よくある落とし穴と対策

① PROCEDURE DIVISION USINGとLINKAGE SECTIONの順番不一致

症状: LINKAGE SECTIONに定義した順番とPROCEDURE DIVISION USING句の並び順が異なっていても、コンパイルエラーにならない場合があります。しかし呼び元のCALL USINGとの対応がずれるため、実行時に別のデータが違う変数に入るバグが発生します。

対策: CALL USINGの引数リストと、PROCEDURE DIVISION USINGの仮引数リストを常に同じ順番に書きます。COPY句でパラメータ定義を共有すると順番のズレ自体が起きません。

② SORT USING指定ファイルを事前にOPENしてしまう

症状: SORT USING句で指定したファイルはランタイムが自動でOPENします。SORT実行前に自分でOPEN INPUT file-nameしてしまうと「ファイルが既にオープン状態です」という実行時エラーが発生します。

対策: SORT USING句で指定するファイルは、SORT文の直前にOPEN・CLOSEを行わないようにします。SORTの前後で同じファイルにアクセスしたい場合は、別の変数に読み込んでから処理します。

③ MERGE USINGで未ソートファイルを渡す

症状: MERGE文のUSING句で指定するファイルは昇順(またはON句で指定した順)にソート済みであることが前提です。未ソートのまま渡すと、出力結果が正しくマージされず、一見動いているように見えてデータの順序が壊れます。

対策: MERGE前に必ず各入力ファイルがソート済みであることを確認します。ソートが保証できない場合はMERGEでなくSORTを使い、複数ファイルをUSINGで一括ソートします。

④ OMITTEDを使った省略引数へのアクセス

症状: 呼び元がOMITTEDで省略した引数を、呼び先でADDRESS OFチェックなしにアクセスしようとするとセグメンテーション違反(不正なメモリアクセス)が発生します。NULLポインタへのアクセスと同じです。

対策: OMITTEDが来る可能性のある引数は、必ずIF ADDRESS OF 仮引数名 = NULLで省略されているかを確認してからアクセスします。

⑤ COPYで展開した定義を呼び元と呼び先で構造変更したとき

症状: コピーブックを修正した際に、そのコピーブックを使っているすべてのプログラムを再コンパイルしないと、古い定義のオブジェクトと新しい定義のオブジェクトが混在してデータ破損が起きます。特にフィールドの途中に新しいフィールドを追加した場合に起きやすいです。

対策: コピーブックを修正したら、そのコピーブックをCOPYしているすべてのプログラムを一括で再コンパイルします。フィールドを追加するときは末尾かFILLER部分への追加を基本とし、既存フィールドの位置が変わらないようにします。

よくある質問

QCALL文のUSING句で定数(リテラル)を直接渡せますか?
ABY CONTENTまたはBY VALUEを指定した場合のみリテラルを渡せます。例: CALL 'SUB' USING BY CONTENT 100 BY CONTENT 'ABC'。BY REFERENCE(デフォルト)ではリテラルを渡せません。定数を渡したい場合はWORKING-STORAGEに定数をMOVEしてからBY CONTENTで渡すか、BY CONTENTに切り替えます。
QSORT USINGとINPUT PROCEDUREはどちらを使えばよいですか?
A入力ファイルをそのままソートするだけならUSING句が最も簡潔です。ソート前にレコードのフィルタリング・加工・型変換が必要な場合はINPUT PROCEDURE(+ RELEASE文)を使います。USING句はコードが短く保守しやすい反面、前処理ができない制約があります。
Q引数の型(PIC句)が呼び元と呼び先でずれていたらどうなりますか?
Aコンパイラによってはエラーにならず、実行時に誤ったバイト数で解釈されてデータが壊れます。たとえば呼び元がPIC 9(7)V99(7バイト)で呼び先がPIC 9(9)V99(9バイト)だと、2バイト分のズレが生じて後続フィールドの値が混入します。COPY句で定義を共有することでこの問題を根本から防げます。
QPROCEDURE DIVISION USINGに書かなかったLINKAGE SECTIONの項目はどうなりますか?
ALINKAGE SECTIONに定義した項目をPROCEDURE DIVISION USINGに書かなければ、その項目はCALL時にアドレスが設定されず未定義の状態になります。誤ってアクセスすると不正メモリアクセスが発生します。LINKAGE SECTIONの項目は必ずPROCEDURE DIVISION USINGに列挙し、CALLで対応する引数を渡してください。
Qサブプログラムから別のサブプログラムをCALLするときもUSING句の仕様は同じですか?
Aはい、同じです。サブプログラムがさらに別のサブプログラムをCALLする場合も、呼び元→サブ→サブのサブという連鎖で同じUSING句のルールが適用されます。自分のLINKAGE SECTIONで受け取った引数をそのまま次のCALLに渡すこともできます(BY REFERENCEなら同じアドレスが連鎖して渡ります)。

まとめ

機能 概要 主な用途
CALL文のUSING句 引数を呼び先に渡す。BY REFERENCE(デフォルト)/ BY CONTENT / BY VALUE 引数渡しの主な場面
PROCEDURE DIVISION USING句 LINKAGE SECTIONの仮引数をCALL USINGの順番で列挙する サブプログラムの引数受け取り
SORT文のUSING句 複数の入力ファイルを列挙。ランタイムが自動でOPEN/READ 入力ファイルをそのままソートしたい場合
MERGE文のUSING句 ソート済みファイルを複数指定してマージ 複数リージョン・期間のファイルを統合
OMITTED 省略を明示。呼び先でADDRESS OF = NULLで検出 オプション引数の実装
COPY句での共有 コピーブックに定義を一元管理してCALL/PROCEDURE双方で展開 型不一致バグの根本予防
グループ統合パターン 関連引数をグループ項目にまとめてCALLを簡潔に 引数が多すぎるインターフェースの改善

USING句はCALL文とPROCEDURE DIVISIONのペアで機能する引数渡しが主役ですが、SORT/MERGEでは入力ファイル指定という全く別の役割も持ちます。COPY句による定義の共有とOMITTEDによる省略可能引数を組み合わせると、保守性と柔軟性の高いインターフェース設計が実現できます。

引数の渡し方(BY REFERENCE / BY CONTENT / BY VALUE)とLINKAGE SECTIONの詳細は引数の使い方完全ガイドを、CALL文の動的/静的・CANCEL・ネストプログラムはCALL文完全ガイドを合わせてご参照ください。