COBOLで「制御を戻す」命令にはRETURN・GOBACK・EXIT PROGRAM・EXITの4系統があります。中でもRETURN文はSORT/MERGEのOUTPUT PROCEDUREでソート済みレコードを1件ずつ取り出す専用命令であり、サブプログラムの終了に使うGOBACK・EXIT PROGRAMとは用途がまったく異なります。
この記事では各命令の正確な用途と使い分けを解説します。SORT/MERGEでのRETURN文の実践パターン、RETURNING句による戻り値の受け渡し、EXIT SECTION/PARAGRAPHを使った段落からの早期脱出まで網羅します。CALLの仕組みやGOBACK/STOP RUNの詳細についてはCALL文完全ガイドもあわせて参照してください。
- RETURN文の正確な用途(SORT/MERGEのOUTPUT PROCEDUREでのレコード取り出し)
- GOBACK・EXIT PROGRAM・STOP RUNの使い分けと選択基準
- RETURNING句でサブプログラムから計算値を返す方法
- EXIT SECTION・EXIT PARAGRAPHで段落・セクションから早期脱出する方法
- SORT/MERGE + OUTPUT PROCEDURE + RETURNの実践パターン
COBOLの「制御を戻す」命令 全体像
COBOLには「制御を移す・戻す」命令が複数ありますが、それぞれ用途が異なります。混同すると重大なバグになるため、まず全体像を把握しておきましょう。
| 命令 | 動作 | 使いどころ |
|---|---|---|
| RETURN | SORT/MERGEのOUTPUT PROCEDUREで、ソート済みファイルから1レコード取り出す | SORT/MERGE OUTPUT PROCEDUREの内部のみ |
| GOBACK | サブプログラム→呼び元に制御を返す。メインプログラムならジョブ終了 | サブプログラムの終了(推奨) |
| EXIT PROGRAM | GOBACKと同じ効果。COBOL 74/85スタイルの旧構文 | 旧システムの保守。新規はGOBACK推奨 |
| STOP RUN | どこから実行してもジョブ全体を終了する | メインプログラムの最終終了のみ |
| EXIT SECTION | 現在のセクションの終端へジャンプし、セクションを抜ける | セクション内の早期脱出 |
| EXIT PARAGRAPH | 現在の段落の終端へジャンプし、段落を抜ける | 段落内の早期脱出 |
| EXIT PERFORM | インラインPERFORMループを強制終了(break相当) | ループからの早期脱出(698参照) |
「RETURN = 呼び元に戻る」はJavaやPythonでの概念です。COBOLのRETURN文はSORT/MERGE専用命令です。サブプログラムを終了して呼び元に制御を戻すにはGOBACKを使います。旧来のCOBOLコードでは誤った説明が散見されますが、標準COBOLの仕様ではRETURNとGOBACKは別物です。
RETURN文の正確な用途(SORT/MERGE OUTPUT PROCEDURE)
RETURN文はSORT文またはMERGE文にOUTPUT PROCEDURE句を指定したときに使います。ソート済みのレコードを1件ずつ取り出し、加工・出力処理を行うためのものです。
RETURN ソートファイル名 RECORD
[INTO 転記先データ名]
AT END 終端処理
[NOT AT END 通常処理]
[END-RETURN].
| 句 | 説明 |
|---|---|
| RETURN ソートファイル名 RECORD | SORT/MERGEで処理されたファイルから次の1レコードを取り出す |
| INTO 転記先データ名 | レコードをWORKING-STORAGEの変数に転記する(省略時はFDのレコード領域に格納) |
| AT END | 全レコードを取り出し終わったときに実行する処理(ループ終了フラグのセットなど) |
| NOT AT END | レコードが取り出せた場合に実行する処理(省略可) |
| END-RETURN | RETURNブロックの終端。AT END/NOT AT ENDを使う場合は必須 |
FILE SECTION.
FD WORK-SORT-FILE.
01 WS-SORT-REC.
05 WS-DEPT-CODE PIC X(4).
05 WS-EMP-NO PIC 9(6).
05 WS-SALARY PIC 9(8)V99.
WORKING-STORAGE SECTION.
01 WS-EOF-FLAG PIC X(1) VALUE 'N'.
88 WS-EOF VALUE 'Y'.
01 WS-WORK-REC.
05 WK-DEPT PIC X(4).
05 WK-EMP-NO PIC 9(6).
05 WK-SALARY PIC 9(8)V99.
PROCEDURE DIVISION.
MAIN-LOGIC.
SORT WORK-SORT-FILE
ON ASCENDING KEY WS-DEPT-CODE
ON ASCENDING KEY WS-EMP-NO
USING INPUT-FILE *> 入力ファイルを自動READ(INPUT PROCEDURE不要)
OUTPUT PROCEDURE PROCESS-SORTED-DATA
STOP RUN.
*=== OUTPUT PROCEDURE: ソート後の処理 ===
PROCESS-SORTED-DATA SECTION.
MOVE 'N' TO WS-EOF-FLAG
*> 最初の1件を取り出す(プライミングリード)
PERFORM GET-NEXT-RECORD
PERFORM UNTIL WS-EOF
*> 取り出したレコードを処理
PERFORM PROCESS-ONE-RECORD
PERFORM GET-NEXT-RECORD
END-PERFORM.
GET-NEXT-RECORD.
RETURN WORK-SORT-FILE RECORD INTO WS-WORK-REC
AT END
MOVE 'Y' TO WS-EOF-FLAG
NOT AT END
CONTINUE
END-RETURN.
PROCESS-ONE-RECORD.
DISPLAY WK-DEPT ' ' WK-EMP-NO ' ' WK-SALARY.
- INPUT PROCEDURE: ソート前にレコードを加工する処理。
RELEASE文でソートファイルに書き込む - OUTPUT PROCEDURE: ソート後にレコードを処理する場所。
RETURN文で1件ずつ取り出す - USING/GIVING: 加工不要の場合はUSING(入力ファイル直接指定)/GIVING(出力ファイル直接指定)で省略できる
RETURN文はOUTPUT PROCEDURE内でのみ有効です。通常のPROCEDURE DIVISIONで使うとコンパイルエラーになります。
GOBACKとEXIT PROGRAM
サブプログラムを終了して呼び元に制御を返すにはGOBACKまたはEXIT PROGRAMを使います。両者は動作がほぼ同じですが、細かい違いがあります。
| 命令 | 歴史 | 動作 | 使いどころ |
|---|---|---|---|
| GOBACK | COBOL 74以降の標準構文 | サブ→呼び元へ戻る。メインではジョブ終了 | メイン・サブ両方で使える。現代COBOLの推奨 |
| EXIT PROGRAM | COBOL 74の旧スタイル | サブ→呼び元へ戻る。メインでは何もしない(fallthrough) | 旧システムの保守時のみ。新規記述にはGOBACK |
| STOP RUN | COBOL 60代からある古い構文 | 必ずジョブ全体を終了。どのプログラムから呼んでも同じ | メインの最終終了のみ。サブで使用禁止 |
*=== EXIT PROGRAMの注意点 ===
* EXIT PROGRAMをメインプログラムで使うと何も起きない(fallthrough)
* GOBACK をメインで使うとジョブが終了する
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN-PGM.
PROCEDURE DIVISION.
CALL 'SUB-PGM'
DISPLAY '呼び元に戻りました'
STOP RUN. *> メインの終了はSTOP RUN
*----------------------------------
IDENTIFICATION DIVISION.
PROGRAM-ID. SUB-PGM.
PROCEDURE DIVISION.
DISPLAY 'サブプログラム実行中'
*> OK: GOBACKで呼び元に戻る
GOBACK.
*> 旧スタイル: EXIT PROGRAMでも同じ動作
*EXIT PROGRAM.
*> NG: サブでSTOP RUNを使うとジョブ全体が終了する
*STOP RUN.
EXIT PROGRAMはサブプログラムを終了して呼び元に戻る命令です。一方、EXIT(単独)は何もしない空命令で、段落の最後に書くマーカーとして使われます。EXIT SECTIONはセクション脱出、EXIT PARAGRAPHは段落脱出です。「EXIT」という単語が含まれていても意味がまったく異なるため、混同しないように注意してください。GOBACKとEND PROGRAMの関係
COBOL 85以降ではEND PROGRAM プログラム名.でプログラムを明示的に終端できます。GOBACKとEND PROGRAMはそれぞれ独立した概念です。
*=== 単体プログラム(ネストなし)===
IDENTIFICATION DIVISION.
PROGRAM-ID. SINGLE-PGM.
PROCEDURE DIVISION.
DISPLAY '処理実行'
GOBACK. *> 制御を返す(呼ばれていればCALL元へ、トップレベルならジョブ終了)
END PROGRAM SINGLE-PGM. *> ソースの終端マーカー(省略可)
*=== ネストプログラム使用時 ===
IDENTIFICATION DIVISION.
PROGRAM-ID. OUTER-PGM.
PROCEDURE DIVISION.
CALL 'INNER-PGM'
STOP RUN. *> 親プログラムの終了
IDENTIFICATION DIVISION.
PROGRAM-ID. INNER-PGM.
PROCEDURE DIVISION.
DISPLAY '内部プログラム'
GOBACK. *> 親プログラムに制御を返す
END PROGRAM INNER-PGM. *> ネストプログラムではEND PROGRAMが必須
END PROGRAM OUTER-PGM.
| パターン | 挙動 |
|---|---|
| GOBACKあり + END PROGRAMあり | 通常の書き方。GOBACKで制御を返し、END PROGRAMでソース終端を明示。ネストプログラムでは必須 |
| GOBACKあり + END PROGRAMなし | 単独プログラムなら問題なし。ネストプログラムを使う場合はEND PROGRAMが必須 |
| GOBACKなし + END PROGRAMあり | PROCEDURE DIVISIONの末尾に達したとき、暗黙的にGOBACKと同じ動作になる(フォールスルー終了)。明示的なGOBACKを書く方が推奨 |
| STOP RUN + END PROGRAMあり | STOP RUNがGOBACKより先に実行されるためEND PROGRAMに意味はなくなるが、ソース構造上の終端マーカーとして書いても問題なし |
RETURNING句でサブプログラムから値を返す
COBOL 2002以降の標準規格では、CALL文にRETURNING句を使ってサブプログラムから値を受け取れます。RETURN-CODEを介したコード伝播とは異なり、任意のデータ型で値を返せます。
*=== 呼び元 ===
WORKING-STORAGE SECTION.
01 WS-INPUT-VAL PIC 9(7)V99.
01 WS-TAX-RESULT PIC 9(7)V99.
PROCEDURE DIVISION.
MOVE 10000.00 TO WS-INPUT-VAL
CALL 'CALC-TAX'
USING BY CONTENT WS-INPUT-VAL
RETURNING WS-TAX-RESULT *> サブの戻り値をWS-TAX-RESULTに受け取る
END-CALL
DISPLAY '税額: ' WS-TAX-RESULT
STOP RUN.
*=== サブプログラム ===
IDENTIFICATION DIVISION.
PROGRAM-ID. CALC-TAX.
DATA DIVISION.
LINKAGE SECTION.
01 LK-AMOUNT PIC 9(7)V99.
01 LK-TAX-OUT PIC 9(7)V99. *> RETURNING で返す変数
PROCEDURE DIVISION USING LK-AMOUNT
RETURNING LK-TAX-OUT.
COMPUTE LK-TAX-OUT ROUNDED = LK-AMOUNT * 0.10
GOBACK.
- COBOL 2002以降の標準機能。IBM z/OS COBOLでは対応状況がバージョン依存のため事前確認が必要
- GnuCOBOL(旧OpenCOBOL)では使用可能
- RETURNING句に指定する変数はLINKAGE SECTIONの最後の項目に対応する
- 互換性が心配な環境ではUSING BY REFERENCE + RETURN-CODEの組み合わせを使う方が確実
PERFORM…RETURNINGで段落から値を返す
COBOL 2002以降では、PERFORM文にもRETURNINGを使って段落・セクションから値を返せます(関数スタイルの呼び出し)。ただしこれも実装依存度が高い機能です。
WORKING-STORAGE SECTION.
01 WS-RADIUS PIC 9(5)V99 VALUE 5.00.
01 WS-AREA PIC 9(9)V99.
PROCEDURE DIVISION.
PERFORM CALC-CIRCLE-AREA
USING BY CONTENT WS-RADIUS
RETURNING WS-AREA
DISPLAY '面積: ' WS-AREA
STOP RUN.
CALC-CIRCLE-AREA SECTION.
*> このスタイルはCOBOL 2002+かつ実装依存
*> 汎用性が必要な場合はCALLによる外部サブプログラムを推奨
COMPUTE WS-AREA = 3.14159 * WS-RADIUS * WS-RADIUS
EXIT SECTION.
PERFORM…RETURNING構文はCOBOL 2002以降の標準に含まれますが、IBM z/OS COBOLやMicro Focus COBOLなど主要な商用コンパイラではサポート状況がバージョンによって異なります。実際の業務システムで安全に値を返すには、サブプログラム(外部CALL)+ USING BY REFERENCEで結果用変数を直接書き換えるパターンか、CALL…RETURNINGを使うのが確実です。
EXIT SECTIONとEXIT PARAGRAPHによる早期脱出
PERFORMのループ内ではEXIT PERFORMを使いますが、セクションや段落の中での条件分岐による早期脱出にはEXIT SECTION/EXIT PARAGRAPHを使います。
PROCEDURE DIVISION.
PERFORM VALIDATE-INPUT-SECTION
IF RETURN-CODE = 8
DISPLAY '入力エラーで中断'
STOP RUN
END-IF
PERFORM PROCESS-DATA-SECTION
STOP RUN.
*=== セクション内でEXIT SECTIONを使ったガード節 ===
VALIDATE-INPUT-SECTION SECTION.
*--- バリデーション開始 ---
IF WS-INPUT-DATA = SPACES
MOVE 8 TO RETURN-CODE
EXIT SECTION *> セクションの末尾にジャンプして抜ける
END-IF
IF WS-AMOUNT NOT NUMERIC
MOVE 8 TO RETURN-CODE
EXIT SECTION
END-IF
IF WS-DATE(1:4) < '2000'
MOVE 8 TO RETURN-CODE
EXIT SECTION
END-IF
*--- 全バリデーション通過 ---
MOVE 0 TO RETURN-CODE.
VALIDATE-END.
EXIT.
PROCEDURE DIVISION.
PERFORM CHECK-RECORD
...
CHECK-RECORD.
*> 削除フラグが立っていたらスキップ
IF WS-DEL-FLAG = 'D'
EXIT PARAGRAPH *> この段落の残り処理をスキップ
END-IF
*> 金額が0以下もスキップ
IF WS-AMOUNT <= 0
EXIT PARAGRAPH
END-IF
*> 正常レコードの処理
ADD WS-AMOUNT TO WS-TOTAL
ADD 1 TO WS-COUNT.
| 命令 | 動作 | 使いどころ |
|---|---|---|
| EXIT SECTION | セクション(SECTION)の末尾にジャンプする | PERFORMで呼んだSECTION内での早期脱出。バリデーションのガード節に便利 |
| EXIT PARAGRAPH | 段落(パラグラフ)の末尾にジャンプする | PERFORMで呼んだ段落内での早期脱出。レコードのスキップ処理などに便利 |
| EXIT | 何もしない空命令(ダミー文) | 段落の終端マーカーとして書く。PERFORMの対象段落として正しく認識させるための構文上の工夫 |
| EXIT PERFORM | インラインPERFORMのループを強制終了(break相当) | ループ内の早期終了。PERFORM文の詳細は698参照 |
| EXIT PERFORM CYCLE | インラインPERFORMの次の反復へスキップ(continue相当) | ループ内の処理スキップ。PERFORM文の詳細は698参照 |
実践パターン
売上データのソートと集計(SORT + RETURN)
部門コードと社員番号でソートした売上レコードを、OUTPUT PROCEDUREの中でRETURNしながら部門別小計を集計するパターンです。
FILE SECTION.
FD SORT-SALES-FILE.
01 SS-REC.
05 SS-DEPT PIC X(4).
05 SS-EMP PIC 9(6).
05 SS-AMOUNT PIC 9(8)V99.
WORKING-STORAGE SECTION.
01 WS-EOF PIC X(1) VALUE 'N'.
88 EOF-REACHED VALUE 'Y'.
01 WS-WORK-REC.
05 WK-DEPT PIC X(4).
05 WK-EMP PIC 9(6).
05 WK-AMOUNT PIC 9(8)V99.
01 WS-PREV-DEPT PIC X(4) VALUE SPACES.
01 WS-SUBTOTAL PIC 9(10)V99 VALUE 0.
01 WS-GRAND-TOT PIC 9(12)V99 VALUE 0.
PROCEDURE DIVISION.
MAIN-LOGIC.
OPEN INPUT SALES-FILE
SORT SORT-SALES-FILE
ON ASCENDING KEY SS-DEPT
ON ASCENDING KEY SS-EMP
INPUT PROCEDURE LOAD-SORT-DATA
OUTPUT PROCEDURE CALC-SUBTOTAL
CLOSE SALES-FILE
DISPLAY '総合計: ' WS-GRAND-TOT
STOP RUN.
*=== INPUT PROCEDURE: RELEASE でソートファイルに送る ===
LOAD-SORT-DATA SECTION.
READ SALES-FILE INTO WS-WORK-REC
AT END MOVE 'Y' TO WS-EOF
END-READ
PERFORM UNTIL EOF-REACHED
RELEASE SS-REC FROM WS-WORK-REC
READ SALES-FILE INTO WS-WORK-REC
AT END MOVE 'Y' TO WS-EOF
END-READ
END-PERFORM.
LOAD-END. EXIT.
*=== OUTPUT PROCEDURE: RETURN でソート済みレコードを取り出す ===
CALC-SUBTOTAL SECTION.
MOVE 'N' TO WS-EOF
RETURN SORT-SALES-FILE RECORD INTO WS-WORK-REC
AT END MOVE 'Y' TO WS-EOF
END-RETURN
PERFORM UNTIL EOF-REACHED
IF WS-PREV-DEPT NOT = WK-DEPT
*> 部門切り替わり→前の部門の小計を出力
IF WS-PREV-DEPT NOT = SPACES
DISPLAY '部門 ' WS-PREV-DEPT ' 小計: ' WS-SUBTOTAL
END-IF
MOVE WK-DEPT TO WS-PREV-DEPT
MOVE 0 TO WS-SUBTOTAL
END-IF
ADD WK-AMOUNT TO WS-SUBTOTAL WS-GRAND-TOT
RETURN SORT-SALES-FILE RECORD INTO WS-WORK-REC
AT END MOVE 'Y' TO WS-EOF
END-RETURN
END-PERFORM
*> 最終部門の小計を出力
IF WS-PREV-DEPT NOT = SPACES
DISPLAY '部門 ' WS-PREV-DEPT ' 小計: ' WS-SUBTOTAL
END-IF.
CALC-END. EXIT.
RETURNINGで計算結果を返す(消費税計算モジュール)
RETURNING句を使って消費税計算モジュールから税額と税込み価格を返す実装例です。複数の値を返す場合はUSING + BY REFERENCEが確実ですが、単一値の返却パターンとして参考にしてください。
*=== 呼び元: メインプログラム ===
WORKING-STORAGE SECTION.
01 WS-PRICE-INFO.
05 WS-BASE-PRICE PIC 9(7)V99. *> 税抜き価格
05 WS-TAX-RATE PIC V99. *> 税率(0.10 = 10%)
05 WS-TAX-AMOUNT PIC 9(7)V99. *> 計算後: 税額
05 WS-TOTAL-PRICE PIC 9(7)V99. *> 計算後: 税込み価格
PROCEDURE DIVISION.
MOVE 50000.00 TO WS-BASE-PRICE
MOVE 0.10 TO WS-TAX-RATE
*> BY REFERENCEでグループ項目を渡すと税額・税込みが書き戻される
CALL 'TAX-CALC'
USING BY REFERENCE WS-PRICE-INFO
END-CALL
DISPLAY '税抜: ' WS-BASE-PRICE
DISPLAY '税額: ' WS-TAX-AMOUNT
DISPLAY '税込: ' WS-TOTAL-PRICE
STOP RUN.
*=== サブプログラム: TAX-CALC ===
IDENTIFICATION DIVISION.
PROGRAM-ID. TAX-CALC.
DATA DIVISION.
LINKAGE SECTION.
01 LK-PRICE-INFO.
05 LK-BASE-PRICE PIC 9(7)V99.
05 LK-TAX-RATE PIC V99.
05 LK-TAX-AMOUNT PIC 9(7)V99.
05 LK-TOTAL-PRICE PIC 9(7)V99.
PROCEDURE DIVISION USING LK-PRICE-INFO.
COMPUTE LK-TAX-AMOUNT ROUNDED =
LK-BASE-PRICE * LK-TAX-RATE
COMPUTE LK-TOTAL-PRICE =
LK-BASE-PRICE + LK-TAX-AMOUNT
MOVE 0 TO RETURN-CODE
GOBACK.
EXIT SECTIONを使った多段バリデーション
入力ファイルのレコードに対して複数のバリデーションを行い、いずれかに違反したら即座にEXIT SECTIONで抜けるパターンです。ネストが深くなることなく、条件が明確になります。
WORKING-STORAGE SECTION.
01 WS-INPUT-REC.
05 WS-CUST-ID PIC 9(8).
05 WS-AMOUNT PIC S9(9)V99 COMP-3.
05 WS-TRX-DATE PIC X(8).
05 WS-TRX-TYPE PIC X(2).
01 WS-VALID-FLAG PIC X(1) VALUE 'Y'.
88 INPUT-VALID VALUE 'Y'.
01 WS-ERR-MSG PIC X(80).
PROCEDURE DIVISION.
READ INPUT-FILE INTO WS-INPUT-REC
AT END MOVE 'N' TO WS-EOF-FLAG
END-READ
PERFORM UNTIL WS-EOF
MOVE 'Y' TO WS-VALID-FLAG
MOVE SPACES TO WS-ERR-MSG
PERFORM VALIDATE-RECORD-SECTION
IF INPUT-VALID
PERFORM PROCESS-VALID-RECORD
ELSE
DISPLAY 'NG: ' WS-CUST-ID ' ' WS-ERR-MSG
ADD 1 TO WS-ERR-COUNT
END-IF
READ INPUT-FILE INTO WS-INPUT-REC
AT END MOVE 'N' TO WS-EOF-FLAG
END-READ
END-PERFORM
STOP RUN.
VALIDATE-RECORD-SECTION SECTION.
*--- ① 顧客IDの数値チェック ---
IF WS-CUST-ID NOT NUMERIC
MOVE 'N' TO WS-VALID-FLAG
MOVE '顧客IDが数値ではありません' TO WS-ERR-MSG
EXIT SECTION *> 以降のチェックをスキップ
END-IF
*--- ② 金額の符号チェック ---
IF WS-AMOUNT < 0
MOVE 'N' TO WS-VALID-FLAG
MOVE '金額がマイナスです' TO WS-ERR-MSG
EXIT SECTION
END-IF
*--- ③ 日付形式チェック ---
IF WS-TRX-DATE(5:2) > '12'
MOVE 'N' TO WS-VALID-FLAG
MOVE '日付の月部分が不正です' TO WS-ERR-MSG
EXIT SECTION
END-IF
*--- ④ 取引種別コードチェック ---
IF WS-TRX-TYPE NOT = '01' AND
WS-TRX-TYPE NOT = '02' AND
WS-TRX-TYPE NOT = '03'
MOVE 'N' TO WS-VALID-FLAG
MOVE '不正な取引種別コードです' TO WS-ERR-MSG
EXIT SECTION
END-IF
*--- 全チェック通過 ---
VALIDATE-END.
EXIT.
複数ファイルのマージと出力(MERGE + RETURN)
MERGE文でも同様にRETURNを使って処理結果を取り出せます。複数の既にソート済みのファイルを結合して出力するパターンです。
FILE SECTION.
FD MERGE-WORK-FILE.
01 MW-REC.
05 MW-DATE PIC X(8).
05 MW-LOG-LVL PIC X(5).
05 MW-MESSAGE PIC X(100).
WORKING-STORAGE SECTION.
01 WS-MERGE-EOF PIC X VALUE 'N'.
88 MERGE-EOF VALUE 'Y'.
01 WS-MERGE-REC.
05 WM-DATE PIC X(8).
05 WM-LOG-LVL PIC X(5).
05 WM-MSG PIC X(100).
PROCEDURE DIVISION.
OPEN OUTPUT MERGED-LOG-FILE
*> 2つのソート済みログファイルを日付順にマージ
MERGE MERGE-WORK-FILE
ON ASCENDING KEY MW-DATE
ON ASCENDING KEY MW-LOG-LVL
USING LOG-FILE-A LOG-FILE-B *> 複数ファイル指定可能
OUTPUT PROCEDURE WRITE-MERGED-LOG
CLOSE MERGED-LOG-FILE
STOP RUN.
WRITE-MERGED-LOG SECTION.
MOVE 'N' TO WS-MERGE-EOF
RETURN MERGE-WORK-FILE RECORD INTO WS-MERGE-REC
AT END MOVE 'Y' TO WS-MERGE-EOF
END-RETURN
PERFORM UNTIL MERGE-EOF
*> ERRORレベルのログだけ出力ファイルに書き出す
IF WM-LOG-LVL = 'ERROR'
WRITE MERGED-LOG-REC FROM WS-MERGE-REC
END-IF
RETURN MERGE-WORK-FILE RECORD INTO WS-MERGE-REC
AT END MOVE 'Y' TO WS-MERGE-EOF
END-RETURN
END-PERFORM.
MERGE-END.
EXIT.
よくある落とし穴と対策
| 落とし穴 | 症状 | 対策 |
|---|---|---|
| RETURN文をサブプログラムの終了に使う | 構文エラーまたは意図しない動作になる。RETURN文はSORT/MERGE専用であり、サブプログラムの終了には使えない | サブプログラムの終了はGOBACKを使う |
| EXIT PROGRAMをメインで使い、ジョブが終了しない | EXIT PROGRAMはメインプログラムで実行すると何もしない。STATEMENTが続く場合そのままフォールスルーする | メインプログラムの終了はSTOP RUNを使う。GOBACKもメインではジョブ終了なので使える |
| EXIT SECTIONとEXIT PERFORMを混同する | EXIT SECTIONはPERFORMで呼んだSECTIONから抜けるが、EXIT PERFORMはインラインPERFORMループを終了させる。用途が異なる | 脱出したい範囲に応じて命令を使い分ける |
| RETURN文のAT END処理でEOFフラグをセットし忘れる | AT ENDが実行されてもRETURNループが終了しない。無限ループになる | AT ENDの中で必ずEOFフラグをセットし、PERFORMの終了条件として使う |
| RETURNING句の互換性を確認せずに使う | COBOL 2002+の機能のため、旧コンパイラではコンパイルエラーになる。特にIBM z/OS COBOLはバージョン依存 | 使用前にコンパイラのバージョンと対応状況を確認する。不安な場合はUSING BY REFERENCEで代替する |
よくある質問
まとめ
COBOLで「制御を戻す」命令は用途ごとに使い分けが重要です。
| 命令/構文 | 用途・ポイント |
|---|---|
| RETURN | SORT/MERGE OUTPUT PROCEDUREでの1件取り出し。サブ終了には使えない |
| GOBACK | サブプログラムの終了・呼び元への制御返却。新規記述の推奨 |
| EXIT PROGRAM | GOBACKと同等の旧スタイル。メインでは何もしない点に注意 |
| STOP RUN | ジョブ全体の終了。メインの最終行のみ。サブ使用禁止 |
| EXIT SECTION | PERFORMで呼んだセクションから早期脱出。ガード節パターンに有効 |
| EXIT PARAGRAPH | PERFORMで呼んだ段落から早期脱出。スキップ処理に有効 |
| RETURNING句 | CALL文でサブからの戻り値を受け取る(COBOL 2002+。環境依存に注意) |
特にRETURN文はSORT/MERGE専用という点を押さえておきましょう。サブプログラムの終了にはGOBACK、複雑なCALL連鎖の設計についてはCALL文完全ガイドをあわせて参照してください。
SORT/MERGEのINPUT PROCEDUREで使うRELEASE文と組み合わせることで、ソート前後の加工処理を柔軟に実装できます。OUTPUT PROCEDUREを使ったRETURNパターンは、部門別小計・フィルタリング出力・マージ処理など実業務で頻繁に登場します。