4 Divisionの構造と役割

COBOLのソースファイルは必ず4つのDivisionを順番に持ちます(省略可能なものもありますが、実務では全て記述されることがほとんどです)。 各Divisionの役割を把握することが、コード全体の見取り図を作る第一歩です。

COBOL — 基本構造
       IDENTIFICATION DIVISION.
       PROGRAM-ID. SAMPLE-PGM.
       AUTHOR.    DEVNOTES.
       DATE-WRITTEN. 2026-06-02.

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT INFILE  ASSIGN TO 'INPUT.DAT'.
           SELECT OUTFILE ASSIGN TO 'OUTPUT.DAT'.

       DATA DIVISION.
       FILE SECTION.
       FD  INFILE.
       01  IN-RECORD  PIC X(80).
       WORKING-STORAGE SECTION.
       01  WS-FLAG    PIC X(1) VALUE 'N'.
       COPY COMMON-AREA.

       PROCEDURE DIVISION.
       MAIN-PARA.
           PERFORM INIT-PARA
           PERFORM PROCESS-PARA UNTIL WS-FLAG = 'Y'
           PERFORM END-PARA
           STOP RUN.
       INIT-PARA.
           OPEN INPUT INFILE OUTPUT OUTFILE.
       PROCESS-PARA.
           READ INFILE AT END MOVE 'Y' TO WS-FLAG.
       END-PARA.
           CLOSE INFILE OUTFILE.
DivisionSection(代表例)記述内容
IDENTIFICATIONPROGRAM-ID・AUTHOR・DATE-WRITTEN など識別情報
ENVIRONMENTCONFIGURATION / INPUT-OUTPUT動作環境・ファイル割り当て(SELECT〜ASSIGN)
DATAFILE / WORKING-STORAGE / LINKAGE変数・レコード定義。COPYによる共有定義のインクルード
PROCEDURESection(任意)/ Paragraph処理ロジック。PERFORMとCALL文が依存の核心

COPY句による依存関係

COPY 句は外部の「コピーブック(.CPY / .CBL)」をソースに展開するディレクティブです。 複数プログラムで共有するレコード定義・定数を一元管理するために使われます。 Javaの import に相当しますが、コンパイル時にテキスト展開されるため静的解析で検出しやすいのが特徴です。

COBOL — COPY句の種類
       * 基本的なCOPY句(コピーブック名 = COMMON-AREA.CPY を展開)
       COPY COMMON-AREA.

       * REPLACING で展開時に文字列置換する
       COPY CUSTOMER-REC REPLACING ==:PREFIX:== BY ==WS==.

       * ライブラリ名を指定(環境依存)
       COPY ORDREC OF PRODLIB.

💡 COPY句抽出の正規表現

COPY\s+([A-Z0-9\-]+) でコピーブック名を抽出できます。REPLACING 以降は無視してOKです。

CALL文による依存関係

CALL文は外部COBOLプログラム(または他言語のサブルーチン)を実行します。 Javaの外部クラス呼び出しに相当し、プログラム間依存のエッジを構成します。

COBOL — CALL文の種類
       * 静的CALL(リテラル指定 — 静的解析で検出しやすい)
       CALL 'SUBPGM01' USING WS-DATA.

       * 動的CALL(変数指定 — 実行時まで対象が決まらない)
       MOVE 'SUBPGM02' TO WS-PGM-NAME.
       CALL WS-PGM-NAME USING WS-DATA.

       * ON EXCEPTION 句(エラーハンドリング付き)
       CALL 'ERRPGM' USING WS-ERR-CODE
           ON EXCEPTION
               DISPLAY 'CALL FAILED'
           END-CALL.

⚠️ 動的CALLの注意点

変数によるCALL(動的CALL)は静的解析では検出できません。変数に格納される値をトレースする必要があります。PART 03 で詳述します。

PlantUMLでDivision構造図を描く

抽出した情報をPlantUMLのコンポーネント図として記述することで、1プログラム内の構造を視覚化できます。

PlantUML — Division構造図
@startuml
package "SAMPLE-PGM" {
  package "IDENTIFICATION DIVISION" {
    [PROGRAM-ID: SAMPLE-PGM]
    [DATE-WRITTEN: 2026-06-02]
  }
  package "ENVIRONMENT DIVISION" {
    [FILE-CONTROL]
    [SELECT INFILE]
    [SELECT OUTFILE]
  }
  package "DATA DIVISION" {
    [WORKING-STORAGE SECTION]
    [WS-FLAG]
  }
  package "PROCEDURE DIVISION" {
    [MAIN-PARA]
    [INIT-PARA]
    [PROCESS-PARA]
    [END-PARA]
    [MAIN-PARA] --> [INIT-PARA] : PERFORM
    [MAIN-PARA] --> [PROCESS-PARA] : PERFORM UNTIL
    [MAIN-PARA] --> [END-PARA] : PERFORM
  }
}

' 外部依存
database "COMMON-AREA.CPY" as CPY
[WORKING-STORAGE SECTION] ..> CPY : COPY

component "SUBPGM01" as SUB
[PROCESS-PARA] --> SUB : CALL
@enduml

Mermaidで依存関係図を描く

複数プログラム間の依存関係はMermaidのフローチャートで表現するとシンプルです。 GitHubやNotion上でそのままレンダリングされるため、ドキュメント共有に適しています。

Mermaid — プログラム間依存図
graph TD
    MAIN["MAIN-PGM
メイン処理"] SUB1["SUBPGM01
データ検証"] SUB2["SUBPGM02
ファイル出力"] CPY1["COMMON-AREA.CPY
共通領域"] CPY2["CUSTOMER-REC.CPY
顧客レコード"] MAIN -->|CALL| SUB1 MAIN -->|CALL| SUB2 MAIN -.->|COPY| CPY1 SUB1 -.->|COPY| CPY2 SUB2 -.->|COPY| CPY1

依存情報の抽出方法

実際のCOBOLソースから依存情報を抽出するには、Pythonで正規表現を使うのが最も手軽です。

Python — COPY句・CALL文の抽出
import re
from pathlib import Path

def extract_dependencies(cobol_file: Path) -> dict:
    """COBOLソースからCOPY句とCALL文を抽出する"""
    text = cobol_file.read_text(encoding='utf-8', errors='replace').upper()

    # COPY句: COPY XXXXXXXX (REPLACING以降は無視)
    copies = re.findall(
        r'^\s{6,}\bCOPY\s+([A-Z0-9\-]+)',
        text, re.MULTILINE
    )

    # 静的CALL: CALL 'XXXXXXXX'
    static_calls = re.findall(
        r'^\s{6,}\bCALL\s+[\'"]([A-Z0-9\-]+)[\'"]',
        text, re.MULTILINE
    )

    # 動的CALL: CALL 変数名(変数名を記録)
    dynamic_calls = re.findall(
        r'^\s{6,}\bCALL\s+([A-Z0-9\-]+)(?!\s*[\'"])',
        text, re.MULTILINE
    )

    return {
        'program': cobol_file.stem,
        'copies':        list(set(copies)),
        'static_calls':  list(set(static_calls)),
        'dynamic_calls': list(set(dynamic_calls)),
    }

# 使用例
for src in Path('src').glob('**/*.cbl'):
    deps = extract_dependencies(src)
    print(deps)

次の章では…

PART 03 では Paragraph Call Graph — PERFORM文による呼び出し連鎖の静的解析と、動的CALLへの対処法を解説します。

→ PART 03 Paragraph Call Graph へ