Skip to content

Mainframe COBOL Decoder

FieldValue
TypeSkill Resource
Source~/.copilot/skills/architecture/references/discovery/mainframe-cobol.md
DescriptionNot specified

Source Content

Mainframe COBOL Decoder

A field guide for reading z/OS COBOL batch systems — the language, the record layouts, the job control, and the file systems underneath. Read this before phase 2 when the platform family is mainframe.

Contents

The stack in one paragraph

A mainframe (IBM Z running z/OS) runs work two ways: batch — programs launched by JCL that read and write datasets — and online — interactive transactions under CICS or IMS (CICS has its own decoder, references/cics-online.md). The programs are usually COBOL; the record layouts they share live in copybooks; the data lives in sequential datasets or VSAM, and increasingly in DB2. Understanding a mainframe system is mostly: read the copybooks (data), read the COBOL (rules), and read the JCL (what runs when).

The four divisions

Every COBOL program has four divisions, always in this order. Skim them in order and you know the program’s shape before its logic:

IDENTIFICATION DIVISION

Names the program (PROGRAM-ID). Sometimes carries author/date comments that hint at age and purpose.

ENVIRONMENT DIVISION

Maps the program’s logical files to physical datasets. The SELECT … ASSIGN TO … clauses in FILE-CONTROL tell you which files the program uses and whether they are sequential, indexed (VSAM KSDS), or relative. This is half of the “what data does it touch” answer.

DATA DIVISION

The layouts. Three sections matter:

  • FILE SECTION — an FD (file description) per file, each with its record layout (often a COPY of a copybook).
  • WORKING-STORAGE SECTION — the program’s variables, constants, flags, and tables. Business thresholds and magic numbers live here.
  • LINKAGE SECTION — parameters passed in from a caller (or from CICS/JCL PARM). This is the program’s input contract.

PROCEDURE DIVISION

The logic — organized into paragraphs and sections that are run with PERFORM. This is where the rules are; read it against the data model, not cold.

Level numbers, PIC, and USAGE

A COBOL field is described by a level number, a name, and a PICTURE (PIC) clause. Read three things per field: how it nests, its type, and how it is stored.

Level numbers show nesting. 01 is a top-level record; 05, 10, 15 nest under it (a group and its sub-fields). Two special levels:

  • 88 — a condition name: a named value test, e.g. 88 CLAIM-APPROVED VALUE 'A'. These are gold — they name business states in plain English. Harvest every 88.
  • 77 — a standalone scalar (no sub-fields).

PIC gives type and size:

PIC symbolMeans
9A numeric digit (PIC 9(5) = 5 digits)
XAny character (PIC X(30) = 30 chars)
AAlphabetic only
SSigned (leading S, e.g. S9(7))
VImplied decimal point (S9(7)V99 = 7 digits, 2 decimals, no stored dot)
Z, ,, ., $, -, /Edit characters — display formatting only, for report fields

USAGE gives physical storage — and this is where reverse-engineering goes wrong if ignored:

USAGEStorageNote
DISPLAY (default)One byte per digit/char, as textEasy to read raw
COMP-3 / PACKED-DECIMALPacked decimal — two digits per byte + sign nibbleExtremely common for money; raw bytes are unreadable without decoding
COMP / COMP-4 / BINARYBinary integer (2/4/8 bytes)Byte order matters
COMP-1 / COMP-2Single/double floating pointRare in business code

A PIC S9(7)V99 COMP-3 amount is 5 bytes of packed decimal representing a signed number with two implied decimals — not a 12-character string. Decode rules and the signed-overpunch trap are in references/data-model-extraction.md.

REDEFINES and OCCURS

Two clauses let one layout mean several things. Both are traps for automated extraction:

REDEFINES overlays a second layout on the same bytes. 05 FILLER PIC X(20) 05 PARSED REDEFINES FILLER … means those 20 bytes are read two ways depending on context. A field can be a date in one branch and a code in another. You must find which condition selects which view — that is a business rule, not just a layout note.

OCCURS makes an array/table: 05 MONTH-AMT PIC S9(7)V99 COMP-3 OCCURS 12. OCCURS … DEPENDING ON n makes it variable-length (the record size depends on a counter field), which means the layout is not fixed and offsets shift at runtime. Flag every OCCURS DEPENDING ON — it complicates any flat extract.

Copybooks: the real data model

A copybook is a shared fragment of DATA DIVISION code pulled in with COPY MEMBER.. It defines a record layout (or a set of constants) once and is reused by every program that touches that file. That makes copybooks the single best source of the data model — they are the schema the mainframe never wrote down as DDL.

Practical consequences for discovery:

  • One copybook is usually one file/table’s record. Inventory the copybooks first; they enumerate the entities.
  • The same copybook COPY’d into many programs is a dependency signal: those programs all share that record and likely that responsibility.
  • COPY … REPLACING substitutes text at copy time (e.g. prefixing field names). The effective layout differs from the raw copybook — expand it mentally before trusting field names.

PROCEDURE DIVISION verbs

The verbs that carry business meaning (as opposed to plumbing):

VerbMeaningDiscovery note
PERFORMCall a paragraph/section (optionally in a loop)The control flow; PERFORM … UNTIL is the main loop idiom
MOVECopy/convert data between fieldsWatch implicit type conversion and truncation
COMPUTE / ADD/SUBTRACT/MULTIPLY/DIVIDEArithmeticWhere money and eligibility math live
IF / EVALUATEBranch / case (EVALUATE = switch)EVALUATE often encodes a decision table
READ / WRITE / REWRITE / DELETEFile I/O (REWRITE = update)The CRUD verbs; check the file’s FD
CALLInvoke another programCross-program edges for the call graph
STRING / UNSTRING / INSPECTText build/parse/scanParsing rules, formatting
SORT / MERGEIn-program sortOften a whole batch step in one verb
GO TOUnconditional jumpLegacy spaghetti signal; trace carefully

Condition names (88 levels) turn cryptic tests into readable ones: IF CLAIM-APPROVED beats IF WS-STAT = 'A'. When you see them used, you have found named business states — put them straight into the rule catalog.

JCL

Job Control Language tells z/OS what programs to run, in what order, with which datasets. A JCL member is a job; a job has steps; each step runs a program (or a cataloged PROC). The three statement types:

  • //JOBNAME JOB … — the job card: name, accounting, class, priority.
  • //STEPnn EXEC PGM=… (or EXEC PROC=…) — a step running a program or procedure. PARM= passes a parameter string to the program (its LINKAGE).
  • //ddname DD … — a data definition: connects a program’s internal file name to a real dataset (DSN=), with a disposition (DISP=(status,normal,abnormal)), or inline data (DD *).

What to extract from JCL:

  • Step order and program calls — the batch flow within a job.
  • DD statements — every dataset a step reads or writes (DISP=SHR read-shared, DISP=OLD exclusive, DISP=(NEW,CATLG) creates). This is the file-usage matrix’s raw material.
  • COND / IF-THEN-ELSE — steps that run only if a prior step’s return code passes. This encodes error handling and conditional flow.
  • PROCs — cataloged, reusable JCL. A job that EXECs a PROC hides its real steps in the PROC member; expand it.
  • UtilitiesIEBGENER (copy), IDCAMS (VSAM admin), DFSORT/SYNCSORT (sort/filter, sometimes doing real business transforms in the sort control cards).

Datasets and VSAM

Mainframe “files” are datasets, named hierarchically (PROD.CLAIMS.MASTER). The kinds you will meet:

Sequential (PS) and partitioned (PDS/PDSE)

A PS is a flat sequential file. A PDS/PDSE is a container of members (like a folder of files) — source code and JCL usually live in PDS members.

VSAM — the indexed file family

VSAM is how the mainframe did keyed/indexed data before DB2. Three organizations:

VSAM typeFull nameAccess patternCOBOL sees it as
KSDSKey-Sequenced Data SetBy unique key (like a primary-key table)Indexed file
ESDSEntry-Sequenced Data SetIn insertion order (like an append log)Sequential file
RRDSRelative Record Data SetBy record number (like an array)Relative file

KSDS is the common one — treat a KSDS as a single-table keyed store; its record layout is the copybook, its key is in the SELECT … RECORD KEY. An alternate index (AIX) on a KSDS is a secondary index — a second access path worth noting as a query the business needed. VSAM clusters are defined and loaded with IDCAMS (DEFINE CLUSTER).

DB2 and IMS

Two database options coexist with VSAM:

DB2 for z/OS

Relational, accessed by embedded SQL in COBOL: EXEC SQL … END-EXEC, precompiled. DCLGEN generates a copybook-like host-variable declaration from a table. When you see EXEC SQL, the data model for those tables is real SQL — get the DDL or catalog (SYSIBM.SYSTABLES, SYSCOLUMNS) and you have an authoritative schema, no reverse-engineering needed.

IMS

A hierarchical database (segments in a parent/child tree) accessed by DL/I calls (CALL 'CBLTDLI' …) rather than SQL, plus IMS/DC for online transactions. Rarer in new discovery but present in the oldest systems. If you see CBLTDLI/PCB/PSB, you are in IMS and the data model is a hierarchy, not tables — model it as nested entities.

Schedulers and the batch cycle

Batch jobs do not run themselves. A schedulerControl-M, CA-7, or IBM TWS/OPC — triggers jobs on a clock and on dependencies (job B runs when job A ends OK and a file arrives). The scheduler definitions (not the JCL) hold the true nightly batch cycle: the order, the timing windows, and the “must finish before 6 AM” constraints that a migration must preserve. If you can get the scheduler export, it is worth more than any single program for understanding operational risk. Draw it as a job DAG — see references/mermaid-legacy-patterns.md.

Abends

A mainframe failure is an abend (abnormal end) with a system completion code. Two are worth recognizing during discovery because they reveal data assumptions:

  • S0C7 — data exception: arithmetic on a field that does not contain valid packed/numeric data. Almost always bad or uninitialized COMP-3 data. Frequent S0C7s in the history mean the data has dirty values the rules must tolerate.
  • S0C4 — protection/addressing exception: often a bad index, subscript, or OCCURS overrun. Signals table-size assumptions.

Abend history (from job logs) is a free source of edge cases for phase 5 test generation.

File-extension cheat sheet

In an exported repo, classify by extension (confirm by the first division/statement):

Extension(s)It is a…
.cbl, .cob, .cobolCOBOL program
.cpy, .cpybk, .copyCopybook (record layout / constants)
.jcl, .jobJCL job
.prc, .procCataloged JCL procedure
.pli, .pl1PL/I program (sibling language; similar role)
.asm, .mlcAssembler (HLASM) — low-level, rare but opaque
.dbrm, .bindDB2 bind artifacts
.sqlSQL DDL/DML
.bmsCICS map source (see references/cics-online.md)
.rex, .rexxREXX scripts (ops automation)

When extensions are absent, the first line decides it: IDENTIFICATION DIVISION → COBOL; //… JOB → JCL; a bare record layout starting with a 01 level → copybook; EXEC SQL blocks → embedded DB2.