Skip to content
PYD ENTERPRISES

COBOL, CICS & JCL

Decompile IBM z/OS and Micro Focus COBOL, byte for byte.

Copybooks expanded, storage laid out to the byte, CICS conversations modeled as state, JCL streams turned into dataset lineage. Then rules, not guesses.

LNACCR02.cbl · COPY expansionIBM Enterprise COBOL 6.4
41 WORKING-STORAGE SECTION.
42 01 WS-LOAN.
43 COPY LNREC REPLACING ==:PFX:== BY ==WS==.
↳ expands LOANS.COPYLIB(LNREC), :PFX: → WS
fieldofflenwhy
WS-LOAN-IDX(10)010char(10), KSDS key
WS-PRIN-BALS9(11)V99 COMP-310713 digits: (13+1)/2
WS-ANN-RATESV9(6) COMP-31746 digits: (6+1)/2, up
WS-PMT-CNTS9(4) COMP212halfword, 0 to 60
WS-PMT-HISTOCCURS 0 TO 602313 × n8 + 5 per entry

record length 23 to 803 bytes · depends on WS-PMT-CNT

Dependency graph explorer

Every job, transaction, program and dataset, connected.

Click a node to see what it uses and what uses it. Switch to downstream impact to see everything a copybook change touches, or upstream callers to find which jobs and transactions reach a program. Dynamic CALLs show every resolved candidate.

ENTRY POINTSPROGRAMSCALLED & COPIEDDATA STORESJOB LNDLY01JOB LNMTH01TRAN LNIQTRAN LNUPLNEXTR01LNACCR02LNGL01LNINQ01LNUPD01LNACCR03RTVAR01RTFIX01COPY LNRECCOPY LNCALCMAPSET LNINQSVSAM LN.MASTERLOANS.ACCR.WORKDB2 RATE_INDEXGDG ACCR.HISTGL.INTERFACE

Complete mainframe syntax

The constructs generic tools skip are the ones that hold the rules.

01 · COPYBOOKS

Expansion before parsing, provenance after.

COPY statements are expanded in compiler order, including nested copybooks and pseudo-text REPLACING such as ==:PFX:== BY ==WS==. Each expanded line remembers its member and original line, so a rule found inside LNCALC cites the copybook, and lists every program that includes it.

Procedure-division copybooks are common in older shops. PYD ENTERPRISES treats shared logic as one rule with many call sites, not as duplicate rules.

LOANS.COPYLIB(LNREC)COBOL
1 * LNREC: loan master record, 803 bytes max
2 05 :PFX:-LOAN-ID PIC X(10).
3 05 :PFX:-PRIN-BAL PIC S9(11)V99 COMP-3.
4 05 :PFX:-ANN-RATE PIC SV9(6) COMP-3.
5 05 :PFX:-PMT-CNT PIC S9(4) COMP.
6 05 :PFX:-PMT-HIST OCCURS 0 TO 60 TIMES
7 DEPENDING ON :PFX:-PMT-CNT.
8 10 :PFX:-PMT-DATE PIC 9(8).
9 10 :PFX:-PMT-AMT PIC S9(7)V99 COMP-3.
LNSTAT.cpyCOBOL
1 05 LN-STATUS-AREA PIC X(12).
2 05 LN-ACTIVE REDEFINES LN-STATUS-AREA.
3 10 LN-NEXT-DUE-DT PIC 9(8).
4 10 LN-DAYS-PAST-DUE PIC S9(5) COMP-3.
5 10 FILLER PIC X(01).
6 05 LN-CLOSED REDEFINES LN-STATUS-AREA.
7 10 LN-CLOSE-DT PIC 9(8).
8 10 LN-CLOSE-RSN PIC X(02).
9 88 LN-PAID-OFF VALUE 'PO'.
10 88 LN-CHARGED-OFF VALUE 'CO'.
11 10 FILLER PIC X(02).

02 · REDEFINES, ODO & COMP-3

Overlays resolved to offsets, not names.

LN-ACTIVE and LN-CLOSED share the same 12 bytes. LN-DAYS-PAST-DUE is S9(5) COMP-3, 3 bytes at offset 8, overlaying the same storage as LN-CLOSE-RSN and the first byte of the trailing FILLER.

Dataflow runs on bytes, so a write through one name is seen by reads through the other. PYD ENTERPRISES finds the discriminator that selects the variant and emits a JSON Schema oneOf; if no discriminator exists, the overlay is flagged.

03 · CICS & BMS

Pseudo-conversations become explicit state.

First entry (EIBCALEN = 0) sends the map and returns with TRANSID('LNIQ') and a COMMAREA. The next task receives the map and LINKs to the calculator. PYD ENTERPRISES models both tasks as states of one conversation.

BMS map fields (LOANIDI, ACCRO) become request and response properties; the LINKed COMMAREA becomes an OpenAPI operation with its own schema.

LNINQ01.cbl (excerpt)COBOL
1 PROCEDURE DIVISION.
2 IF EIBCALEN = 0
3 MOVE LOW-VALUES TO LNINQMO
4 EXEC CICS SEND MAP('LNINQM') MAPSET('LNINQS')
5 FROM(LNINQMO) ERASE
6 END-EXEC
7 EXEC CICS RETURN TRANSID('LNIQ')
8 COMMAREA(WS-COMMAREA)
9 LENGTH(LENGTH OF WS-COMMAREA)
10 END-EXEC
11 END-IF
12 MOVE DFHCOMMAREA TO WS-COMMAREA
13 EXEC CICS RECEIVE MAP('LNINQM') MAPSET('LNINQS')
14 INTO(LNINQMI) RESP(WS-RESP)
15 END-EXEC
16 MOVE LOANIDI TO CA-LOAN-ID
17 EXEC CICS LINK PROGRAM('LNACCR03')
18 COMMAREA(WS-ACCR-AREA)
19 END-EXEC
LOANS.JCL(LNDLY01)JCL
1//LNDLY01 JOB (LN01),'DAILY ACCRUAL',CLASS=A,MSGCLASS=X
2//EXTRACT EXEC PGM=LNEXTR01
3//LNMAST DD DSN=LOANS.LN.MASTER,DISP=SHR
4//ACCRWK DD DSN=LOANS.ACCR.WORK,DISP=OLD
5//ACCRUE EXEC PGM=LNACCR02,COND=(4,LT,EXTRACT)
6//ACCRWK DD DSN=LOANS.ACCR.WORK,DISP=SHR
7//LNMAST DD DSN=LOANS.LN.MASTER,DISP=SHR
8//LNHIST DD DSN=LOANS.ACCR.HIST(+1),DISP=(NEW,CATLG,DELETE),
9// SPACE=(CYL,(50,10)),DCB=(RECFM=FB,LRECL=120)
10//GLPOST EXEC PGM=LNGL01,COND=((8,LE,EXTRACT),(4,LT,ACCRUE))
11//LNHIST DD DSN=LOANS.ACCR.HIST(+1),DISP=SHR
12//GLOUT DD DSN=GL.POSTING.LOANS,DISP=MOD

04 · JCL & DATASET LINEAGE

COND codes read the way z/OS reads them.

A COND test bypasses the step when it is true. COND=(4,LT,EXTRACT) skips ACCRUE when 4 is less than EXTRACT's return code, so ACCRUE runs only when EXTRACT ends with RC 4 or lower. GLPOST needs EXTRACT below 8 and ACCRUE at 4 or lower.

DD statements bind each program's files to datasets, including GDG generations, so lineage runs from VSAM master through the work file to the general ledger posting file.

Dead code & unreachable paragraphs

Prune before you extract.

Thirty years of change requests leave code nobody runs. Extracting rules from it inflates scope and misleads the build team.

  1. 01

    Build the full CFG

    PERFORM THRU ranges, fall-through between paragraphs, GO TO DEPENDING ON targets and every ALTER that can change a GO TO are modeled as edges, so reachability is computed on the real graph rather than on paragraph names.

  2. 02

    Seed from real entry points

    Reachability starts at JCL EXEC PGM steps, CICS transactions in your CSD extract, and CALL and LINK targets. A program nobody invokes is reported as an orphan, not deleted.

  3. 03

    Fold constant conditions

    Switches set once from a JCL PARM or a constant VALUE clause are propagated. A branch on an 88-level that can never be true under the supplied PARMs is marked conditionally dead, with the PARM that kills it.

  4. 04

    Classify, never delete

    Unreachable paragraphs, dead stores and redundant MOVEs are excluded from rule extraction and listed with line ranges. Your source is never modified.

Pruning report · LOANS412 paragraphs excluded
  • dead

    9000-OLD-RATE-TABLE unreachable

    LNACCR02.cbl:3310-3488

    No PERFORM, GO TO or fall-through reaches it since CR 3120 (1997).

  • cond

    IF WS-RUN-MODE = 'Q' never true

    LNEXTR01.cbl:402-517

    WS-RUN-MODE set only from PARM; jobs pass 'D' and 'M'.

  • alter

    ALTER 1500-DISPATCH TO PROCEED TO 1580-RETRY

    LNGL01.cbl:211

    Modeled as a two-state switch; both targets kept reachable.

  • dead

    Dead store to WS-TEMP-BAL

    LNACCR02.cbl:1206

    Overwritten at 1219 before any read.

  • orphan

    Program LNPURG02 has no callers

    LNPURG02.cbl

    Not in any JCL, CSD or CALL in this scan; confirm with operations.

Source is never modified. Exclusions are reviewable.

“It resolved COMP-3 fields and nested REDEFINES that every generic AI tool we tried got wrong.”
Mainframe technical lead · Tier 2 US commercial bank

Dialect coverage

Two COBOL front ends, one symbol graph.

ConstructIBM Enterprise COBOL (z/OS)Micro Focus COBOL
COPY, COPY REPLACING, nested copybooksFullFull
REDEFINES, RENAMES (66), OCCURS DEPENDING ONFullFull
COMP, COMP-3, COMP-5, DISPLAY SIGN SEPARATEFullFull
PERFORM THRU, GO TO DEPENDING ON, ALTERFullFull
EXEC CICS (incl. BMS SEND/RECEIVE MAP, LINK, XCTL)FullFull (with CICS option)
EXEC SQL (DB2 static and dynamic)FullFull
IMS DL/I calls (CBLTDLI, PCB masks)FullNot applicable
JCL, cataloged PROCs, symbolic substitutionFullVia JCL import
Micro Focus directives ($SET), Net Express extensionsNot applicableFull

Patterns these constructs create, and how they map to modern designs, are documented in the legacy anti-patterns catalog.

FAQ

Mainframe questions.

Migrating off COBOL? Read the COBOL to Spring Boot guide.

How does PYD ENTERPRISES handle copybooks with the same name in different libraries?

You supply the library concatenation order your compile step uses (Endevor processor groups or the SYSLIB DD), and PYD ENTERPRISES resolves each COPY to the first library containing the member, exactly as the compiler does. Every expanded line keeps a reference to the copybook member and line it came from.

Does it compute storage offsets the way the compiler does?

Yes. Lengths follow the usage rules: DISPLAY one byte per digit, COMP-3 (digits + 1) / 2 rounded up, binary halfword or fullword by digit count. OCCURS DEPENDING ON tables are modeled with their minimum and maximum size, and SYNCHRONIZED slack bytes are inserted when the clause is present.

Can it follow a dynamic CALL through a variable?

When the variable is set from literals in the same program, PYD ENTERPRISES resolves the full candidate set and records the condition that picks each one. When the value comes from a file or a table, the CALL is listed as unresolved with whatever candidates exist, and rules downstream of it are flagged for review.

How are CICS pseudo-conversational programs modeled?

As a state machine across task boundaries. EIBCALEN checks, RETURN TRANSID with a COMMAREA and the fields carried in it become explicit states and transitions, so the extracted interface describes the whole conversation, not only one task.

What about Micro Focus specific syntax?

The Micro Focus front end honors $SET directives such as DIALECT and SOURCEFORMAT, free-format source and Net Express extensions. Choose the dialect per source path in scan.yaml.

Point it at your copybook library.

Run PYD ENTERPRISES on 100,000 lines of COBOL or Java in your private VPC and review OpenAPI specs and DMN tables tomorrow.